feat: add scripts
This commit is contained in:
parent
7fe79a2bdb
commit
92c0e0ee6c
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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 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.
|
@ -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
|
|
||||||
|
@ -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 (_) {}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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.");
|
||||||
|
@ -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)
|
||||||
|
@ -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
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.
|
@ -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
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