diff --git a/apps/lutris/README.md b/apps/lutris/README.md index c75d567..cf3eb1a 100644 --- a/apps/lutris/README.md +++ b/apps/lutris/README.md @@ -1,45 +1,64 @@ # Lutris scripts + ## `preloader.sh` + Execute multiple scripts in a folder (default is `./preloader`), usually useful for Lutris Pre-launch/Post-exit script -+ Logging is enabled by default, but can be disabled by changing DEBUG to 0 in script source (`DEBUG=0`) -> This script will execute scripts in **current working directory** *(where `preloader.sh` is executed)*, so for example if a script need a file called `nightmare`, and preloader.sh is in `~`, **put the file in `~`** *instead of `~/preloader/`* + +- Logging is enabled by default, but can be disabled by changing DEBUG to 0 in script source (`DEBUG=0`) + > This script will execute scripts in **current working directory** _(where `preloader.sh` is executed)_, so for example if a script need a file called `nightmare`, and preloader.sh is in `~`, **put the file in `~`** _instead of `~/preloader/`_ + ### Installation -+ To download `preloader.sh` itself: + +- To download `preloader.sh` itself: + ```sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/apps/Lutris/preloader.sh chmod +x preloader.sh ``` -+ After that, copy/move this script to the game prefix you want to use, then in Lutris: - - Set pre-launch script in Lutris to where `preloader.sh` is located. - - Disable **Wait for pre-launch script completion** (optional) -+ **IMPORTANT**: Now, to add pre-launch script, instead of setting them in Lutris, add them to `./preloader` (or the folder you specified). -+ Enjoy :L +- After that, copy/move this script to the game prefix you want to use, then in Lutris: + + - Set pre-launch script in Lutris to where `preloader.sh` is located. + - Disable **Wait for pre-launch script completion** (optional) + +- **IMPORTANT**: Now, to add pre-launch script, instead of setting them in Lutris, add them to `./preloader` (or the folder you specified). +- Enjoy :L ### Documentation + There are environment variables to control how preloader.sh work: -+ `PRELOADER_PATH=./preloader`: Path to preload scripts. -+ `PRELOADER_DEBUG=0`: Enable debug (1) or disable it (0) + +- `PRELOADER_PATH=./preloader`: Path to preload scripts. +- `PRELOADER_DEBUG=0`: Enable debug (1) or disable it (0) ## `discord_rpc.sh` + Launch `winediscordrpcbridge.exe`, to be able to get Discord Rich Presence on Wine applications on the specified prefix. ### Installation -+ To install you must have [`winediscordrpcbridge.exe`](https://github.com/0e4ef622/wine-discord-ipc-bridge/) present, if not you can download latest version by executing + +- To install you must have [`winediscordrpcbridge.exe`](https://github.com/0e4ef622/wine-discord-ipc-bridge/) present, if not you can download latest version by executing + ```sh curl -OL https://github.com/0e4ef622/wine-discord-ipc-bridge/releases/latest/download/winediscordipcbridge.exe ``` + or use my build (latest commit: `master/9d56418`) + ```sh curl -OL https://github.com/teppyboy/releases/releases/download/git%2B0e4ef622%2Fwine-discord-ipc-bridge%2Bmaster%2F9d56418/winediscordipcbridge.exe ``` -+ Then to download `discord_rpc.sh` itself: + +- Then to download `discord_rpc.sh` itself: + ```sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/apps/Lutris/discord_rpc.sh chmod +x discord_rpc.sh ``` -+ After that, copy/move this script to the game prefix you want to use, then in Lutris: - - Set pre-launch script in Lutris to where `discord_rpc.sh` is located. - - Disable **Wait for pre-launch script completion** -+ Enjoy :L +- After that, copy/move this script to the game prefix you want to use, then in Lutris: + + - Set pre-launch script in Lutris to where `discord_rpc.sh` is located. + - Disable **Wait for pre-launch script completion** + +- Enjoy :L diff --git a/apps/ws-scrcpy/README.md b/apps/ws-scrcpy/README.md index 9e3c03e..bcca111 100644 --- a/apps/ws-scrcpy/README.md +++ b/apps/ws-scrcpy/README.md @@ -4,19 +4,19 @@ ### Notes -+ **YOU NEED TO HAVE WS-SCRCPY INSTALLED, ALONG WITH ROOT ACCESS AND DEPENDENCIES** -+ ~~YOU ALSO NEED TO OPEN ADB WIRELESS IN DEVELOPER SETTINGS FOR THIS TO WORK~~ (The script can use `su` to start ADB wireless now) -+ You need to grant Termux:API full Location permission and set to "Always" (Foreground mode will not work correctly) -+ Rootless mode is available, although it **will not** work in most cases. -+ Dependencies: `root-repo` `tsu` `moreutils` `build-essential` `nodejs` `python3` `android-tools` `git` `termux-api` +- **YOU NEED TO HAVE WS-SCRCPY INSTALLED, ALONG WITH ROOT ACCESS AND DEPENDENCIES** +- ~~YOU ALSO NEED TO OPEN ADB WIRELESS IN DEVELOPER SETTINGS FOR THIS TO WORK~~ (The script can use `su` to start ADB wireless now) +- You need to grant Termux:API full Location permission and set to "Always" (Foreground mode will not work correctly) +- Rootless mode is available, although it **will not** work in most cases. +- Dependencies: `root-repo` `tsu` `moreutils` `build-essential` `nodejs` `python3` `android-tools` `git` `termux-api` > Or execute `pkg install root-repo tsu moreutils build-essential nodejs python3 android-tools git termux-api` -+ You also need to downgrade npm to version 6 to fix Termux problem: `npm install -g npm@6` +- You also need to downgrade npm to version 6 to fix Termux problem: `npm install -g npm@6` > Please ignore the vulnerability message, if you care about it then please don't use this script. -+ Download ws-scrcpy-launcher.py: +- Download ws-scrcpy-launcher.py: ```bash curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/Apps/ws-scrcpy/ws-scrcpy-launcher.py @@ -25,7 +25,7 @@ chmod +x ws-scrcpy-launcher.py > Execute `./ws-scrcpy-launcher.py` to launch ws-scrcpy with scrcpy server for local device. -+ Full script for lazy people (including install ws-scrcpy steps): +- Full script for lazy people (including install ws-scrcpy steps): ```bash pkg update @@ -41,6 +41,6 @@ curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/Apps/ws-scrcpy/ws-scrcp chmod +x ws-scrcpy-launcher.py ``` -+ The script will tell you to wait for ws-scrcpy to start, and when it starts it'll show the started message with the ip address and the port to access using browsers +- The script will tell you to wait for ws-scrcpy to start, and when it starts it'll show the started message with the ip address and the port to access using browsers > You need to use `adb pair` to pair termux with your device adb server, then you can launch ws-scrcpy as explained above. diff --git a/games/aov/README.md b/games/aov/README.md deleted file mode 100644 index a2a3411..0000000 --- a/games/aov/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Scripts for Arena of Valor -Scripts I created for this game, thats it. (Not cheating scripts in-game tho) -## Scripts -+ [AWC_AutoSpin.sh](./AWC_AutoSpin.sh) - Auto spin the wheel in AWC website (Works in Vietnamese AOV only, other region need to tweak some string into their language) diff --git a/games/aov/awc_autospin.js b/games/aov/awc_autospin.js deleted file mode 100644 index 1ba9e3f..0000000 --- a/games/aov/awc_autospin.js +++ /dev/null @@ -1,114 +0,0 @@ -// Fetch jQuery -await fetch("https://code.jquery.com/jquery-3.6.0.min.js").then(x => x.text()).then(y => eval(y)) -// Wait for jQuery to be loaded. -{ - // From https://stackoverflow.com/a/53914092 - class ClassWatcher { - - constructor(targetNode, classToWatch, classAddedCallback, classRemovedCallback) { - this.targetNode = targetNode - this.classToWatch = classToWatch - this.classAddedCallback = classAddedCallback - this.classRemovedCallback = classRemovedCallback - this.observer = null - this.lastClassState = targetNode.classList.contains(this.classToWatch) - - this.init() - } - - init() { - this.observer = new MutationObserver(this.mutationCallback) - this.observe() - } - - observe() { - this.observer.observe(this.targetNode, { attributes: true }) - } - - disconnect() { - this.observer.disconnect() - } - - mutationCallback = mutationsList => { - for(let mutation of mutationsList) { - if (mutation.type === 'attributes' && mutation.attributeName === 'class') { - let currentClassState = mutation.target.classList.contains(this.classToWatch) - if(this.lastClassState !== currentClassState) { - this.lastClassState = currentClassState - if(currentClassState) { - this.classAddedCallback() - } - else { - this.classRemovedCallback() - } - } - } - } - } - } - - var disableChest = false - function clickFirstButtonByClassName(className) { - let btn = document.getElementsByClassName(className)[0] - if (!(typeof btn === "undefined")) { - btn.dispatchEvent(new MouseEvent("click")); - } - } - // Click the spin button - function spin() { - clickFirstButtonByClassName("wheel__main--note") - if (!disableChest) { - clickFirstButtonByClassName("chest") - } - } - - function pickCard() { - let teams = document.getElementsByClassName("popup-draw__card") - for (let i = 0; i < 3; i++) { - teams[i].dispatchEvent(new MouseEvent("click")); - } - setTimeout(() => jQuery(".ReactModal__Overlay").trigger("click"), 2000) - } - // Check for dialog message then close - function closeSwalDialog() { - clickFirstButtonByClassName("swal2-close") - if (document.getElementsByClassName("swal2-close").length > 0) { - setTimeout(closeSwalDialog, 100); - } - } - - function Swal2Dialog() { - if (document.getElementsByClassName("popup-draw__card").length > 0) { - pickCard() - } - else { - let swal2msg = document.getElementsByClassName("popup-alert__message") - if (swal2msg.length > 0) { - console.log(swal2msg[0].innerHTML) - if (swal2msg[0].innerHTML == "Đã đạt đến giới hạn Rương đếm ngược hàng ngày") { - disableChest = true - } - else if (swal2msg[0].innerHTML == "Bạn đã hết lượt quay trong ngày") { - closeAutoFarm() - } - } - } - closeSwalDialog() - } - - // Watch for SweetAlert 2 - let swal2Watcher = new ClassWatcher(document.body, 'swal2-shown', Swal2Dialog, spin); - - function closeAutoFarm() { - swal2Watcher.disconnect() - } - - spin() - // Disable window change - jQuery("window").off("mouseup") - jQuery("document").off("visibilitychange") - // Remove video player (so it isnt annoying to me and save CPU by a lot) - Array.from(document.getElementsByTagName("iframe")).forEach((iframe) => { - iframe.remove() - }) -} diff --git a/games/cities_skylines/README.md b/games/cities_skylines/README.md index 3f30038..09a0bd9 100644 --- a/games/cities_skylines/README.md +++ b/games/cities_skylines/README.md @@ -1,9 +1,12 @@ # Scripts for [Cities: Skylines](https://www.citiesskylines.com/) + Scripts I created for this game, thats it. ### Scripts -+ [NotParadoxLauncher_Win_Proton.sh](./NotParadoxLauncher_Win_Proton.sh) - Install [Not Paradox Launcher] to Cities: Skylines (Windows version running in Linux using Proton) -+ [Win_Proton_dowser_patch.sh](./Win_Proton_dowser_patch.sh) - Replace dowser.exe with Cities.exe so the game can launch without using bloated launcher (for CS Windows version running in Proton) + +- [NotParadoxLauncher_Win_Proton.sh](./NotParadoxLauncher_Win_Proton.sh) - Install [Not Paradox Launcher] to Cities: Skylines (Windows version running in Linux using Proton) +- [Win_Proton_dowser_patch.sh](./Win_Proton_dowser_patch.sh) - Replace dowser.exe with Cities.exe so the game can launch without using bloated launcher (for CS Windows version running in Proton) #### Note -These script I created for my friend because I don't play this game, so if it has any problem then feel free to open a issue, thanks. \ No newline at end of file + +These script I created for my friend because I don't play this game, so if it has any problem then feel free to open a issue, thanks. diff --git a/games/lol/linux/README.md b/games/lol/linux/README.md index f27f622..847bf35 100644 --- a/games/lol/linux/README.md +++ b/games/lol/linux/README.md @@ -1,58 +1,71 @@ # leagueoflinux scripts + ## `sulaunchhelper2.sh` + This script is a wrapper for `sulaunchhelper2.py` for use with Lutris pre-game launch script. + ### Installation + > This script no longer wraps `syscall_check.sh`, if you need to execute that script alongside this one, I recommend you to take a look at [preloader.sh](../../../apps/Lutris#preloadersh) -+ To install you must have `sulaunchhelper2.py` present, if not you can execute these to quickly download them (to current directory): +- To install you must have `sulaunchhelper2.py` present, if not you can execute these to quickly download them (to current directory): + ```sh curl -OL https://raw.githubusercontent.com/CakeTheLiar/launchhelper/master/sulaunchhelper2.py chmod +x sulaunchhelper2.py ``` -+ Then to download `sulaunchhelper2.sh` itself: + +- Then to download `sulaunchhelper2.sh` itself: + ```sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/games/LoL/linux/sulaunchhelper2.sh chmod +x sulaunchhelper2.sh ``` -+ After that, copy all these files to the game prefix you want to use, then in Lutris: - - Set pre-launch script in Lutris to where `sulaunchhelper2.sh` is located. - - Disable **Wait for pre-launch script completion** - - Enable **Disable Lutris Runtime** -> Failure to do above steps will result in Zenity can't show necessary messages dialog so LoL UI can't launch properly. -+ Enjoy your LoL experience :P + +- After that, copy all these files to the game prefix you want to use, then in Lutris: - Set pre-launch script in Lutris to where `sulaunchhelper2.sh` is located. - Disable **Wait for pre-launch script completion** - Enable **Disable Lutris Runtime** + > Failure to do above steps will result in Zenity can't show necessary messages dialog so LoL UI can't launch properly. +- Enjoy your LoL experience :P ## [`discord_rpc.sh`](../../../apps/Lutris#discord_rpcsh) -+ This script will bridge Discord RPC from LoL prefix to your linux Discord. -> Note: The script in current directory [`discord_rpc.sh`](./discord_rpc.sh) is modified from the script mentioned above to work properly with `sulaunchhelper2.sh`, -the installation is the same **except** when installing the script itself, execute this instead: + +- This script will bridge Discord RPC from LoL prefix to your linux Discord. + > Note: The script in current directory [`discord_rpc.sh`](./discord_rpc.sh) is modified from the script mentioned above to work properly with `sulaunchhelper2.sh`, + > the installation is the same **except** when installing the script itself, execute this instead: + ```sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/games/LoL/linux/discord_rpc.sh chmod +x discord_rpc.sh ``` + ## Deprecated ### `garena_wrapper.sh` + > Garena no longer owns LoL so to play LoL you need to use Rito Client. This script automates the launching of [lol.py](https://github.com/nhubaotruong/league-of-legends-linux-garena-script) (LoL in Garena client) so you don't have to manually do it ;) + #### Installation + > This script no longer wraps `syscall_check.sh`, if you need to execute that script alongside this one, I recommend you to take a look at [`preloader.sh`](../../../apps/Lutris#preloadersh) -If you plan to use `preloader.sh` then I **highly recommend you** to **disable logging**, because **lol.py and `preloader.sh` will log your token to ./preloader/preloader_garena_wrapper.sh.log if you keep it enabled**, hence your account may get compromised. +> If you plan to use `preloader.sh` then I **highly recommend you** to **disable logging**, because **lol.py and `preloader.sh` will log your token to ./preloader/preloader_garena_wrapper.sh.log if you keep it enabled**, hence your account may get compromised. You need to follow steps in `lol.py` repository to properly config your LoL prefix. -+ To install you must have `lol.py` present, if not you can execute these to quickly download them (to current directory): + +- To install you must have `lol.py` present, if not you can execute these to quickly download them (to current directory): + ```sh curl -OL https://raw.githubusercontent.com/nhubaotruong/league-of-legends-linux-garena-script/main/lol.py chmod +x lol.py ``` -+ Then to download `garena_wrapper.sh` itself: + +- Then to download `garena_wrapper.sh` itself: + ```sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/games/LoL/linux/garena_wrapper.sh chmod +x garena_wrapper.sh ``` -+ After that, copy all these files to the game prefix you want to use, then in Lutris: - - Set pre-launch script in Lutris to where `garena_wrapper.sh` is located. - - Disable **Wait for pre-launch script completion** - - Enable **Disable Lutris Runtime** -> Failure to do above steps will result in Zenity can't show necessary messages dialog so LoL UI may not launch properly (it'll still launch if you use `sulaunchhelper2.sh` and have installed it correctly). -+ Enjoy your Garena LoL experience :P \ No newline at end of file + +- After that, copy all these files to the game prefix you want to use, then in Lutris: - Set pre-launch script in Lutris to where `garena_wrapper.sh` is located. - Disable **Wait for pre-launch script completion** - Enable **Disable Lutris Runtime** + > Failure to do above steps will result in Zenity can't show necessary messages dialog so LoL UI may not launch properly (it'll still launch if you use `sulaunchhelper2.sh` and have installed it correctly). +- Enjoy your Garena LoL experience :P diff --git a/userscripts/anonyviet-skip-wait.user.js b/userscripts/anonyviet-skip-wait.user.js index 2a49aeb..bea3bc0 100644 --- a/userscripts/anonyviet-skip-wait.user.js +++ b/userscripts/anonyviet-skip-wait.user.js @@ -12,12 +12,16 @@ // @downloadURL https://gitlab.com/tretrauit/scripts/-/raw/main/userscripts/anonyviet-skip-wait.user.js // ==/UserScript== -const REDIRECT_PAGE = "https://anonyviet.com/tieptucdentrangmoi/?url=" +const REDIRECT_PAGE = "https://anonyviet.com/tieptucdentrangmoi/?url="; for (const element of document.getElementsByTagName("a")) { - try { - if (element.getAttribute("href").startsWith(REDIRECT_PAGE)) { - element.setAttribute("href", decodeURIComponent(element.getAttribute("href").substring(REDIRECT_PAGE.length))) - } - } catch (_) { + try { + if (element.getAttribute("href").startsWith(REDIRECT_PAGE)) { + element.setAttribute( + "href", + decodeURIComponent( + element.getAttribute("href").substring(REDIRECT_PAGE.length), + ), + ); } + } catch (_) {} } diff --git a/userscripts/genshin-concert2022-wallpaper-mode.user.js b/userscripts/genshin-concert2022-wallpaper-mode.user.js index 14aab92..0b2c35a 100644 --- a/userscripts/genshin-concert2022-wallpaper-mode.user.js +++ b/userscripts/genshin-concert2022-wallpaper-mode.user.js @@ -13,16 +13,20 @@ // ==/UserScript== setTimeout(() => { - const header = document.querySelector(".src-components-common-TopBar-assets-__pc_---top---uiHfPh"); + const header = document.querySelector( + ".src-components-common-TopBar-assets-__pc_---top---uiHfPh", + ); if (header != null) { - header.remove() - console.log("Removed header") + header.remove(); + console.log("Removed header"); } setTimeout(() => { - const watermark = document.querySelector(".src-components-pages-assets-__kv_---kv-slogan---IBwwuz.kv-slogan"); + const watermark = document.querySelector( + ".src-components-pages-assets-__kv_---kv-slogan---IBwwuz.kv-slogan", + ); if (watermark != null) { - watermark.remove() - console.log("Removed watermark") + watermark.remove(); + console.log("Removed watermark"); } }, 5000); }, 5000); diff --git a/userscripts/hidemy.name-free-ipport-export.user.js b/userscripts/hidemy.name-free-ipport-export.user.js index 8453cf8..91eb0bb 100644 --- a/userscripts/hidemy.name-free-ipport-export.user.js +++ b/userscripts/hidemy.name-free-ipport-export.user.js @@ -12,25 +12,27 @@ // @downloadURL https://gitlab.com/tretrauit/scripts/-/raw/main/userscripts/hidemy.name-free-ipport-export.user.js // ==/UserScript== -setTimeout(function() { - const tblContent = document.getElementsByClassName("table_block")[0].getElementsByTagName("tbody")[0].children +setTimeout(function () { + const tblContent = document + .getElementsByClassName("table_block")[0] + .getElementsByTagName("tbody")[0].children; - // Replace the export IP:Port button - const btns = document.getElementsByClassName("export")[0] - const exportBtn = btns.children[0] - const fakeExportBtn = exportBtn.cloneNode(true) - fakeExportBtn.removeAttribute("href") - fakeExportBtn.addEventListener("click", () => { - var proxyStr = "" - for (let proxyContent of tblContent) { - const proxyContentChildren = proxyContent.children - const proxyIp = proxyContentChildren[0].innerHTML - const proxyPort = proxyContentChildren[1].innerHTML - proxyStr += proxyIp + ":" + proxyPort + "\n" - } - navigator.clipboard.writeText(proxyStr) - alert("Copied IP:Port list to clipboard.") - }) - exportBtn.remove() - btns.prepend(fakeExportBtn) + // Replace the export IP:Port button + const btns = document.getElementsByClassName("export")[0]; + const exportBtn = btns.children[0]; + const fakeExportBtn = exportBtn.cloneNode(true); + fakeExportBtn.removeAttribute("href"); + fakeExportBtn.addEventListener("click", () => { + var proxyStr = ""; + for (let proxyContent of tblContent) { + const proxyContentChildren = proxyContent.children; + const proxyIp = proxyContentChildren[0].innerHTML; + const proxyPort = proxyContentChildren[1].innerHTML; + proxyStr += proxyIp + ":" + proxyPort + "\n"; + } + navigator.clipboard.writeText(proxyStr); + alert("Copied IP:Port list to clipboard."); + }); + exportBtn.remove(); + btns.prepend(fakeExportBtn); }, 5000); diff --git a/userscripts/kgvn-8thang5-autofarm.user.js b/userscripts/kgvn-8thang5-autofarm.user.js index 2647f16..92ab9fd 100644 --- a/userscripts/kgvn-8thang5-autofarm.user.js +++ b/userscripts/kgvn-8thang5-autofarm.user.js @@ -14,81 +14,88 @@ // ==/UserScript== function init() { - const chest = document.getElementsByClassName("chest")[0] - const chestStatus = document.getElementsByClassName("chest__btn btn")[0] - const openWheelBtn = document.getElementsByClassName("wheel__btn")[0] - const upgradeBtn = document.getElementsByClassName("card__upgrade")[0] - // Has string characters need to be removed first. - const requiredScore = document.getElementsByClassName("card__note")[0].getElementsByTagName("strong")[0] - const currentScore = document.getElementsByClassName("card__data")[0].getElementsByTagName("span")[1] + const chest = document.getElementsByClassName("chest")[0]; + const chestStatus = document.getElementsByClassName("chest__btn btn")[0]; + const openWheelBtn = document.getElementsByClassName("wheel__btn")[0]; + const upgradeBtn = document.getElementsByClassName("card__upgrade")[0]; + // Has string characters need to be removed first. + const requiredScore = document + .getElementsByClassName("card__note")[0] + .getElementsByTagName("strong")[0]; + const currentScore = document + .getElementsByClassName("card__data")[0] + .getElementsByTagName("span")[1]; - function toInt(str) { - return parseInt(str.replace(/[^0-9]/g, '')) + function toInt(str) { + return parseInt(str.replace(/[^0-9]/g, "")); + } + + function upgradeRank() { + if (toInt(currentScore.innerHTML) >= toInt(requiredScore.innerHTML)) { + upgradeBtn.click(); } + } - function upgradeRank() { - if (toInt(currentScore.innerHTML) >= toInt(requiredScore.innerHTML)) { - upgradeBtn.click() + function receiveRankReward() { + const rewards = document.getElementsByClassName("milestone available"); + for (const reward of rewards) { + if (reward.className.includes("claimed")) { + continue; + } + reward.click(); + } + } + + function spinWheel() { + const spinBtn = document.getElementsByClassName("popup-wheel__btn")[0]; + const spinLeft = spinBtn.children[1].getElementsByTagName("strong")[0]; + function doSpin() { + spinBtn.click(); + setTimeout(() => { + if (parseInt(spinLeft.innerHTML) > 0) { + setTimeout(doSpin, 1000); } + }, 3000); } + doSpin(); + const closeBtn = document.getElementsByClassName("close")[0]; + closeBtn.click(); + } - function receiveRankReward() { - const rewards = document.getElementsByClassName("milestone available") - for (const reward of rewards) { - if (reward.className.includes("claimed")) { - continue - } - reward.click() - } + function wheel() { + if ( + !openWheelBtn.className.includes("animate__tada") || + document.getElementById("wheel") != null + ) { + return; } + console.log("click chest"); + openWheelBtn.click(); + setTimeout(spinWheel, 1000); + } - function spinWheel() { - const spinBtn = document.getElementsByClassName("popup-wheel__btn")[0] - const spinLeft = spinBtn.children[1].getElementsByTagName("strong")[0] - function doSpin() { - spinBtn.click() - setTimeout(() => { - if (parseInt(spinLeft.innerHTML) > 0) { - setTimeout(doSpin, 1000) - } - }, 3000) - } - doSpin() - const closeBtn = document.getElementsByClassName("close")[0] - closeBtn.click() + function receiveScore() { + if (chestStatus.innerHTML === "Nhận") { + chest.click(); } + } - function wheel() { - if (!openWheelBtn.className.includes("animate__tada") || document.getElementById("wheel") != null) { - return - } - console.log("click chest") - openWheelBtn.click() - setTimeout(spinWheel, 1000) + setInterval(() => { + if ((element = document.getElementsByClassName("swal2-close")[0])) { + element.click(); } + }, 100); - function receiveScore() { - if (chestStatus.innerHTML === "Nhận") { - chest.click() - } - } - - setInterval(() => { - if (element = document.getElementsByClassName("swal2-close")[0]) { - element.click() - } - }, 100); - - function loop() { - receiveScore() - upgradeRank() - receiveRankReward() - setTimeout(wheel, 500) - setTimeout(loop, 1000) - } - loop() + function loop() { + receiveScore(); + upgradeRank(); + receiveRankReward(); + setTimeout(wheel, 500); + setTimeout(loop, 1000); + } + loop(); } -setTimeout(init, 5000) +setTimeout(init, 5000); -console.warn("[8thang5 - Auto farm] Successfully loaded") -console.log("Made by @tretrauit under MIT License") +console.warn("[8thang5 - Auto farm] Successfully loaded"); +console.log("Made by @tretrauit under MIT License"); diff --git a/userscripts/messenger-dynamic-sidebar.user.js b/userscripts/messenger-dynamic-sidebar.user.js index 72c0654..bbbaca0 100644 --- a/userscripts/messenger-dynamic-sidebar.user.js +++ b/userscripts/messenger-dynamic-sidebar.user.js @@ -13,65 +13,69 @@ // ==/UserScript== function injectCSS(css) { - const style = document.createElement('style'); + const style = document.createElement("style"); style.appendChild(document.createTextNode(css)); document.head.appendChild(style); } function findElement(tag, properties) { - const elements = document.querySelectorAll(tag); - elementLoop: - for (const element of elements) { - for (const [key, value] of Object.entries(properties)) { - if (element.getAttribute(key) != value) { - continue elementLoop; - } - } - return element; + const elements = document.querySelectorAll(tag); + elementLoop: for (const element of elements) { + for (const [key, value] of Object.entries(properties)) { + if (element.getAttribute(key) != value) { + continue elementLoop; + } } + return element; + } } function getAncestor(element, level) { - if (element == null) { - return null; - } - for (let i = 0; i < level; i++) { - element = element.parentNode; - } - return element; + if (element == null) { + return null; + } + for (let i = 0; i < level; i++) { + element = element.parentNode; + } + return element; } console.log("Scanning class for components..."); // Search box -let searchBox = findElement("input", {"aria-autocomplete": "list"}); +let searchBox = findElement("input", { "aria-autocomplete": "list" }); if (searchBox == null) { - console.warn("Failed to get searchBox element."); - throw new Error(); + console.warn("Failed to get searchBox element."); + throw new Error(); } searchBox = getAncestor(searchBox, 7); // Header & Text header -let textHeader = findElement("span", {"style": "line-height: var(--base-line-clamp-line-height); --base-line-clamp-line-height:28px;"}); +let textHeader = findElement("span", { + style: + "line-height: var(--base-line-clamp-line-height); --base-line-clamp-line-height:28px;", +}); let header; if (textHeader == null) { - console.warn("Failed to get textHeader element."); - throw new Error(); + console.warn("Failed to get textHeader element."); + throw new Error(); } header = getAncestor(textHeader, 7); textHeader = textHeader.childNodes[0]; // Unread indicator -let unreadIndicator = findElement("span", {"data-visualcompletion": "ignore"}); +let unreadIndicator = findElement("span", { + "data-visualcompletion": "ignore", +}); // Action bar -let actionBar = findElement("div", {"aria-expanded": "false"}); +let actionBar = findElement("div", { "aria-expanded": "false" }); if (actionBar == null) { - console.warn("Failed to get actionBar element."); - throw new Error(); + console.warn("Failed to get actionBar element."); + throw new Error(); } actionBar = actionBar.parentNode; // Chats -let chats = findElement("div", {"aria-label": "Chats"}); +let chats = findElement("div", { "aria-label": "Chats" }); if (chats == null) { - console.warn("Failed to get chats element."); - throw new Error(); + console.warn("Failed to get chats element."); + throw new Error(); } chats = chats.parentNode; // Print elements diff --git a/userscripts/tiktok.user.js b/userscripts/tiktok.user.js index b915277..21baf1e 100644 --- a/userscripts/tiktok.user.js +++ b/userscripts/tiktok.user.js @@ -13,19 +13,24 @@ // ==/UserScript== // Remove the "download app ads" -const dlClasses = ["tiktok-9er52i-DivCtaGuideWrapper", "tiktok-99ed1t-DivFooterGuide", "tiktok-txik7e-DivFloatButtonWrapper", "tiktok-h0mxry-DivCtaContentWrapper"] +const dlClasses = [ + "tiktok-9er52i-DivCtaGuideWrapper", + "tiktok-99ed1t-DivFooterGuide", + "tiktok-txik7e-DivFloatButtonWrapper", + "tiktok-h0mxry-DivCtaContentWrapper", +]; setInterval(() => { - for (const dlClass of dlClasses) { - const element = document.getElementsByClassName(dlClass)[0] - if (element === undefined) { - continue - } - for (const childElm of element.children) { - console.log(childElm) - setTimeout(() => element.removeChild(childElm), 1) - } - element.style["height"] = "0px" - element.style["padding"] = "0px" - element.style["z-index"] = "-1" + for (const dlClass of dlClasses) { + const element = document.getElementsByClassName(dlClass)[0]; + if (element === undefined) { + continue; } -}, 50) \ No newline at end of file + for (const childElm of element.children) { + console.log(childElm); + setTimeout(() => element.removeChild(childElm), 1); + } + element.style["height"] = "0px"; + element.style["padding"] = "0px"; + element.style["z-index"] = "-1"; + } +}, 50); diff --git a/userscripts/yt-noshorts.user.js b/userscripts/yt-noshorts.user.js index 2c5c89f..980ec82 100644 --- a/userscripts/yt-noshorts.user.js +++ b/userscripts/yt-noshorts.user.js @@ -24,20 +24,19 @@ function logDebug(...kwargs) { console.log(...kwargs); } -function getShortsId(videoPathName) -{ - const shortPath = videoPathName.split("/") - return shortPath[shortPath.length - 1] +function getShortsId(videoPathName) { + const shortPath = videoPathName.split("/"); + return shortPath[shortPath.length - 1]; } function redirectReplace() { - window.location.replace("https://www.youtube.com/watch?v=" + getShortsId(window.location.pathname)); + window.location.replace( + "https://www.youtube.com/watch?v=" + getShortsId(window.location.pathname), + ); } -function checkCurrentURL() -{ - if (window.location.pathname.includes("/shorts/")) - { +function checkCurrentURL() { + if (window.location.pathname.includes("/shorts/")) { logDebug("Shorts url detected, redirecting..."); redirectReplace(); } @@ -46,22 +45,19 @@ function checkCurrentURL() // Should be run asap checkCurrentURL(); -function replaceHrefURL(element) -{ - if (element.href != null && element.href.includes("/shorts/")) - { - element.href = "/watch?v=" + getShortsId(element.href) +function replaceHrefURL(element) { + if (element.href != null && element.href.includes("/shorts/")) { + element.href = "/watch?v=" + getShortsId(element.href); } } -function checkElements() -{ - insertionQ(':is(#video-title, #thumbnail) ').every(function(element) { +function checkElements() { + insertionQ(":is(#video-title, #thumbnail) ").every(function (element) { replaceHrefURL(element); }); } -window.addEventListener('yt-navigate-finish', checkCurrentURL); +window.addEventListener("yt-navigate-finish", checkCurrentURL); // Replace addEventListener with our sus one. const o_addEventListener = window.addEventListener; const o_shady_addEventListener = window.__shady_addEventListener; @@ -89,17 +85,21 @@ function f_addEventListener(eventName, callback) { // This event is made by SponsorBlock not Youtube so by default it will not run. // But this can speed up the page navigation process so i'll just keep it. const data = event.data; - if (data.type == 'navigation' && data.pageType == 'shorts') { + if (data.type == "navigation" && data.pageType == "shorts") { if (data.videoID == undefined) { return; } logDebug("Thank you SponsorBlock for this event :3"); logDebug("Navigating to video..."); if (window.location.pathname.includes("/shorts/")) { - window.location.replace("https://www.youtube.com/watch?v=" + data.videoID); + window.location.replace( + "https://www.youtube.com/watch?v=" + data.videoID, + ); return; } - window.location.assign("https://www.youtube.com/watch?v=" + data.videoID); + window.location.assign( + "https://www.youtube.com/watch?v=" + data.videoID, + ); return; } } @@ -117,4 +117,4 @@ logDebug("Init fake addEventListener successful."); window.__shady_addEventListener = f_sus_addEventListener; logDebug("Init fake __shady_addEventListener successful."); checkElements(); -console.warn("Fuck you YouTube - NoShorts loaded.") +console.warn("Fuck you YouTube - NoShorts loaded."); diff --git a/userstyles/README.md b/userstyles/README.md index 39a6ce8..d752345 100644 --- a/userstyles/README.md +++ b/userstyles/README.md @@ -1,6 +1,8 @@ -# UserStyles +# UserStyles + Contains random UserStyles. ## UserStyles list -+ [Messenger Dynamic Sidebar](./messenger-dynamic-sidebar.user.css): [reizumi](https://codeberg.org/reizumi)'s Messenger Dynamic Sidebar ported to pure CSS for Ferdium support -> Ported from commit [`1cb2a5b12ad2d04d8c3932892108b6be05528c6f`](https://codeberg.org/reizumi/userstyles/commit/1cb2a5b12ad2d04d8c3932892108b6be05528c6f) + +- [Messenger Dynamic Sidebar](./messenger-dynamic-sidebar.user.css): [reizumi](https://codeberg.org/reizumi)'s Messenger Dynamic Sidebar ported to pure CSS for Ferdium support + > Ported from commit [`1cb2a5b12ad2d04d8c3932892108b6be05528c6f`](https://codeberg.org/reizumi/userstyles/commit/1cb2a5b12ad2d04d8c3932892108b6be05528c6f) diff --git a/userstyles/messenger-dynamic-sidebar.user.css b/userstyles/messenger-dynamic-sidebar.user.css index b773ba4..583bd7e 100644 --- a/userstyles/messenger-dynamic-sidebar.user.css +++ b/userstyles/messenger-dynamic-sidebar.user.css @@ -1,96 +1,104 @@ :root { - --sidebarSpeed: .2s; - --sidebarDelay: .1s; - --actionBarDelay: .15s; - --sidebarEase: "ease"; - --sidebarWidth: 360px; + --sidebarSpeed: 0.2s; + --sidebarDelay: 0.1s; + --actionBarDelay: 0.15s; + --sidebarEase: "ease"; + --sidebarWidth: 360px; } .bdao358l.om3e55n1.g4tp4svg.alzwoclg.cqf1kptm.jez8cy9q.gvxzyvdx.aeinzg81.qp72b3h3.oxkhqvkx.nch0832m.srn514ro.rl78xhln { - max-width: 0; - overflow: hidden; - border-right-color: var(--web-wash); - transition: max-width var(--sidebarSpeed); - transition-delay: var(--actionBarDelay); + max-width: 0; + overflow: hidden; + border-right-color: var(--web-wash); + transition: max-width var(--sidebarSpeed); + transition-delay: var(--actionBarDelay); } .bdao358l.om3e55n1.g4tp4svg.alzwoclg.cqf1kptm.jez8cy9q.gvxzyvdx.aeinzg81.qp72b3h3.oxkhqvkx.nch0832m.srn514ro.rl78xhln:hover { - max-width: 211px; - border-right-color: var(--media-inner-border); + max-width: 211px; + border-right-color: var(--media-inner-border); } /* Header */ -.mm98tyaj .bdao358l.om3e55n1.g4tp4svg.alzwoclg.jez8cy9q.sl27f92c.i85zmo3j.sr926ui1.jl2a5g8c.anf3k8p9.rj0o91l8.qjfq86k5.p9ctufpz.lth9pzmp { - opacity: 0; - height: 0; - margin: 0 16px; - overflow: hidden; - transition: var(--sidebarSpeed); +.mm98tyaj + .bdao358l.om3e55n1.g4tp4svg.alzwoclg.jez8cy9q.sl27f92c.i85zmo3j.sr926ui1.jl2a5g8c.anf3k8p9.rj0o91l8.qjfq86k5.p9ctufpz.lth9pzmp { + opacity: 0; + height: 0; + margin: 0 16px; + overflow: hidden; + transition: var(--sidebarSpeed); } /* Search */ .mm98tyaj .bdao358l.om3e55n1.g4tp4svg.r227ecj6.gt60zsk1.rj2hsocd.f9xcifuu { - opacity: 0; - height: 0; - overflow: hidden; - transition: var(--sidebarSpeed); + opacity: 0; + height: 0; + overflow: hidden; + transition: var(--sidebarSpeed); } /* Text Header */ .mm98tyaj .jxuftiz4.jwegzro5.hl4rid49.icdlwmnq { - width: 150px; + width: 150px; } /* Unread Message Indicator */ .mm98tyaj .nmlomj2f[data-visualcompletion="ignore"] { - position: relative; - right: 83px; - transition-delay: var(--sidebarDelay); + position: relative; + right: 83px; + transition-delay: var(--sidebarDelay); } /* Notification bell */ .mm98tyaj .sr926ui1.alzwoclg.i85zmo3j svg, .mm98tyaj .sr926ui1.alzwoclg.i85zmo3j .i1ozlmoo { - display: none; + display: none; } /* Scrollbar */ -.mm98tyaj .alzwoclg.cqf1kptm.cgu29s5g.i15ihif8.sl4bvocy.lq84ybu9.efm7ts3d.om3e55n1.mfclru0v { - overflow-y: hidden; +.mm98tyaj + .alzwoclg.cqf1kptm.cgu29s5g.i15ihif8.sl4bvocy.lq84ybu9.efm7ts3d.om3e55n1.mfclru0v { + overflow-y: hidden; } /* Hide contents (workaround) */ .i85zmo3j.alzwoclg.rtxb060y.p4zypb3t { - overflow: hidden; + overflow: hidden; } /* Sidebar (not focused) */ .mm98tyaj { - width: 80px; - min-width: 80px; - transition: width var(--sidebarSpeed) var(--sidebarEase); - transition-delay: var(--sidebarDelay); + width: 80px; + min-width: 80px; + transition: width var(--sidebarSpeed) var(--sidebarEase); + transition-delay: var(--sidebarDelay); } /* Sidebar (focused) */ .b0ur3jhr:hover .mm98tyaj { - width: var(--sidebarWidth); - transition-delay: 0s; + width: var(--sidebarWidth); + transition-delay: 0s; } /* Header (focused) */ -.b0ur3jhr:hover .mm98tyaj .bdao358l.om3e55n1.g4tp4svg.alzwoclg.jez8cy9q.sl27f92c.i85zmo3j.sr926ui1.jl2a5g8c.anf3k8p9.rj0o91l8.qjfq86k5.p9ctufpz.lth9pzmp { - opacity: 1; - height: auto; - overflow: visible; - margin: 20px 16px 12px 16px; +.b0ur3jhr:hover + .mm98tyaj + .bdao358l.om3e55n1.g4tp4svg.alzwoclg.jez8cy9q.sl27f92c.i85zmo3j.sr926ui1.jl2a5g8c.anf3k8p9.rj0o91l8.qjfq86k5.p9ctufpz.lth9pzmp { + opacity: 1; + height: auto; + overflow: visible; + margin: 20px 16px 12px 16px; } /* Search (focused) */ -.b0ur3jhr:hover .mm98tyaj .bdao358l.om3e55n1.g4tp4svg.r227ecj6.gt60zsk1.rj2hsocd.f9xcifuu { - opacity: 1; - height: auto; - overflow: visible; +.b0ur3jhr:hover + .mm98tyaj + .bdao358l.om3e55n1.g4tp4svg.r227ecj6.gt60zsk1.rj2hsocd.f9xcifuu { + opacity: 1; + height: auto; + overflow: visible; } /* Unread Message Indicator (focused) */ .b0ur3jhr:hover .mm98tyaj .nmlomj2f[data-visualcompletion="ignore"] { - right: 0; - transition-delay: 0s; + right: 0; + transition-delay: 0s; } /* Notification bell (focused) */ .b0ur3jhr:hover .mm98tyaj .sr926ui1.alzwoclg.i85zmo3j svg, .b0ur3jhr:hover .mm98tyaj .sr926ui1.alzwoclg.i85zmo3j .i1ozlmoo { - display: block; + display: block; } /* Scrollbar (focused) */ -.b0ur3jhr:hover .mm98tyaj .alzwoclg.cqf1kptm.cgu29s5g.i15ihif8.sl4bvocy.lq84ybu9.efm7ts3d.om3e55n1.mfclru0v { - overflow-y: scroll; +.b0ur3jhr:hover + .mm98tyaj + .alzwoclg.cqf1kptm.cgu29s5g.i15ihif8.sl4bvocy.lq84ybu9.efm7ts3d.om3e55n1.mfclru0v { + overflow-y: scroll; } diff --git a/web/aov-vn/README.md b/web/aov-vn/README.md new file mode 100644 index 0000000..1c86d90 --- /dev/null +++ b/web/aov-vn/README.md @@ -0,0 +1,8 @@ +# Scripts for Arena of Valor minigame + +Scripts I created for this game, thats it. (Not cheating scripts in-game tho) + +## Scripts + +- [awc_autospin.js](./awc_autospin.js) - Auto spin the wheel in AWC website (Works in Vietnamese AOV only, other region need to tweak some string into their language) +- [apl2022-clicker.js](./apl2022-clicker.js) - "Auto click" to claim gift by abusing GraphQL requests. diff --git a/games/aov/apl2022-clicker.js b/web/aov-vn/apl2022-clicker.js similarity index 57% rename from games/aov/apl2022-clicker.js rename to web/aov-vn/apl2022-clicker.js index 623f849..a4aa016 100644 --- a/games/aov/apl2022-clicker.js +++ b/web/aov-vn/apl2022-clicker.js @@ -1,16 +1,16 @@ if (!window.location.href.startsWith("https://apl2022.lienquan.garena.vn")) { - console.error("This script is for https://apl2022.lienquan.garena.vn only."); + console.error("This script is for https://apl2022.lienquan.garena.vn only."); } async function getCurrentUser() { - const rsp = await fetch('/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - operationName: "getUser", - query: ` + const rsp = await fetch("/graphql", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + operationName: "getUser", + query: ` query getUser { getUser { id @@ -49,24 +49,24 @@ async function getCurrentUser() { __typename } `, - variables: {}, - }), - }) - if (!rsp.ok) { - throw `Failed to get current user info` - } - return (await rsp.json()).data.getUser; + variables: {}, + }), + }); + if (!rsp.ok) { + throw `Failed to get current user info`; + } + return (await rsp.json()).data.getUser; } async function postClick(amount) { - const rsp = await fetch('/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - operationName: "doDailyClick", - query: ` + const rsp = await fetch("/graphql", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + operationName: "doDailyClick", + query: ` mutation doDailyClick($clicks: Int!) { dailyClick(clicks: $clicks) { id @@ -99,41 +99,41 @@ async function postClick(amount) { __typename } `, - variables: { - clicks: amount, - }, - }), - }) - if (!rsp.ok) { - throw `Failed to post click request with amount ${amount}` - } + variables: { + clicks: amount, + }, + }), + }); + if (!rsp.ok) { + throw `Failed to post click request with amount ${amount}`; + } } async function main() { - console.log("Fetching user information..."); - let user; - try { - user = await getCurrentUser(); - } catch(e) { - console.error(e); - return; - } - console.log(`Hello, ${user.name}!`); - console.log("Calculating remaining clicks needed..."); - const clicksNeeded = 1000 - user.profile.dailyClicks; - if (clicksNeeded == 0) { - console.warn("You've already clicked enough for a day :D"); - return; - } - console.log(`Clicks needed: ${clicksNeeded}`); - console.log("Sending click request..."); - try { - postClick(clicksNeeded); - } catch(e) { - console.error(e); - return; - } - console.log("Success! Please reload page to see the changes."); + console.log("Fetching user information..."); + let user; + try { + user = await getCurrentUser(); + } catch (e) { + console.error(e); + return; + } + console.log(`Hello, ${user.name}!`); + console.log("Calculating remaining clicks needed..."); + const clicksNeeded = 1000 - user.profile.dailyClicks; + if (clicksNeeded == 0) { + console.warn("You've already clicked enough for a day :D"); + return; + } + console.log(`Clicks needed: ${clicksNeeded}`); + console.log("Sending click request..."); + try { + postClick(clicksNeeded); + } catch (e) { + console.error(e); + return; + } + console.log("Success! Please reload page to see the changes."); } -main() +main(); diff --git a/web/aov-vn/awc_autospin.js b/web/aov-vn/awc_autospin.js new file mode 100644 index 0000000..84a700f --- /dev/null +++ b/web/aov-vn/awc_autospin.js @@ -0,0 +1,130 @@ +// Fetch jQuery +await fetch("https://code.jquery.com/jquery-3.6.0.min.js") + .then((x) => x.text()) + .then((y) => eval(y)); +// Wait for jQuery to be loaded. +{ + // From https://stackoverflow.com/a/53914092 + class ClassWatcher { + constructor( + targetNode, + classToWatch, + classAddedCallback, + classRemovedCallback, + ) { + this.targetNode = targetNode; + this.classToWatch = classToWatch; + this.classAddedCallback = classAddedCallback; + this.classRemovedCallback = classRemovedCallback; + this.observer = null; + this.lastClassState = targetNode.classList.contains(this.classToWatch); + + this.init(); + } + + init() { + this.observer = new MutationObserver(this.mutationCallback); + this.observe(); + } + + observe() { + this.observer.observe(this.targetNode, { attributes: true }); + } + + disconnect() { + this.observer.disconnect(); + } + + mutationCallback = (mutationsList) => { + for (let mutation of mutationsList) { + if ( + mutation.type === "attributes" && + mutation.attributeName === "class" + ) { + let currentClassState = mutation.target.classList.contains( + this.classToWatch, + ); + if (this.lastClassState !== currentClassState) { + this.lastClassState = currentClassState; + if (currentClassState) { + this.classAddedCallback(); + } else { + this.classRemovedCallback(); + } + } + } + } + }; + } + + var disableChest = false; + function clickFirstButtonByClassName(className) { + let btn = document.getElementsByClassName(className)[0]; + if (!(typeof btn === "undefined")) { + btn.dispatchEvent(new MouseEvent("click")); + } + } + // Click the spin button + function spin() { + clickFirstButtonByClassName("wheel__main--note"); + if (!disableChest) { + clickFirstButtonByClassName("chest"); + } + } + + function pickCard() { + let teams = document.getElementsByClassName("popup-draw__card"); + for (let i = 0; i < 3; i++) { + teams[i].dispatchEvent(new MouseEvent("click")); + } + setTimeout(() => jQuery(".ReactModal__Overlay").trigger("click"), 2000); + } + // Check for dialog message then close + function closeSwalDialog() { + clickFirstButtonByClassName("swal2-close"); + if (document.getElementsByClassName("swal2-close").length > 0) { + setTimeout(closeSwalDialog, 100); + } + } + + function Swal2Dialog() { + if (document.getElementsByClassName("popup-draw__card").length > 0) { + pickCard(); + } else { + let swal2msg = document.getElementsByClassName("popup-alert__message"); + if (swal2msg.length > 0) { + console.log(swal2msg[0].innerHTML); + if ( + swal2msg[0].innerHTML == + "Đã đạt đến giới hạn Rương đếm ngược hàng ngày" + ) { + disableChest = true; + } else if (swal2msg[0].innerHTML == "Bạn đã hết lượt quay trong ngày") { + closeAutoFarm(); + } + } + } + closeSwalDialog(); + } + + // Watch for SweetAlert 2 + let swal2Watcher = new ClassWatcher( + document.body, + "swal2-shown", + Swal2Dialog, + spin, + ); + + function closeAutoFarm() { + swal2Watcher.disconnect(); + } + + spin(); + // Disable window change + jQuery("window").off("mouseup"); + jQuery("document").off("visibilitychange"); + // Remove video player (so it isnt annoying to me and save CPU by a lot) + Array.from(document.getElementsByTagName("iframe")).forEach((iframe) => { + iframe.remove(); + }); +} diff --git a/web/olm.vn/screenshot-answers.js b/web/olm.vn/screenshot-answers.js new file mode 100644 index 0000000..1e333ac --- /dev/null +++ b/web/olm.vn/screenshot-answers.js @@ -0,0 +1,52 @@ +// Dependencies +eval( + await ( + await fetch("https://html2canvas.hertzen.com/dist/html2canvas.min.js") + ).text(), +); +eval( + await ( + await fetch("https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js") + ).text(), +); +eval( + await ( + await fetch( + "https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.0/FileSaver.min.js", + ) + ).text(), +); + +const zipFile = new JSZip(); + +async function screenshotAnswer(answerElement) { + console.log(answerElement); + const canvas = await html2canvas(answerElement); + return await new Promise((resolve) => canvas.toBlob(resolve)); +} + +async function saveImage(image, imageName) { + zipFile.file(imageName, image); +} + +async function saveZip() { + const generatedFile = await zipFile.generateAsync({ type: "blob" }); + console.log(`URL: ${URL.createObjectURL(generatedFile)}`); + saveAs(generatedFile, "olm-answers.zip"); +} + +const questionBtns = document.querySelector("#question-static").children; +const wrongQuestionCount = + document.querySelectorAll(".q-static.q-wrong").length; +for (const [index, questionBtn] of Array.from(questionBtns).entries()) { + if (index > questionBtns.length - 1 - wrongQuestionCount) { + break; + } + // Click the button + questionBtn.click(); + const answerElement = + document.querySelector("#qholder").parentElement.parentElement; + const answerImage = await screenshotAnswer(answerElement); + saveImage(answerImage, `question-${index + 1}.png`); +} +await saveZip();