feat: add scripts
This commit is contained in:
parent
7fe79a2bdb
commit
92c0e0ee6c
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
@ -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()
|
||||
})
|
||||
}
|
@ -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.
|
@ -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
|
||||
|
||||
- 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
|
||||
|
@ -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 (_) {}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
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);
|
||||
|
@ -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.");
|
||||
|
@ -1,6 +1,8 @@
|
||||
# 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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
8
web/aov-vn/README.md
Normal file
8
web/aov-vn/README.md
Normal 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.
|
@ -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();
|
130
web/aov-vn/awc_autospin.js
Normal file
130
web/aov-vn/awc_autospin.js
Normal 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();
|
||||
});
|
||||
}
|
52
web/olm.vn/screenshot-answers.js
Normal file
52
web/olm.vn/screenshot-answers.js
Normal 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();
|
Loading…
Reference in New Issue
Block a user