feat: add scripts

This commit is contained in:
tretrauit 2023-08-22 01:28:47 +07:00
parent 7fe79a2bdb
commit 92c0e0ee6c
19 changed files with 581 additions and 438 deletions

View File

@ -1,45 +1,64 @@
# Lutris scripts # Lutris scripts
## `preloader.sh` ## `preloader.sh`
Execute multiple scripts in a folder (default is `./preloader`), usually useful for Lutris Pre-launch/Post-exit script 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 ### Installation
+ To download `preloader.sh` itself:
- To download `preloader.sh` itself:
```sh ```sh
curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/apps/Lutris/preloader.sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/apps/Lutris/preloader.sh
chmod +x preloader.sh chmod +x preloader.sh
``` ```
+ After that, copy/move this script to the game prefix you want to use, then in Lutris:
- 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. - Set pre-launch script in Lutris to where `preloader.sh` is located.
- Disable **Wait for pre-launch script completion** (optional) - 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). - **IMPORTANT**: Now, to add pre-launch script, instead of setting them in Lutris, add them to `./preloader` (or the folder you specified).
+ Enjoy :L - Enjoy :L
### Documentation ### Documentation
There are environment variables to control how preloader.sh work: 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` ## `discord_rpc.sh`
Launch `winediscordrpcbridge.exe`, to be able to get Discord Rich Presence on Wine applications on the specified prefix. Launch `winediscordrpcbridge.exe`, to be able to get Discord Rich Presence on Wine applications on the specified prefix.
### Installation ### 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 ```sh
curl -OL https://github.com/0e4ef622/wine-discord-ipc-bridge/releases/latest/download/winediscordipcbridge.exe curl -OL https://github.com/0e4ef622/wine-discord-ipc-bridge/releases/latest/download/winediscordipcbridge.exe
``` ```
or use my build (latest commit: `master/9d56418`) or use my build (latest commit: `master/9d56418`)
```sh ```sh
curl -OL https://github.com/teppyboy/releases/releases/download/git%2B0e4ef622%2Fwine-discord-ipc-bridge%2Bmaster%2F9d56418/winediscordipcbridge.exe 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 ```sh
curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/apps/Lutris/discord_rpc.sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/apps/Lutris/discord_rpc.sh
chmod +x 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:
- 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. - Set pre-launch script in Lutris to where `discord_rpc.sh` is located.
- Disable **Wait for pre-launch script completion** - Disable **Wait for pre-launch script completion**
+ Enjoy :L - Enjoy :L

View File

@ -4,19 +4,19 @@
### Notes ### Notes
+ **YOU NEED TO HAVE WS-SCRCPY INSTALLED, ALONG WITH ROOT ACCESS AND DEPENDENCIES** - **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 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) - 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. - 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` - 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` > 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. > 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 ```bash
curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/Apps/ws-scrcpy/ws-scrcpy-launcher.py 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. > 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 ```bash
pkg update 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 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. > You need to use `adb pair` to pair termux with your device adb server, then you can launch ws-scrcpy as explained above.

View File

@ -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)

View File

@ -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()
})
}

View File

@ -1,9 +1,12 @@
# Scripts for [Cities: Skylines](https://www.citiesskylines.com/) # Scripts for [Cities: Skylines](https://www.citiesskylines.com/)
Scripts I created for this game, thats it. Scripts I created for this game, thats it.
### Scripts ### 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 #### 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. 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.

View File

@ -1,58 +1,71 @@
# leagueoflinux scripts # leagueoflinux scripts
## `sulaunchhelper2.sh` ## `sulaunchhelper2.sh`
This script is a wrapper for `sulaunchhelper2.py` for use with Lutris pre-game launch script. This script is a wrapper for `sulaunchhelper2.py` for use with Lutris pre-game launch script.
### Installation ### 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) > 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 ```sh
curl -OL https://raw.githubusercontent.com/CakeTheLiar/launchhelper/master/sulaunchhelper2.py curl -OL https://raw.githubusercontent.com/CakeTheLiar/launchhelper/master/sulaunchhelper2.py
chmod +x sulaunchhelper2.py chmod +x sulaunchhelper2.py
``` ```
+ Then to download `sulaunchhelper2.sh` itself:
- Then to download `sulaunchhelper2.sh` itself:
```sh ```sh
curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/games/LoL/linux/sulaunchhelper2.sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/games/LoL/linux/sulaunchhelper2.sh
chmod +x 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. - 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**
- Disable **Wait for pre-launch script completion** > Failure to do above steps will result in Zenity can't show necessary messages dialog so LoL UI can't launch properly.
- Enable **Disable Lutris Runtime** - Enjoy your LoL experience :P
> 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) ## [`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`, - This script will bridge Discord RPC from LoL prefix to your linux Discord.
the installation is the same **except** when installing the script itself, execute this instead: > 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 ```sh
curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/games/LoL/linux/discord_rpc.sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/games/LoL/linux/discord_rpc.sh
chmod +x discord_rpc.sh chmod +x discord_rpc.sh
``` ```
## Deprecated ## Deprecated
### `garena_wrapper.sh` ### `garena_wrapper.sh`
> Garena no longer owns LoL so to play LoL you need to use Rito Client. > 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 ;) 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 #### 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) > 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. 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 ```sh
curl -OL https://raw.githubusercontent.com/nhubaotruong/league-of-legends-linux-garena-script/main/lol.py curl -OL https://raw.githubusercontent.com/nhubaotruong/league-of-legends-linux-garena-script/main/lol.py
chmod +x lol.py chmod +x lol.py
``` ```
+ Then to download `garena_wrapper.sh` itself:
- Then to download `garena_wrapper.sh` itself:
```sh ```sh
curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/games/LoL/linux/garena_wrapper.sh curl -OL https://gitlab.com/tretrauit/scripts/-/raw/main/games/LoL/linux/garena_wrapper.sh
chmod +x 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. - 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**
- Disable **Wait for pre-launch script completion** > 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).
- Enable **Disable Lutris Runtime** - Enjoy your Garena LoL experience :P
> 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

View File

@ -12,12 +12,16 @@
// @downloadURL https://gitlab.com/tretrauit/scripts/-/raw/main/userscripts/anonyviet-skip-wait.user.js // @downloadURL https://gitlab.com/tretrauit/scripts/-/raw/main/userscripts/anonyviet-skip-wait.user.js
// ==/UserScript== // ==/UserScript==
const REDIRECT_PAGE = "https://anonyviet.com/tieptucdentrangmoi/?url=" const REDIRECT_PAGE = "https://anonyviet.com/tieptucdentrangmoi/?url=";
for (const element of document.getElementsByTagName("a")) { for (const element of document.getElementsByTagName("a")) {
try { try {
if (element.getAttribute("href").startsWith(REDIRECT_PAGE)) { if (element.getAttribute("href").startsWith(REDIRECT_PAGE)) {
element.setAttribute("href", decodeURIComponent(element.getAttribute("href").substring(REDIRECT_PAGE.length))) element.setAttribute(
} "href",
} catch (_) { decodeURIComponent(
element.getAttribute("href").substring(REDIRECT_PAGE.length),
),
);
} }
} catch (_) {}
} }

View File

@ -13,16 +13,20 @@
// ==/UserScript== // ==/UserScript==
setTimeout(() => { 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) { if (header != null) {
header.remove() header.remove();
console.log("Removed header") console.log("Removed header");
} }
setTimeout(() => { 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) { if (watermark != null) {
watermark.remove() watermark.remove();
console.log("Removed watermark") console.log("Removed watermark");
} }
}, 5000); }, 5000);
}, 5000); }, 5000);

View File

@ -12,25 +12,27 @@
// @downloadURL https://gitlab.com/tretrauit/scripts/-/raw/main/userscripts/hidemy.name-free-ipport-export.user.js // @downloadURL https://gitlab.com/tretrauit/scripts/-/raw/main/userscripts/hidemy.name-free-ipport-export.user.js
// ==/UserScript== // ==/UserScript==
setTimeout(function() { setTimeout(function () {
const tblContent = document.getElementsByClassName("table_block")[0].getElementsByTagName("tbody")[0].children const tblContent = document
.getElementsByClassName("table_block")[0]
.getElementsByTagName("tbody")[0].children;
// Replace the export IP:Port button // Replace the export IP:Port button
const btns = document.getElementsByClassName("export")[0] const btns = document.getElementsByClassName("export")[0];
const exportBtn = btns.children[0] const exportBtn = btns.children[0];
const fakeExportBtn = exportBtn.cloneNode(true) const fakeExportBtn = exportBtn.cloneNode(true);
fakeExportBtn.removeAttribute("href") fakeExportBtn.removeAttribute("href");
fakeExportBtn.addEventListener("click", () => { fakeExportBtn.addEventListener("click", () => {
var proxyStr = "" var proxyStr = "";
for (let proxyContent of tblContent) { for (let proxyContent of tblContent) {
const proxyContentChildren = proxyContent.children const proxyContentChildren = proxyContent.children;
const proxyIp = proxyContentChildren[0].innerHTML const proxyIp = proxyContentChildren[0].innerHTML;
const proxyPort = proxyContentChildren[1].innerHTML const proxyPort = proxyContentChildren[1].innerHTML;
proxyStr += proxyIp + ":" + proxyPort + "\n" proxyStr += proxyIp + ":" + proxyPort + "\n";
} }
navigator.clipboard.writeText(proxyStr) navigator.clipboard.writeText(proxyStr);
alert("Copied IP:Port list to clipboard.") alert("Copied IP:Port list to clipboard.");
}) });
exportBtn.remove() exportBtn.remove();
btns.prepend(fakeExportBtn) btns.prepend(fakeExportBtn);
}, 5000); }, 5000);

View File

@ -14,81 +14,88 @@
// ==/UserScript== // ==/UserScript==
function init() { function init() {
const chest = document.getElementsByClassName("chest")[0] const chest = document.getElementsByClassName("chest")[0];
const chestStatus = document.getElementsByClassName("chest__btn btn")[0] const chestStatus = document.getElementsByClassName("chest__btn btn")[0];
const openWheelBtn = document.getElementsByClassName("wheel__btn")[0] const openWheelBtn = document.getElementsByClassName("wheel__btn")[0];
const upgradeBtn = document.getElementsByClassName("card__upgrade")[0] const upgradeBtn = document.getElementsByClassName("card__upgrade")[0];
// Has string characters need to be removed first. // Has string characters need to be removed first.
const requiredScore = document.getElementsByClassName("card__note")[0].getElementsByTagName("strong")[0] const requiredScore = document
const currentScore = document.getElementsByClassName("card__data")[0].getElementsByTagName("span")[1] .getElementsByClassName("card__note")[0]
.getElementsByTagName("strong")[0];
const currentScore = document
.getElementsByClassName("card__data")[0]
.getElementsByTagName("span")[1];
function toInt(str) { function toInt(str) {
return parseInt(str.replace(/[^0-9]/g, '')) return parseInt(str.replace(/[^0-9]/g, ""));
} }
function upgradeRank() { function upgradeRank() {
if (toInt(currentScore.innerHTML) >= toInt(requiredScore.innerHTML)) { if (toInt(currentScore.innerHTML) >= toInt(requiredScore.innerHTML)) {
upgradeBtn.click() upgradeBtn.click();
} }
} }
function receiveRankReward() { function receiveRankReward() {
const rewards = document.getElementsByClassName("milestone available") const rewards = document.getElementsByClassName("milestone available");
for (const reward of rewards) { for (const reward of rewards) {
if (reward.className.includes("claimed")) { if (reward.className.includes("claimed")) {
continue continue;
} }
reward.click() reward.click();
} }
} }
function spinWheel() { function spinWheel() {
const spinBtn = document.getElementsByClassName("popup-wheel__btn")[0] const spinBtn = document.getElementsByClassName("popup-wheel__btn")[0];
const spinLeft = spinBtn.children[1].getElementsByTagName("strong")[0] const spinLeft = spinBtn.children[1].getElementsByTagName("strong")[0];
function doSpin() { function doSpin() {
spinBtn.click() spinBtn.click();
setTimeout(() => { setTimeout(() => {
if (parseInt(spinLeft.innerHTML) > 0) { if (parseInt(spinLeft.innerHTML) > 0) {
setTimeout(doSpin, 1000) setTimeout(doSpin, 1000);
} }
}, 3000) }, 3000);
} }
doSpin() doSpin();
const closeBtn = document.getElementsByClassName("close")[0] const closeBtn = document.getElementsByClassName("close")[0];
closeBtn.click() closeBtn.click();
} }
function wheel() { function wheel() {
if (!openWheelBtn.className.includes("animate__tada") || document.getElementById("wheel") != null) { if (
return !openWheelBtn.className.includes("animate__tada") ||
document.getElementById("wheel") != null
) {
return;
} }
console.log("click chest") console.log("click chest");
openWheelBtn.click() openWheelBtn.click();
setTimeout(spinWheel, 1000) setTimeout(spinWheel, 1000);
} }
function receiveScore() { function receiveScore() {
if (chestStatus.innerHTML === "Nhận") { if (chestStatus.innerHTML === "Nhận") {
chest.click() chest.click();
} }
} }
setInterval(() => { setInterval(() => {
if (element = document.getElementsByClassName("swal2-close")[0]) { if ((element = document.getElementsByClassName("swal2-close")[0])) {
element.click() element.click();
} }
}, 100); }, 100);
function loop() { function loop() {
receiveScore() receiveScore();
upgradeRank() upgradeRank();
receiveRankReward() receiveRankReward();
setTimeout(wheel, 500) setTimeout(wheel, 500);
setTimeout(loop, 1000) setTimeout(loop, 1000);
} }
loop() loop();
} }
setTimeout(init, 5000) setTimeout(init, 5000);
console.warn("[8thang5 - Auto farm] Successfully loaded") console.warn("[8thang5 - Auto farm] Successfully loaded");
console.log("Made by @tretrauit under MIT License") console.log("Made by @tretrauit under MIT License");

View File

@ -13,15 +13,14 @@
// ==/UserScript== // ==/UserScript==
function injectCSS(css) { function injectCSS(css) {
const style = document.createElement('style'); const style = document.createElement("style");
style.appendChild(document.createTextNode(css)); style.appendChild(document.createTextNode(css));
document.head.appendChild(style); document.head.appendChild(style);
} }
function findElement(tag, properties) { function findElement(tag, properties) {
const elements = document.querySelectorAll(tag); const elements = document.querySelectorAll(tag);
elementLoop: elementLoop: for (const element of elements) {
for (const element of elements) {
for (const [key, value] of Object.entries(properties)) { for (const [key, value] of Object.entries(properties)) {
if (element.getAttribute(key) != value) { if (element.getAttribute(key) != value) {
continue elementLoop; continue elementLoop;
@ -43,14 +42,17 @@ function getAncestor(element, level) {
console.log("Scanning class for components..."); console.log("Scanning class for components...");
// Search box // Search box
let searchBox = findElement("input", {"aria-autocomplete": "list"}); let searchBox = findElement("input", { "aria-autocomplete": "list" });
if (searchBox == null) { if (searchBox == null) {
console.warn("Failed to get searchBox element."); console.warn("Failed to get searchBox element.");
throw new Error(); throw new Error();
} }
searchBox = getAncestor(searchBox, 7); searchBox = getAncestor(searchBox, 7);
// Header & Text header // 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; let header;
if (textHeader == null) { if (textHeader == null) {
console.warn("Failed to get textHeader element."); console.warn("Failed to get textHeader element.");
@ -59,16 +61,18 @@ if (textHeader == null) {
header = getAncestor(textHeader, 7); header = getAncestor(textHeader, 7);
textHeader = textHeader.childNodes[0]; textHeader = textHeader.childNodes[0];
// Unread indicator // Unread indicator
let unreadIndicator = findElement("span", {"data-visualcompletion": "ignore"}); let unreadIndicator = findElement("span", {
"data-visualcompletion": "ignore",
});
// Action bar // Action bar
let actionBar = findElement("div", {"aria-expanded": "false"}); let actionBar = findElement("div", { "aria-expanded": "false" });
if (actionBar == null) { if (actionBar == null) {
console.warn("Failed to get actionBar element."); console.warn("Failed to get actionBar element.");
throw new Error(); throw new Error();
} }
actionBar = actionBar.parentNode; actionBar = actionBar.parentNode;
// Chats // Chats
let chats = findElement("div", {"aria-label": "Chats"}); let chats = findElement("div", { "aria-label": "Chats" });
if (chats == null) { if (chats == null) {
console.warn("Failed to get chats element."); console.warn("Failed to get chats element.");
throw new Error(); throw new Error();

View File

@ -13,19 +13,24 @@
// ==/UserScript== // ==/UserScript==
// Remove the "download app ads" // 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(() => { setInterval(() => {
for (const dlClass of dlClasses) { for (const dlClass of dlClasses) {
const element = document.getElementsByClassName(dlClass)[0] const element = document.getElementsByClassName(dlClass)[0];
if (element === undefined) { if (element === undefined) {
continue continue;
} }
for (const childElm of element.children) { for (const childElm of element.children) {
console.log(childElm) console.log(childElm);
setTimeout(() => element.removeChild(childElm), 1) setTimeout(() => element.removeChild(childElm), 1);
} }
element.style["height"] = "0px" element.style["height"] = "0px";
element.style["padding"] = "0px" element.style["padding"] = "0px";
element.style["z-index"] = "-1" element.style["z-index"] = "-1";
} }
}, 50) }, 50);

View File

@ -24,20 +24,19 @@ function logDebug(...kwargs) {
console.log(...kwargs); console.log(...kwargs);
} }
function getShortsId(videoPathName) function getShortsId(videoPathName) {
{ const shortPath = videoPathName.split("/");
const shortPath = videoPathName.split("/") return shortPath[shortPath.length - 1];
return shortPath[shortPath.length - 1]
} }
function redirectReplace() { 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() function checkCurrentURL() {
{ if (window.location.pathname.includes("/shorts/")) {
if (window.location.pathname.includes("/shorts/"))
{
logDebug("Shorts url detected, redirecting..."); logDebug("Shorts url detected, redirecting...");
redirectReplace(); redirectReplace();
} }
@ -46,22 +45,19 @@ function checkCurrentURL()
// Should be run asap // Should be run asap
checkCurrentURL(); checkCurrentURL();
function replaceHrefURL(element) function replaceHrefURL(element) {
{ if (element.href != null && element.href.includes("/shorts/")) {
if (element.href != null && element.href.includes("/shorts/")) element.href = "/watch?v=" + getShortsId(element.href);
{
element.href = "/watch?v=" + getShortsId(element.href)
} }
} }
function checkElements() function checkElements() {
{ insertionQ(":is(#video-title, #thumbnail) ").every(function (element) {
insertionQ(':is(#video-title, #thumbnail) ').every(function(element) {
replaceHrefURL(element); replaceHrefURL(element);
}); });
} }
window.addEventListener('yt-navigate-finish', checkCurrentURL); window.addEventListener("yt-navigate-finish", checkCurrentURL);
// Replace addEventListener with our sus one. // Replace addEventListener with our sus one.
const o_addEventListener = window.addEventListener; const o_addEventListener = window.addEventListener;
const o_shady_addEventListener = window.__shady_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. // 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. // But this can speed up the page navigation process so i'll just keep it.
const data = event.data; const data = event.data;
if (data.type == 'navigation' && data.pageType == 'shorts') { if (data.type == "navigation" && data.pageType == "shorts") {
if (data.videoID == undefined) { if (data.videoID == undefined) {
return; return;
} }
logDebug("Thank you SponsorBlock for this event :3"); logDebug("Thank you SponsorBlock for this event :3");
logDebug("Navigating to video..."); logDebug("Navigating to video...");
if (window.location.pathname.includes("/shorts/")) { 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; return;
} }
window.location.assign("https://www.youtube.com/watch?v=" + data.videoID); window.location.assign(
"https://www.youtube.com/watch?v=" + data.videoID,
);
return; return;
} }
} }
@ -117,4 +117,4 @@ logDebug("Init fake addEventListener successful.");
window.__shady_addEventListener = f_sus_addEventListener; window.__shady_addEventListener = f_sus_addEventListener;
logDebug("Init fake __shady_addEventListener successful."); logDebug("Init fake __shady_addEventListener successful.");
checkElements(); checkElements();
console.warn("Fuck you YouTube - NoShorts loaded.") console.warn("Fuck you YouTube - NoShorts loaded.");

View File

@ -1,6 +1,8 @@
# UserStyles # UserStyles
Contains random UserStyles. Contains random UserStyles.
## UserStyles list ## 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)

View File

@ -1,7 +1,7 @@
:root { :root {
--sidebarSpeed: .2s; --sidebarSpeed: 0.2s;
--sidebarDelay: .1s; --sidebarDelay: 0.1s;
--actionBarDelay: .15s; --actionBarDelay: 0.15s;
--sidebarEase: "ease"; --sidebarEase: "ease";
--sidebarWidth: 360px; --sidebarWidth: 360px;
} }
@ -18,7 +18,8 @@
border-right-color: var(--media-inner-border); border-right-color: var(--media-inner-border);
} }
/* Header */ /* Header */
.mm98tyaj .bdao358l.om3e55n1.g4tp4svg.alzwoclg.jez8cy9q.sl27f92c.i85zmo3j.sr926ui1.jl2a5g8c.anf3k8p9.rj0o91l8.qjfq86k5.p9ctufpz.lth9pzmp { .mm98tyaj
.bdao358l.om3e55n1.g4tp4svg.alzwoclg.jez8cy9q.sl27f92c.i85zmo3j.sr926ui1.jl2a5g8c.anf3k8p9.rj0o91l8.qjfq86k5.p9ctufpz.lth9pzmp {
opacity: 0; opacity: 0;
height: 0; height: 0;
margin: 0 16px; margin: 0 16px;
@ -48,7 +49,8 @@
display: none; display: none;
} }
/* Scrollbar */ /* Scrollbar */
.mm98tyaj .alzwoclg.cqf1kptm.cgu29s5g.i15ihif8.sl4bvocy.lq84ybu9.efm7ts3d.om3e55n1.mfclru0v { .mm98tyaj
.alzwoclg.cqf1kptm.cgu29s5g.i15ihif8.sl4bvocy.lq84ybu9.efm7ts3d.om3e55n1.mfclru0v {
overflow-y: hidden; overflow-y: hidden;
} }
/* Hide contents (workaround) */ /* Hide contents (workaround) */
@ -68,14 +70,18 @@
transition-delay: 0s; transition-delay: 0s;
} }
/* Header (focused) */ /* Header (focused) */
.b0ur3jhr:hover .mm98tyaj .bdao358l.om3e55n1.g4tp4svg.alzwoclg.jez8cy9q.sl27f92c.i85zmo3j.sr926ui1.jl2a5g8c.anf3k8p9.rj0o91l8.qjfq86k5.p9ctufpz.lth9pzmp { .b0ur3jhr:hover
.mm98tyaj
.bdao358l.om3e55n1.g4tp4svg.alzwoclg.jez8cy9q.sl27f92c.i85zmo3j.sr926ui1.jl2a5g8c.anf3k8p9.rj0o91l8.qjfq86k5.p9ctufpz.lth9pzmp {
opacity: 1; opacity: 1;
height: auto; height: auto;
overflow: visible; overflow: visible;
margin: 20px 16px 12px 16px; margin: 20px 16px 12px 16px;
} }
/* Search (focused) */ /* Search (focused) */
.b0ur3jhr:hover .mm98tyaj .bdao358l.om3e55n1.g4tp4svg.r227ecj6.gt60zsk1.rj2hsocd.f9xcifuu { .b0ur3jhr:hover
.mm98tyaj
.bdao358l.om3e55n1.g4tp4svg.r227ecj6.gt60zsk1.rj2hsocd.f9xcifuu {
opacity: 1; opacity: 1;
height: auto; height: auto;
overflow: visible; overflow: visible;
@ -91,6 +97,8 @@
display: block; display: block;
} }
/* Scrollbar (focused) */ /* Scrollbar (focused) */
.b0ur3jhr:hover .mm98tyaj .alzwoclg.cqf1kptm.cgu29s5g.i15ihif8.sl4bvocy.lq84ybu9.efm7ts3d.om3e55n1.mfclru0v { .b0ur3jhr:hover
.mm98tyaj
.alzwoclg.cqf1kptm.cgu29s5g.i15ihif8.sl4bvocy.lq84ybu9.efm7ts3d.om3e55n1.mfclru0v {
overflow-y: scroll; overflow-y: scroll;
} }

8
web/aov-vn/README.md Normal file
View File

@ -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.

View File

@ -3,10 +3,10 @@ if (!window.location.href.startsWith("https://apl2022.lienquan.garena.vn")) {
} }
async function getCurrentUser() { async function getCurrentUser() {
const rsp = await fetch('/graphql', { const rsp = await fetch("/graphql", {
method: 'POST', method: "POST",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
}, },
body: JSON.stringify({ body: JSON.stringify({
operationName: "getUser", operationName: "getUser",
@ -51,18 +51,18 @@ async function getCurrentUser() {
`, `,
variables: {}, variables: {},
}), }),
}) });
if (!rsp.ok) { if (!rsp.ok) {
throw `Failed to get current user info` throw `Failed to get current user info`;
} }
return (await rsp.json()).data.getUser; return (await rsp.json()).data.getUser;
} }
async function postClick(amount) { async function postClick(amount) {
const rsp = await fetch('/graphql', { const rsp = await fetch("/graphql", {
method: 'POST', method: "POST",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
}, },
body: JSON.stringify({ body: JSON.stringify({
operationName: "doDailyClick", operationName: "doDailyClick",
@ -103,9 +103,9 @@ async function postClick(amount) {
clicks: amount, clicks: amount,
}, },
}), }),
}) });
if (!rsp.ok) { if (!rsp.ok) {
throw `Failed to post click request with amount ${amount}` throw `Failed to post click request with amount ${amount}`;
} }
} }
@ -114,7 +114,7 @@ async function main() {
let user; let user;
try { try {
user = await getCurrentUser(); user = await getCurrentUser();
} catch(e) { } catch (e) {
console.error(e); console.error(e);
return; return;
} }
@ -129,11 +129,11 @@ async function main() {
console.log("Sending click request..."); console.log("Sending click request...");
try { try {
postClick(clicksNeeded); postClick(clicksNeeded);
} catch(e) { } catch (e) {
console.error(e); console.error(e);
return; return;
} }
console.log("Success! Please reload page to see the changes."); console.log("Success! Please reload page to see the changes.");
} }
main() main();

130
web/aov-vn/awc_autospin.js Normal file
View File

@ -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();
});
}

View File

@ -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();