Compare commits
15 Commits
68b3d2109e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a47ef7cd4f | ||
|
|
321c72a999 | ||
|
|
ef4c0f8747 | ||
|
|
4ab5b3a2f1 | ||
|
|
323af82393 | ||
|
|
a356f4c003 | ||
| 44f4df5c72 | |||
| 62570d7b31 | |||
| b4cc68b0c1 | |||
| 5edd85e60a | |||
|
|
cbef487915 | ||
|
|
e1db401b58 | ||
|
|
e1b525eaa1 | ||
|
|
dcbdd201ce | ||
|
|
34e5c276d9 |
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Chrome against localhost",
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"webRoot": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
246
adb-music-sync/adb-music-sync.py
Normal file
246
adb-music-sync/adb-music-sync.py
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Tuple, Optional
|
||||||
|
|
||||||
|
# --- Configuration ---
|
||||||
|
HOME = Path.home()
|
||||||
|
SOURCES = [
|
||||||
|
HOME / "Music",
|
||||||
|
HOME / "Downloads",
|
||||||
|
]
|
||||||
|
DEST_ON_PHONE = "/sdcard/Music"
|
||||||
|
# Model tag as seen in `adb devices -l` (e.g., ... model:AGM_M7 ...)
|
||||||
|
ADB_MODEL_MATCH = ["AGM_M7", "AGM", "M7"]
|
||||||
|
POLL_INTERVAL_SEC = 60
|
||||||
|
SIZE_LIMIT_BYTES = 7 * 1024 ** 3 # 7 GiB
|
||||||
|
MUSIC_EXTS = {".mp3", ".m4a", ".ogg", ".aac", ".opus", ".alac", ".flac"}
|
||||||
|
|
||||||
|
# If you have a static Wi-Fi ADB endpoint, set it here (e.g., "192.168.1.50:5555").
|
||||||
|
ADB_IP_PORT: Optional[str] = None
|
||||||
|
|
||||||
|
# --- Helpers ---
|
||||||
|
def run(cmd: List[str], check: bool = False, text: bool = True, timeout: Optional[int] = None) -> subprocess.CompletedProcess:
|
||||||
|
try:
|
||||||
|
return subprocess.run(cmd, check=check, text=text, capture_output=True, timeout=timeout)
|
||||||
|
except Exception as e:
|
||||||
|
return subprocess.CompletedProcess(cmd, returncode=1, stdout="", stderr=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_adb_server() -> None:
|
||||||
|
run(["adb", "start-server"]) # best-effort
|
||||||
|
|
||||||
|
|
||||||
|
def list_adb_devices() -> List[str]:
|
||||||
|
proc = run(["adb", "devices", "-l"]) # do not check, we parse regardless
|
||||||
|
if proc.returncode != 0:
|
||||||
|
return []
|
||||||
|
lines = [ln.strip() for ln in proc.stdout.splitlines()]
|
||||||
|
# skip header line: "List of devices attached"
|
||||||
|
if lines and lines[0].lower().startswith("list of devices"):
|
||||||
|
lines = lines[1:]
|
||||||
|
return [ln for ln in lines if ln]
|
||||||
|
|
||||||
|
|
||||||
|
def adb_connect_if_needed():
|
||||||
|
if not ADB_IP_PORT:
|
||||||
|
return
|
||||||
|
devices = list_adb_devices()
|
||||||
|
if any(ADB_IP_PORT in ln for ln in devices):
|
||||||
|
return # already connected
|
||||||
|
run(["adb", "connect", ADB_IP_PORT])
|
||||||
|
|
||||||
|
|
||||||
|
def is_agm_connected() -> bool:
|
||||||
|
devices = list_adb_devices()
|
||||||
|
for ln in devices:
|
||||||
|
if "device" in ln and not ln.endswith("offline"):
|
||||||
|
if any(tag in ln for tag in ADB_MODEL_MATCH):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def gather_music_files() -> List[Tuple[Path, Path, float, int]]:
|
||||||
|
# Returns list of tuples: (root_dir, file_path, mtime, size)
|
||||||
|
entries: List[Tuple[Path, Path, float, int]] = []
|
||||||
|
for root in SOURCES:
|
||||||
|
try:
|
||||||
|
if not root.exists():
|
||||||
|
continue
|
||||||
|
for dirpath, _, filenames in os.walk(root):
|
||||||
|
dpath = Path(dirpath)
|
||||||
|
for fn in filenames:
|
||||||
|
p = dpath / fn
|
||||||
|
if p.suffix.lower() not in MUSIC_EXTS:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
st = p.stat()
|
||||||
|
entries.append((root, p, st.st_mtime, st.st_size))
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
# newest first by mtime
|
||||||
|
entries.sort(key=lambda t: t[2], reverse=True)
|
||||||
|
return entries
|
||||||
|
|
||||||
|
|
||||||
|
def select_up_to_size(entries: List[Tuple[Path, Path, float, int]], limit_bytes: int) -> List[Tuple[Path, Path, int]]:
|
||||||
|
selected: List[Tuple[Path, Path, int]] = []
|
||||||
|
total = 0
|
||||||
|
for root, p, _mt, sz in entries:
|
||||||
|
if total >= limit_bytes:
|
||||||
|
break
|
||||||
|
selected.append((root, p, sz))
|
||||||
|
total += sz
|
||||||
|
return selected
|
||||||
|
|
||||||
|
|
||||||
|
def adb_shell(cmd: str) -> subprocess.CompletedProcess:
|
||||||
|
# Single string executed via adb shell
|
||||||
|
return run(["adb", "shell", cmd])
|
||||||
|
|
||||||
|
|
||||||
|
def remote_size(adb_path: str) -> Optional[int]:
|
||||||
|
# Uses stat if available; returns None if missing
|
||||||
|
# Escape path for shell
|
||||||
|
qpath = shlex.quote(adb_path)
|
||||||
|
proc = adb_shell(f"stat -c %s {qpath}")
|
||||||
|
if proc.returncode != 0 or not proc.stdout.strip():
|
||||||
|
return None
|
||||||
|
out = proc.stdout.strip()
|
||||||
|
if "No such file" in out or "not found" in out:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return int(out.splitlines()[-1].strip())
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_remote_dir(adb_path: str) -> None:
|
||||||
|
# mkdir -p dirname
|
||||||
|
dirname = os.path.dirname(adb_path)
|
||||||
|
if not dirname:
|
||||||
|
return
|
||||||
|
adb_shell(f"mkdir -p {shlex.quote(dirname)}")
|
||||||
|
|
||||||
|
|
||||||
|
def have_ffmpeg() -> bool:
|
||||||
|
proc = run(["ffmpeg", "-version"])
|
||||||
|
return proc.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
|
def transcode_flac_to_mp3(src: Path) -> Optional[Path]:
|
||||||
|
try:
|
||||||
|
tmp = tempfile.NamedTemporaryFile(suffix=".mp3", delete=False)
|
||||||
|
tmp_path = Path(tmp.name)
|
||||||
|
tmp.close()
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
cmd = [
|
||||||
|
"ffmpeg",
|
||||||
|
"-y",
|
||||||
|
"-i",
|
||||||
|
str(src),
|
||||||
|
"-vn",
|
||||||
|
"-c:a",
|
||||||
|
"libmp3lame",
|
||||||
|
"-q:a",
|
||||||
|
"2",
|
||||||
|
str(tmp_path),
|
||||||
|
]
|
||||||
|
proc = run(cmd)
|
||||||
|
if proc.returncode != 0:
|
||||||
|
try:
|
||||||
|
tmp_path.unlink(missing_ok=True) # type: ignore[arg-type]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
return tmp_path
|
||||||
|
|
||||||
|
|
||||||
|
def push_file(local_path: Path, remote_path: str, size: int) -> bool:
|
||||||
|
# Skip if same size exists
|
||||||
|
rsz = remote_size(remote_path)
|
||||||
|
if rsz is not None and rsz == size:
|
||||||
|
print(f"[=] Skip (same size): {local_path} -> {remote_path}")
|
||||||
|
return True
|
||||||
|
ensure_remote_dir(remote_path)
|
||||||
|
proc = run(["adb", "push", "-p", str(local_path), remote_path])
|
||||||
|
if proc.returncode == 0:
|
||||||
|
print(f"[+] Pushed: {local_path} -> {remote_path}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"[!] Push failed: {local_path}\n{proc.stderr}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def sync_latest_batch():
|
||||||
|
entries = gather_music_files()
|
||||||
|
if not entries:
|
||||||
|
print("[i] No music files found.")
|
||||||
|
return
|
||||||
|
batch = select_up_to_size(entries, SIZE_LIMIT_BYTES)
|
||||||
|
print(f"[i] Selected {len(batch)} files up to {SIZE_LIMIT_BYTES/(1024**3):.2f} GiB")
|
||||||
|
for root, p, sz in batch:
|
||||||
|
try:
|
||||||
|
rel = p.relative_to(root)
|
||||||
|
except Exception:
|
||||||
|
rel = p.name # fallback
|
||||||
|
if p.suffix.lower() == ".flac":
|
||||||
|
if not have_ffmpeg():
|
||||||
|
print(f"[!] ffmpeg not available, skipping: {p}")
|
||||||
|
continue
|
||||||
|
mp3_tmp = transcode_flac_to_mp3(p)
|
||||||
|
if not mp3_tmp:
|
||||||
|
print(f"[!] Transcode failed, skipping: {p}")
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
if isinstance(rel, Path):
|
||||||
|
rel_mp3 = rel.with_suffix(".mp3")
|
||||||
|
remote = f"{DEST_ON_PHONE.rstrip('/')}/{rel_mp3.as_posix()}"
|
||||||
|
else:
|
||||||
|
remote = f"{DEST_ON_PHONE.rstrip('/')}/{Path(rel).with_suffix('.mp3').as_posix()}"
|
||||||
|
msz = mp3_tmp.stat().st_size
|
||||||
|
push_file(mp3_tmp, remote, msz)
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
mp3_tmp.unlink()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
remote = f"{DEST_ON_PHONE.rstrip('/')}/{rel.as_posix()}"
|
||||||
|
push_file(p, remote, sz)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("[i] adb-music-sync daemon starting...")
|
||||||
|
ensure_adb_server()
|
||||||
|
connected_prev = False
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
ensure_adb_server()
|
||||||
|
adb_connect_if_needed()
|
||||||
|
connected = is_agm_connected()
|
||||||
|
if connected and not connected_prev:
|
||||||
|
print("[+] AGM M7 connected. Starting sync of latest ~7 GiB...")
|
||||||
|
sync_latest_batch()
|
||||||
|
elif not connected and connected_prev:
|
||||||
|
print("[-] AGM M7 disconnected.")
|
||||||
|
connected_prev = connected
|
||||||
|
time.sleep(POLL_INTERVAL_SEC)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("[i] Exiting on user interrupt.")
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[!] Error in main loop: {e}")
|
||||||
|
time.sleep(POLL_INTERVAL_SEC)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
78
adb-music-sync/install.sh
Normal file
78
adb-music-sync/install.sh
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SILENT=false
|
||||||
|
LOG_PREFIX="[adb-music-sync]"
|
||||||
|
|
||||||
|
PYTHON_SCRIPT="$HOME/.linux-env/adb-music-sync/adb-music-sync.py"
|
||||||
|
INSTALL_TARGET="$HOME/.local/bin/adb-music-sync.py"
|
||||||
|
AUTOSTART_DIR="$HOME/.config/autostart"
|
||||||
|
AUTOSTART_FILE="$AUTOSTART_DIR/adb-music-sync.desktop"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
if [ "$SILENT" = true ]; then return; fi
|
||||||
|
echo "$LOG_PREFIX $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_and_install_deps() {
|
||||||
|
# Minimal dependency: adb
|
||||||
|
if ! command -v adb >/dev/null 2>&1; then
|
||||||
|
if command -v apt >/dev/null 2>&1; then
|
||||||
|
log "[+] Installation d'adb (apt) ..."
|
||||||
|
sudo apt update -y && sudo apt install -y adb
|
||||||
|
elif command -v dnf >/dev/null 2>&1; then
|
||||||
|
log "[+] Installation d'adb (dnf) ..."
|
||||||
|
sudo dnf install -y android-tools
|
||||||
|
elif command -v pacman >/dev/null 2>&1; then
|
||||||
|
log "[+] Installation d'adb (pacman) ..."
|
||||||
|
sudo pacman -Sy --noconfirm android-tools
|
||||||
|
else
|
||||||
|
log "[!] adb introuvable et gestionnaire de paquets inconnu. Installez adb manuellement."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_script() {
|
||||||
|
check_and_install_deps
|
||||||
|
|
||||||
|
log "[+] Copie du script Python..."
|
||||||
|
mkdir -p "$(dirname "$INSTALL_TARGET")"
|
||||||
|
cp "$PYTHON_SCRIPT" "$INSTALL_TARGET"
|
||||||
|
chmod +x "$INSTALL_TARGET"
|
||||||
|
|
||||||
|
log "[+] Création du fichier autostart..."
|
||||||
|
mkdir -p "$AUTOSTART_DIR"
|
||||||
|
cat > "$AUTOSTART_FILE" <<EOF
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Exec=$INSTALL_TARGET
|
||||||
|
Hidden=false
|
||||||
|
NoDisplay=false
|
||||||
|
X-GNOME-Autostart-enabled=true
|
||||||
|
Name=ADB Music Sync
|
||||||
|
Comment=Lance la synchronisation de ~5GiB de musique vers l'AGM M7 à la connexion ADB
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log "[✓] Installation terminée. Le script se lancera automatiquement à l'ouverture de session."
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstall_script() {
|
||||||
|
log "[+] Suppression du script Python et autostart..."
|
||||||
|
rm -f "$INSTALL_TARGET"
|
||||||
|
rm -f "$AUTOSTART_FILE"
|
||||||
|
log "[✓] Désinstallation terminée."
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
uninstall)
|
||||||
|
uninstall_script
|
||||||
|
;;
|
||||||
|
silent)
|
||||||
|
SILENT=true
|
||||||
|
uninstall_script &>/dev/null || true
|
||||||
|
install_script &>/dev/null
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
install_script
|
||||||
|
;;
|
||||||
|
esac
|
||||||
11
applications/install.sh
Normal file
11
applications/install.sh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# desktop apps
|
||||||
|
cp ~/.linux-env/applications/*/*.desktop ~/.local/share/applications/
|
||||||
|
cp ~/.linux-env/applications/*/*.sh ~/.local/bin/
|
||||||
|
cp ~/.linux-env/applications/*/*.svg ~/.local/share/icons/
|
||||||
|
|
||||||
|
chmod +x ~/.local/share/applications/*.desktop
|
||||||
|
chmod +x ~/.local/bin/*.sh
|
||||||
|
|
||||||
|
update-desktop-database ~/.local/share/applications/
|
||||||
|
gtk-update-icon-cache ~/.local/share/icons/ # inutile sauf si tu fais un vrai thème d'icônes
|
||||||
BIN
applications/ratio-master/RM.exe
Normal file
BIN
applications/ratio-master/RM.exe
Normal file
Binary file not shown.
BIN
applications/ratio-master/blingring.torrent
Normal file
BIN
applications/ratio-master/blingring.torrent
Normal file
Binary file not shown.
7
applications/ratio-master/clients/Azureus_3050.client
Normal file
7
applications/ratio-master/clients/Azureus_3050.client
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<client name="Azureus 3.0.5.0" author="seba14.org" version="1.0" processname="azureus"> <query>info_hash={infohash}&peer_id={peerid}&supportcrypto=1&port={port}&azudp={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0{event}&numwant={numwant}&no_peer_id=1&compact=1&key={key}&azver=3</query>
|
||||||
|
<headers>User-Agent: Azureus 3.0.5.0;Windows XP;Java 1.6.0_05_nl_Connection: close_nl_Accept-Encoding: gzip_nl_Host: {host}_nl_Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2_nl_Content-type: application/x-www-form-urlencoded_nl_</headers>
|
||||||
|
<peer_id prefix="-AZ3050-" type="alphanumeric" length="12" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/BitComet0107.client
Normal file
8
applications/ratio-master/clients/BitComet0107.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="BitComet 1.07" author="seba14.org" version="1.0" processname="bitcomet">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&natmapped=1&localip={localip}&port_type=wan&uploaded={uploaded}&downloaded={downloaded}&left={left}&numwant={numwant}&compact=1&no_peer_id=1&key={key}{event}</query>
|
||||||
|
<headers>Host: {host}_nl_Connection: close_nl_Accpet: */*_nl_Accept-Encoding: gzip_nl_User-Agent: BitComet/1.7.12.3_nl_Pragma: no-cache_nl_Cache-Control: no-cache_nl_</headers>
|
||||||
|
<peer_id prefix="-BC0107-" type="random" length="12" urlencoding="true" upperCase="true" value="" />
|
||||||
|
<key type="numeric" length="5" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/BitComet0113.client
Normal file
8
applications/ratio-master/clients/BitComet0113.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="BitComet 1.13" author="seba14.org" version="1.0" processname="bitcomet">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&natmapped=1&localip={localip}&port_type=wan&uploaded={uploaded}&downloaded={downloaded}&left={left}&numwant={numwant}&compact=1&no_peer_id=1&key={key}{event}</query>
|
||||||
|
<headers>Host: {host}_nl_Connection: close_nl_Accept: */*_nl_Accept-Encoding: gzip_nl_User-Agent: BitComet/1.13.6.22_nl_Pragma: no-cache_nl_Cache-Control: no-cache_nl_</headers>
|
||||||
|
<peer_id prefix="-BC0113-" type="random" length="12" urlencoding="true" upperCase="true" value="" />
|
||||||
|
<key type="numeric" length="5" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
</client>
|
||||||
BIN
applications/ratio-master/clients/BitSpirit_v3.5.0.275.client
Normal file
BIN
applications/ratio-master/clients/BitSpirit_v3.5.0.275.client
Normal file
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="BitTorrent 6.0.3 (8642)" author="Rebound" version="1.0" processname="bittorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: BitTorrent/6030_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="M6-0-3--" type="random" length="12" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/BitTyrant_1.1.client
Normal file
8
applications/ratio-master/clients/BitTyrant_1.1.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="BitTyrant 1.1" author="res0r9lm" version="1.0" processname="Azureus">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&supportcrypto=1&port={port}&azudp={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}{event}&numwant={numwant}&no_peer_id=1&compact=1&key={key}</query>
|
||||||
|
<headers>User-Agent: AzureusBitTyrant 2.5.0.0BitTyrant;Windows XP;Java 1.5.0_10_nl_Connection: close_nl_Accept-Encoding: gzip_nl_Host: {host}_nl_Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2_nl_Proxy-Connection: keep-alive_nl_Content-type: application/x-www-form-urlencoded_nl_</headers>
|
||||||
|
<peer_id prefix="AZ2500BT" type="alphanumeric" length="12" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/Deluge_1.1.7.client
Normal file
8
applications/ratio-master/clients/Deluge_1.1.7.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="Deluge 1.1.7" author="seba14.org" version="1.0">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}{event}&key={key}&compact=1&numwant={numwant}&supportcrypto=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: Deluge 1.1.7_nl_Connection: close_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-DE1170-" type="alphanumeric" length="12" urlencoding="false" upperCase="false" value="" />
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.0"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
9
applications/ratio-master/clients/Deluge_1.1.9.client
Normal file
9
applications/ratio-master/clients/Deluge_1.1.9.client
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<client name="Deluge 1.1.9" author="seba14.org" version="1.0">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}{event}&key={key}&compact=1&numwant={numwant}&supportcrypto=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: Deluge 1.1.9_nl_Connection: close_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-DE1190-" type="printable" length="12" urlencoding="false" upperCase="false" value="" />
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="false" lowerCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.0"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
<urlencoding exceptions="." />
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/Halite 0.3.1.1.client
Normal file
8
applications/ratio-master/clients/Halite 0.3.1.1.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="Halite 0.3.1.1" author="seba14.org" version="2.0"> <query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}{event}&key={key}&compact=1&numwant={numwant}&supportcrypto=1&no_peer_id=1</query>
|
||||||
|
<headers>Accept-Encoding: gzip_nl_User-Agent: Halite v 0.3.1.1_nl_Host: {host}_nl_</headers>
|
||||||
|
<peer_id prefix="-HL0311-" type="printable" length="12" urlencoding="false"/>
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.0"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
<urlencoding exceptions="_-()~!*."/>
|
||||||
|
</client>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="Transmission 1.06 (Build 5136)" author="seba14.org" version="1.0">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&corrupt=0&left={left}&compact=1&numwant={numwant}&key={key}&supportcrypto=1&requirecrypto=0{event}</query>
|
||||||
|
<headers>Host: {host}_nl_Connection: close_nl_User-Agent: Transmission/1.06 (5136)_nl_</headers>
|
||||||
|
<peer_id prefix="-TR1060-" type="alphanumeric" length="12" urlencoding="false" lowerCase="true" value=""/>
|
||||||
|
<key type="alphanumeric" length="10" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/Vuze_4202.client
Normal file
8
applications/ratio-master/clients/Vuze_4202.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="Vuze 4.2.0.2" author="seba14.org" version="1.0" processname="azureus"> <query>info_hash={infohash}&peer_id={peerid}&supportcrypto=1&port={port}&azudp={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0{event}&numwant={numwant}&no_peer_id=1&compact=1&key={key}&azver=3</query>
|
||||||
|
<headers>User-Agent: Azureus 4.2.0.2;Windows XP;Java 1.6.0_13_nl_Connection: close_nl_Accept-Encoding: gzip_nl_Host: {host}_nl_Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2_nl_</headers>
|
||||||
|
<peer_id prefix="-AZ4202-" type="alphanumeric" length="12" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
<urlencoding exceptions="*-._" />
|
||||||
|
</client>
|
||||||
9
applications/ratio-master/clients/Vuze_4204.client
Normal file
9
applications/ratio-master/clients/Vuze_4204.client
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<client name="Vuze 4.2.0.4" author="Ratiomaster" version="1.0" processname="azureus">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&supportcrypto=1&port={port}&azudp={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0{event}&numwant={numwant}&no_peer_id=1&compact=1&key={key}&azver=3</query>
|
||||||
|
<headers>User-Agent: Azureus 4.2.0.4;{osver};{javaver}_nl_Connection: close_nl_Accept-Encoding: gzip_nl_Host: {host}_nl_Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2_nl_</headers>
|
||||||
|
<peer_id prefix="-AZ4204-" type="alphanumeric" length="12" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
<urlencoding exceptions="*-._" />
|
||||||
|
</client>
|
||||||
9
applications/ratio-master/clients/Vuze_4208.client
Normal file
9
applications/ratio-master/clients/Vuze_4208.client
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<client name="Vuze 4.2.0.8" author="KTC" version="1.0" processname="azureus">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&supportcrypto=1&port={port}&azudp={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0{event}&numwant={numwant}&no_peer_id=1&compact=1&key={key}&azver=3</query>
|
||||||
|
<headers>User-Agent: Azureus 4.2.0.8;{osver};{javaver}_nl_Connection: close_nl_Accept-Encoding: gzip_nl_Host: {host}_nl_Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2_nl_</headers>
|
||||||
|
<peer_id prefix="-AZ4208-" type="alphanumeric" length="12" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
<urlencoding exceptions="*-._" />
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/Vuze_4306.client
Normal file
8
applications/ratio-master/clients/Vuze_4306.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="Vuze 4.3.0.6" author="seba14.org" version="1.0" processname="azureus"> <query>info_hash={infohash}&peer_id={peerid}&supportcrypto=1&port={port}&azudp={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0{event}&numwant={numwant}&no_peer_id=1&compact=1&key={key}&azver=3</query>
|
||||||
|
<headers>User-Agent: Azureus 4.3.0.6;{osver};{javaver}_nl_Connection: close_nl_Accept-Encoding: gzip_nl_Host: {host}_nl_Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2_nl_</headers>
|
||||||
|
<peer_id prefix="-AZ4306-" type="alphanumeric" length="12" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
<urlencoding exceptions="*-._" />
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/Vuze_4404-Fixed.client
Normal file
8
applications/ratio-master/clients/Vuze_4404-Fixed.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="Vuze 4.4.0.4" author="seba14.org" version="2.0" processname="azureus"> <query>info_hash={infohash}&peer_id={peerid}&supportcrypto=1&port={port}&azudp={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0{event}&numwant={numwant}&no_peer_id=1&compact=1&key={key}&azver=3</query>
|
||||||
|
<headers>User-Agent: Azureus 4.4.0.4;{osver};{javaver}_nl_Connection: close_nl_Accept-Encoding: gzip_nl_Host: {host}_nl_Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2_nl_</headers>
|
||||||
|
<peer_id prefix="-AZ4404-" type="alphanumeric" length="12" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
<urlencoding exceptions="*-._" />
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/Vuze_4500-Fixed.client
Normal file
8
applications/ratio-master/clients/Vuze_4500-Fixed.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="Vuze 4.5.0.0" author="seba14.org" version="2.0" processname="azureus"> <query>info_hash={infohash}&peer_id={peerid}&supportcrypto=1&port={port}&azudp={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0{event}&numwant={numwant}&no_peer_id=1&compact=1&key={key}&azver=3</query>
|
||||||
|
<headers>User-Agent: Azureus 4.5.0.0;{osver};{javaver}_nl_Connection: close_nl_Accept-Encoding: gzip_nl_Host: {host}_nl_Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2_nl_</headers>
|
||||||
|
<peer_id prefix="-AZ4500-" type="alphanumeric" length="12" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<key type="alphanumeric" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
<urlencoding exceptions="*-._" />
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/bitlord_1.1.client
Normal file
8
applications/ratio-master/clients/bitlord_1.1.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="BitLord 1.1" author="Ratiomaster" version="1.0" processname="bitlord">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&natmapped=1&uploaded={uploaded}&downloaded={downloaded}&left={left}&numwant={numwant}&compact=1&no_peer_id=1&key={key}{event}</query>
|
||||||
|
<headers>User-Agent: BitTorrent/3.4.2_nl_Connection: close_nl_Accept-Encoding: gzip, deflate_nl_Host: {host}_nl_Cache-Control: no-cache_nl_</headers>
|
||||||
|
<peer_id prefix="exbc%01%01LORDCz%03%92" type="random" length="6" urlencoding="true" upperCase="true" value="" />
|
||||||
|
<key type="numeric" length="4" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.0"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
</client>
|
||||||
8
applications/ratio-master/clients/burst_310b.client
Normal file
8
applications/ratio-master/clients/burst_310b.client
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="Burst 3.1.0b" author="RatioMaster" version="1.0" processname="btdownloadheadless">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&key={key}&uploaded={uploaded}&downloaded={downloaded}&left={left}&compact=1{event}</query>
|
||||||
|
<headers>Host: {host}_nl_Accept-Encoding: gzip_nl_User-Agent: BitTorrent/brst1.1.3_nl_</headers>
|
||||||
|
<peer_id prefix="Mbrst1-1-3" type="hex" length="10" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="false" value=""/>
|
||||||
|
<protocol value="HTTP/1.0"/>
|
||||||
|
<hash upperCase="true"/>
|
||||||
|
</client>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="uTorrent 1.7.7 build (8179)" author="uk10" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/1770_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1770-%f3%9f" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="uTorrent 1.8.1 (build 12616)" author="SpongeBob101" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/1810_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1810-H1" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="uTorrent 1.8.1 (build 12639)" author="MurderTR" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/1810_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1810-_1" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="uTorrent 1.8.2 (build 15227)" author="Gox" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/1820_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1820-%7b%3b" type="random" length="10" urlencoding="true" upperCase="false" value="" />
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="utorrent 1.8.2 (build 14153)" author="rogeruk" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>User-Agent: uTorrent/1820_nl_Accept-Encoding: gzip, deflate_nl_Host: {host}_nl_Cache-Control: no-cache_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1820-I7" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="utorrent 1.8.2 (build 14458)" author="MurderTR" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>User-Agent: uTorrent/1820_nl_Accept-Encoding: gzip, deflate_nl_Host: {host}_nl_Cache-Control: no-cache_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1820-z8" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="uTorrent 1.8.2 Build (15167)" author="seba14.org" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/1820_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1820-%3f%3b" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<client name="uTorrent 1.8.3 Build (15728)" author="seba14.org" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/1830(15728)_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1830-p%3d" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
<urlencoding exceptions="_()~._-" />
|
||||||
|
</client>
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,9 @@
|
|||||||
|
<client name="uTorrent 1.8.4 Build (16150)" author="seba14.org" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/1840(16150)_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1840-%16%3f" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
<urlencoding exceptions="_-~!*."/>
|
||||||
|
</client>
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
<client name="uTorrent 1.8 (build 11813)" author="SpongeBob101" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/1800_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT1800-%25." type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
</client>
|
||||||
Binary file not shown.
@@ -0,0 +1,10 @@
|
|||||||
|
<client name="uTorrent 2.0.4 Build (21431)" author="CoreCore and Anon" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/2040(21431)_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT2040-%b7S" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
<urlencoding exceptions="-._~"/>
|
||||||
|
<numwant value="200" randomize="false"/>
|
||||||
|
</client>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<client name="uTorrent 2.0.4 Build (21515)" author="CoreCore and Anon" version="1.0" processname="utorrent">
|
||||||
|
<query>info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}{event}&numwant={numwant}&compact=1&no_peer_id=1</query>
|
||||||
|
<headers>Host: {host}_nl_User-Agent: uTorrent/2040(21515)_nl_Accept-Encoding: gzip_nl_</headers>
|
||||||
|
<peer_id prefix="-UT2040-%0bT" type="random" length="10" urlencoding="true" upperCase="false" value=""/>
|
||||||
|
<key type="hex" length="8" urlencoding="false" upperCase="true" value=""/>
|
||||||
|
<protocol value="HTTP/1.1"/>
|
||||||
|
<hash upperCase="false"/>
|
||||||
|
<urlencoding exceptions="-._~"/>
|
||||||
|
<numwant value="200" randomize="false"/>
|
||||||
|
</client>
|
||||||
BIN
applications/ratio-master/lng/1english.lng
Normal file
BIN
applications/ratio-master/lng/1english.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/Arabic.lng
Normal file
BIN
applications/ratio-master/lng/Arabic.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/Armenian.lng
Normal file
BIN
applications/ratio-master/lng/Armenian.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/Danish.lng
Normal file
BIN
applications/ratio-master/lng/Danish.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/Korean.lng
Normal file
BIN
applications/ratio-master/lng/Korean.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/bulgarian.lng
Normal file
BIN
applications/ratio-master/lng/bulgarian.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/chinese.lng
Normal file
BIN
applications/ratio-master/lng/chinese.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/french.lng
Normal file
BIN
applications/ratio-master/lng/french.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/german.lng
Normal file
BIN
applications/ratio-master/lng/german.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/hebrew.lng
Normal file
BIN
applications/ratio-master/lng/hebrew.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/hungarian.lng
Normal file
BIN
applications/ratio-master/lng/hungarian.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/italian.lng
Normal file
BIN
applications/ratio-master/lng/italian.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/lithuanian.lng
Normal file
BIN
applications/ratio-master/lng/lithuanian.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/polish.lng
Normal file
BIN
applications/ratio-master/lng/polish.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/portuguese.lng
Normal file
BIN
applications/ratio-master/lng/portuguese.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/romanian.lng
Normal file
BIN
applications/ratio-master/lng/romanian.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/russian.lng
Normal file
BIN
applications/ratio-master/lng/russian.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/slovenian.lng
Normal file
BIN
applications/ratio-master/lng/slovenian.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/spanish.lng
Normal file
BIN
applications/ratio-master/lng/spanish.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/swedish.lng
Normal file
BIN
applications/ratio-master/lng/swedish.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/thai.lng
Normal file
BIN
applications/ratio-master/lng/thai.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/turkish.lng
Normal file
BIN
applications/ratio-master/lng/turkish.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/ukrainian.lng
Normal file
BIN
applications/ratio-master/lng/ukrainian.lng
Normal file
Binary file not shown.
BIN
applications/ratio-master/lng/vietnamese.lng
Normal file
BIN
applications/ratio-master/lng/vietnamese.lng
Normal file
Binary file not shown.
10
applications/ratio-master/ratio-master.desktop
Executable file
10
applications/ratio-master/ratio-master.desktop
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=RatioMaster
|
||||||
|
Comment=Ratio spoofing tool for torrents
|
||||||
|
Exec=wine /home/valere/.local/bin/RatioMaster/RM.exe
|
||||||
|
Path=/home/valere/.local/bin/RatioMaster
|
||||||
|
Icon=/home/valere/.local/bin/RatioMaster/logo.svg
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
Categories=Network;P2P;
|
||||||
|
StartupNotify=true
|
||||||
65
applications/ratio-master/ratio-master.svg
Normal file
65
applications/ratio-master/ratio-master.svg
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="773.29401"
|
||||||
|
height="773.29401"
|
||||||
|
viewBox="0 -28.5 247.45409 247.45409"
|
||||||
|
version="1.1"
|
||||||
|
preserveAspectRatio="xMidYMid"
|
||||||
|
id="svg3"
|
||||||
|
sodipodi:docname="logo.svg"
|
||||||
|
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs3" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview3"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#505050"
|
||||||
|
inkscape:zoom="0.48911087"
|
||||||
|
inkscape:cx="-24.534315"
|
||||||
|
inkscape:cy="80.758786"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1132"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg3" />
|
||||||
|
<g
|
||||||
|
id="g3"
|
||||||
|
transform="translate(5.5656067,239.04617)">
|
||||||
|
<rect
|
||||||
|
style="fill:#eb001b;fill-opacity:1;stroke-width:11.3833;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2.3;paint-order:fill markers stroke"
|
||||||
|
id="rect3"
|
||||||
|
width="112.2394"
|
||||||
|
height="112.45076"
|
||||||
|
x="-105.21542"
|
||||||
|
y="-209.79523"
|
||||||
|
transform="rotate(45)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f79e1b;fill-opacity:1;stroke-width:11.3833;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2.3;paint-order:fill markers stroke"
|
||||||
|
id="rect3-6"
|
||||||
|
width="112.2394"
|
||||||
|
height="112.45076"
|
||||||
|
x="-42.293499"
|
||||||
|
y="-272.13583"
|
||||||
|
transform="rotate(45)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ff5f00;fill-opacity:1;stroke-width:5.03456;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2.3;paint-order:fill markers stroke"
|
||||||
|
id="rect3-6-5"
|
||||||
|
width="49.315277"
|
||||||
|
height="50.120525"
|
||||||
|
x="-42.293499"
|
||||||
|
y="-209.80559"
|
||||||
|
transform="rotate(45)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
42
applications/ratio-master/ratiomaster.config
Normal file
42
applications/ratio-master/ratiomaster.config
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ApplicationSettings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<textStopMinLeecher>0</textStopMinLeecher>
|
||||||
|
<updateAnnounceParamsOnStart>true</updateAnnounceParamsOnStart>
|
||||||
|
<finishedPercent>100</finishedPercent>
|
||||||
|
<uploadRate>55003.37</uploadRate>
|
||||||
|
<downloadRate>0.21</downloadRate>
|
||||||
|
<interval>1800</interval>
|
||||||
|
<TorrentClientsIndex>11</TorrentClientsIndex>
|
||||||
|
<checkLogEnabled>true</checkLogEnabled>
|
||||||
|
<checkRequestScrap>true</checkRequestScrap>
|
||||||
|
<checkShowTrayBaloon>true</checkShowTrayBaloon>
|
||||||
|
<checkTCPListen>false</checkTCPListen>
|
||||||
|
<customPort />
|
||||||
|
<customKey>WMAAIhLqVx</customKey>
|
||||||
|
<customPeersNum />
|
||||||
|
<customPeerID>-TR1060-pauut3h9agwn</customPeerID>
|
||||||
|
<textProxyHost />
|
||||||
|
<textProxyPort />
|
||||||
|
<textProxyPass />
|
||||||
|
<textProxyUser />
|
||||||
|
<comboProxyTypeIndex>0</comboProxyTypeIndex>
|
||||||
|
<checkNewVersion>true</checkNewVersion>
|
||||||
|
<checkRandomUpload>true</checkRandomUpload>
|
||||||
|
<checkRandomDownload>true</checkRandomDownload>
|
||||||
|
<RandomUploadFrom>50000</RandomUploadFrom>
|
||||||
|
<RandomUploadTo>100000</RandomUploadTo>
|
||||||
|
<RandomDownloadFrom>0</RandomDownloadFrom>
|
||||||
|
<RandomDownloadTo>4</RandomDownloadTo>
|
||||||
|
<ignoreFailureReason>false</ignoreFailureReason>
|
||||||
|
<torrentFilePath>C:\users\valere\Desktop\Downloads\l.horloger.de.saint-paul.1974.VOF RESTAUREE.1080p.BDrip.x265.FLAC-AZAZE.mkv.torrent</torrentFilePath>
|
||||||
|
<torrentHash>1164387932F4CB6B1267B3ABA7E0A4CD26593E14</torrentHash>
|
||||||
|
<stopProcessActionBox>0</stopProcessActionBox>
|
||||||
|
<stopProcessValue>1000</stopProcessValue>
|
||||||
|
<stopProcessUnitsBox>-1</stopProcessUnitsBox>
|
||||||
|
<selectedLanguage>Z:\home\valere\.local\bin\RatioMaster\lng\1english.lng</selectedLanguage>
|
||||||
|
<bindToIp>default</bindToIp>
|
||||||
|
<minimizeTotray>true</minimizeTotray>
|
||||||
|
<ignoreTimeout>false</ignoreTimeout>
|
||||||
|
<useUPnP>false</useUPnP>
|
||||||
|
<savePeerList>false</savePeerList>
|
||||||
|
</ApplicationSettings>
|
||||||
0
applications/ratio-master/rm_updates.xml
Normal file
0
applications/ratio-master/rm_updates.xml
Normal file
BIN
applications/ratio-master/torrent.torrent
Normal file
BIN
applications/ratio-master/torrent.torrent
Normal file
Binary file not shown.
107
bashrc/.bashrc
Normal file
107
bashrc/.bashrc
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
# .linux-env
|
||||||
|
VIDEO_DIR_LOCAL="/home/valere/Downloads"
|
||||||
|
IMAGE_DIR_LOCAL="/home/valere/Downloads"
|
||||||
|
MUSIC_DIR_LOCAL="/home/valere/evilspins/web/mnt/media/files/music"
|
||||||
|
|
||||||
|
|
||||||
|
VIDEO_PATH="/home/root/media/video/autre"
|
||||||
|
IMAGE_PATH="/home/root/media/image/screenshit"
|
||||||
|
MUSIC_DIR="/home/root/media/files/music"
|
||||||
|
|
||||||
|
dlvideo() {
|
||||||
|
cd "$VIDEO_DIR" || return
|
||||||
|
pip install -U yt-dlp
|
||||||
|
yt-dlp -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4" --merge-output-format mp4 "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
dlimage() {
|
||||||
|
wget -P "$IMAGE_DIR" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
dlcover() {
|
||||||
|
query_or_file="$1"
|
||||||
|
manual_url="$2"
|
||||||
|
|
||||||
|
|
||||||
|
if [ -f "$query_or_file" ]; then
|
||||||
|
file="$query_or_file"
|
||||||
|
elif echo "$query_or_file" | grep -q '%(ext)'; then
|
||||||
|
file="$query_or_file"
|
||||||
|
else
|
||||||
|
file=$(find "$MUSIC_DIR" -type f \
|
||||||
|
\( -iname "*${query_or_file}*.mp3" -o -iname "*${query_or_file}*.m4a" -o -iname "*${query_or_file}*.flac" -o -iname "*${query_or_file}*.wav" -o -iname "*${query_or_file}*.ogg" \) \
|
||||||
|
| head -n 1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$file" ]; then
|
||||||
|
echo "❌ Aucun fichier trouvé pour: $query_or_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
base="${file%.*}"
|
||||||
|
|
||||||
|
if [ -n "$manual_url" ]; then
|
||||||
|
curl -s "$manual_url" -o "${base}.jpg"
|
||||||
|
echo "✅ ${base}.jpg saved from manual URL (fichier: $file)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
artist_raw=$(echo "$base" | awk -F'__' '{print $2}')
|
||||||
|
title_raw=$(echo "$base" | awk -F'__' '{for(i=3;i<=NF;i++){printf (i>3?" ":""); printf $i}}')
|
||||||
|
artist=$(echo "$artist_raw" | tr '_' ' ')
|
||||||
|
title=$(echo "$title_raw" | tr '_' ' ')
|
||||||
|
query_enc=$(jq -rn --arg s "$artist $title" '$s|@uri')
|
||||||
|
|
||||||
|
it_url="https://itunes.apple.com/search?term=${query_enc}&entity=song&limit=1"
|
||||||
|
art=$(curl -s "$it_url" | jq -r '.results[0].artworkUrl100')
|
||||||
|
if [ -n "$art" ] && [ "$art" != "null" ]; then
|
||||||
|
art_hi=$(echo "$art" | sed 's/100x100bb/1000x1000bb/')
|
||||||
|
curl -s "$art_hi" -o "${base}.jpg"
|
||||||
|
echo "✅ ${base}.jpg saved from iTunes (fichier: $file)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
api_key="5ae5d1212599f96ffa799e21da1b2a7a38274c94bb5ae8ad26ce8d5b08528aaa"
|
||||||
|
url=$(curl -s "https://serpapi.com/search.json?engine=google&q=${query_enc}&tbm=isch&api_key=${api_key}" \
|
||||||
|
| jq -r '.images_results[0].original')
|
||||||
|
|
||||||
|
if [ -n "$url" ] && [ "$url" != "null" ]; then
|
||||||
|
curl -s "$url" -o "${base}.jpg"
|
||||||
|
echo "✅ ${base}.jpg saved from Google Images (fichier: $file)"
|
||||||
|
else
|
||||||
|
echo "❌ No cover found for $artist - $title (fichier: $file)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
dlmusic() {
|
||||||
|
mkdir -p "$MUSIC_PATH"
|
||||||
|
|
||||||
|
NOW=$(date +"%Y%m%d%H")
|
||||||
|
URL="$1"
|
||||||
|
|
||||||
|
# Récupère le titre
|
||||||
|
TITLE=$(yt-dlp --get-title "$URL")
|
||||||
|
|
||||||
|
# Transforme le titre pour le nom de fichier
|
||||||
|
SAFE_TITLE="${TITLE// - /__}"
|
||||||
|
SAFE_TITLE="${SAFE_TITLE// /_}"
|
||||||
|
|
||||||
|
TRACK_NAME="$MUSIC_PATH/${NOW}__${SAFE_TITLE}.%(ext)s"
|
||||||
|
|
||||||
|
# Téléchargement
|
||||||
|
yt-dlp -x --audio-format mp3 -o $TRACK_NAME "$URL"
|
||||||
|
dlcover $TRACK_NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
search() {
|
||||||
|
find ./ -iname "*$1*"
|
||||||
|
}
|
||||||
|
|
||||||
|
searchinside() {
|
||||||
|
grep -rwl "$1" ./
|
||||||
|
}
|
||||||
|
|
||||||
|
alias evilsync='rsync -avz --delete -e ssh $MUSIC_DIR_LOCAL root@erudi.fr:$MUSIC_DIR'
|
||||||
|
alias evildiff='rsync -avzn --delete -e ssh $MUSIC_DIR_LOCAL root@erudi.fr:$MUSIC_DIR'
|
||||||
|
|
||||||
|
# end .linux-env
|
||||||
4
bashrc/install.sh
Normal file
4
bashrc/install.sh
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
sed -i '/# .linux-env/,/# .linux-env/d' ~/.bashrc
|
||||||
|
cat ~/.linux-env/bashrc/.bashrc >> ~/.bashrc
|
||||||
94
gamecube-pad/gamecube-pad.py
Normal file
94
gamecube-pad/gamecube-pad.py
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import evdev
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
|
||||||
|
DEVICE_NAMES = ["8BitDo NGC Modkit"]
|
||||||
|
BUTTON_MAP = {
|
||||||
|
"304": "Return", # A
|
||||||
|
"305": None, # B (non utilisé)
|
||||||
|
"311": "Alt_L", # R
|
||||||
|
"307": "Right", # X
|
||||||
|
"308": "Left", # Y
|
||||||
|
# 318 (BTN_THUMBR) sera géré à part
|
||||||
|
}
|
||||||
|
|
||||||
|
def find_device():
|
||||||
|
for path in evdev.list_devices():
|
||||||
|
try:
|
||||||
|
dev = evdev.InputDevice(path)
|
||||||
|
if any(dn in dev.name for dn in DEVICE_NAMES):
|
||||||
|
return path
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_dolphin_running():
|
||||||
|
try:
|
||||||
|
output = subprocess.check_output(["flatpak", "ps"]).decode()
|
||||||
|
return "org.DolphinEmu.dolphin-emu" in output
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def press_key(key, press):
|
||||||
|
# press=True -> key down, press=False -> key up
|
||||||
|
action = "keydown" if press else "keyup"
|
||||||
|
subprocess.run(["xdotool", action, key])
|
||||||
|
|
||||||
|
def handle_device(dev_path):
|
||||||
|
dev = evdev.InputDevice(dev_path)
|
||||||
|
try:
|
||||||
|
for event in dev.read_loop():
|
||||||
|
if event.type != evdev.ecodes.EV_KEY:
|
||||||
|
continue
|
||||||
|
|
||||||
|
key_code = str(event.code)
|
||||||
|
|
||||||
|
# cas spécial : joystick jaune (BTN_THUMBR, code 318)
|
||||||
|
if key_code == "318" and event.value == 1: # pression
|
||||||
|
press_key("Alt_L", True)
|
||||||
|
time.sleep(0.02)
|
||||||
|
press_key("Escape", True)
|
||||||
|
time.sleep(0.05)
|
||||||
|
press_key("Escape", False)
|
||||||
|
press_key("Alt_L", False)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if key_code in BUTTON_MAP:
|
||||||
|
mapped_key = BUTTON_MAP[key_code]
|
||||||
|
if mapped_key is not None:
|
||||||
|
press_key(mapped_key, event.value == 1)
|
||||||
|
|
||||||
|
except OSError:
|
||||||
|
dev.close()
|
||||||
|
raise
|
||||||
|
|
||||||
|
def main():
|
||||||
|
connected = False
|
||||||
|
time.sleep(5) # délai pour que le serveur graphique soit prêt
|
||||||
|
while True:
|
||||||
|
dev_path = find_device()
|
||||||
|
if dev_path and not connected:
|
||||||
|
print(f"[+] Manette connectée: {dev_path}")
|
||||||
|
connected = True
|
||||||
|
if not is_dolphin_running():
|
||||||
|
try:
|
||||||
|
subprocess.Popen(["flatpak", "run", "org.DolphinEmu.dolphin-emu"])
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[!] Impossible de lancer Dolphin: {e}")
|
||||||
|
try:
|
||||||
|
handle_device(dev_path)
|
||||||
|
except OSError:
|
||||||
|
print("[-] Manette déconnectée")
|
||||||
|
connected = False
|
||||||
|
try:
|
||||||
|
subprocess.Popen(["flatpak", "kill", "org.DolphinEmu.dolphin-emu"])
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[!] Impossible de tuer Dolphin: {e}")
|
||||||
|
elif not dev_path and connected:
|
||||||
|
print("[-] Manette déconnectée")
|
||||||
|
connected = False
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SERVICE_NAME="gamecube-pad.service"
|
|
||||||
SERVICE_PATH="/etc/systemd/system/$SERVICE_NAME"
|
|
||||||
PYTHON_SCRIPT="/home/$USER/.local/bin/gamecube-pad.py"
|
|
||||||
|
|
||||||
install_service() {
|
|
||||||
echo "[+] Installation des dépendances..."
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install -y python3-evdev python3-uinput xdotool wmctrl
|
|
||||||
|
|
||||||
echo "[+] Création du script Python watcher..."
|
|
||||||
cat > "$PYTHON_SCRIPT" <<'EOF'
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
import evdev
|
|
||||||
import uinput
|
|
||||||
import subprocess
|
|
||||||
import time
|
|
||||||
|
|
||||||
DEVICE_NAMES = ["8BitDo NGC Modkit"]
|
|
||||||
AXIS_MAP = {
|
|
||||||
"ABS_X": ("KEY_LEFT", "KEY_RIGHT"),
|
|
||||||
"ABS_Y": ("KEY_UP", "KEY_DOWN")
|
|
||||||
}
|
|
||||||
BUTTON_MAP = {
|
|
||||||
"304": "KEY_ENTER",
|
|
||||||
"305": "KEY_ESC",
|
|
||||||
"311": "KEY_LEFTALT",
|
|
||||||
"308": "KEY_TAB",
|
|
||||||
"310": "KEY_LEFTCTRL",
|
|
||||||
"307": "KEY_LEFTSHIFT",
|
|
||||||
"314": "KEY_T"
|
|
||||||
}
|
|
||||||
THRESHOLD = 100
|
|
||||||
DOLPHIN_NAME = "Dolphin"
|
|
||||||
|
|
||||||
events = [
|
|
||||||
uinput.KEY_UP, uinput.KEY_DOWN, uinput.KEY_LEFT, uinput.KEY_RIGHT,
|
|
||||||
uinput.KEY_ENTER, uinput.KEY_ESC, uinput.KEY_LEFTALT, uinput.KEY_TAB,
|
|
||||||
uinput.KEY_LEFTCTRL, uinput.KEY_LEFTSHIFT, uinput.KEY_T
|
|
||||||
]
|
|
||||||
keyboard = uinput.Device(events)
|
|
||||||
|
|
||||||
def find_device():
|
|
||||||
devices = []
|
|
||||||
for path in evdev.list_devices():
|
|
||||||
try:
|
|
||||||
dev = evdev.InputDevice(path)
|
|
||||||
devices.append((path, dev.name))
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
for path, name in devices:
|
|
||||||
if any(dn in name for dn in DEVICE_NAMES):
|
|
||||||
return path
|
|
||||||
return None
|
|
||||||
|
|
||||||
def handle_device(dev_path):
|
|
||||||
dev = evdev.InputDevice(dev_path)
|
|
||||||
abs_center = {axis: dev.absinfo(axis).value for axis in (evdev.ecodes.ABS_X, evdev.ecodes.ABS_Y)}
|
|
||||||
try:
|
|
||||||
for event in dev.read_loop():
|
|
||||||
if event.type == evdev.ecodes.EV_KEY:
|
|
||||||
key_code = str(event.code)
|
|
||||||
if key_code in BUTTON_MAP:
|
|
||||||
keyboard.emit(getattr(uinput, BUTTON_MAP[key_code]), event.value)
|
|
||||||
if event.type == evdev.ecodes.EV_ABS:
|
|
||||||
axis = evdev.ecodes.ABS[event.code]
|
|
||||||
val = event.value
|
|
||||||
neg_key, pos_key = AXIS_MAP.get(axis, (None, None))
|
|
||||||
if neg_key and pos_key:
|
|
||||||
keyboard.emit(getattr(uinput, neg_key), int(val < abs_center[event.code]-THRESHOLD))
|
|
||||||
keyboard.emit(getattr(uinput, pos_key), int(val > abs_center[event.code]+THRESHOLD))
|
|
||||||
except OSError:
|
|
||||||
dev.close()
|
|
||||||
raise
|
|
||||||
|
|
||||||
def main():
|
|
||||||
connected = False
|
|
||||||
while True:
|
|
||||||
dev_path = find_device()
|
|
||||||
if dev_path and not connected:
|
|
||||||
print(f"[+] Manette connectée: {dev_path}")
|
|
||||||
connected = True
|
|
||||||
try:
|
|
||||||
subprocess.Popen(["flatpak", "run", "org.DolphinEmu.dolphin-emu"]) # ou juste ["ma_commande"] si pas d'arguments
|
|
||||||
except Exception as e:
|
|
||||||
print(f"[!] Impossible de lancer la commande: {e}")
|
|
||||||
try:
|
|
||||||
handle_device(dev_path)
|
|
||||||
except OSError:
|
|
||||||
print("[-] Manette déconnectée")
|
|
||||||
connected = False
|
|
||||||
try:
|
|
||||||
subprocess.Popen(["flatpak", "kill", "org.DolphinEmu.dolphin-emu"]) # ou juste ["ma_commande"] si pas d'arguments
|
|
||||||
except Exception as e:
|
|
||||||
print(f"[!] Impossible de lancer la commande: {e}")
|
|
||||||
elif not dev_path and connected:
|
|
||||||
print("[-] Manette déconnectée")
|
|
||||||
connected = False
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
if __name__=="__main__":
|
|
||||||
main()
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x "$PYTHON_SCRIPT"
|
|
||||||
|
|
||||||
echo "[+] Création du service systemd..."
|
|
||||||
sudo tee "$SERVICE_PATH" > /dev/null <<EOF
|
|
||||||
[Unit]
|
|
||||||
Description=Pad Dolphin Watcher Service
|
|
||||||
After=graphical.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStart=/usr/bin/python3 $PYTHON_SCRIPT
|
|
||||||
WorkingDirectory=/home/$USER
|
|
||||||
Restart=always
|
|
||||||
RestartSec=3
|
|
||||||
User=$USER
|
|
||||||
Group=$USER
|
|
||||||
StandardOutput=journal+console
|
|
||||||
StandardError=journal+console
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "[+] Activation du service..."
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable "$SERVICE_NAME"
|
|
||||||
sudo systemctl restart "$SERVICE_NAME"
|
|
||||||
|
|
||||||
echo "[✓] Installation terminée. Consulte les logs avec : journalctl -u $SERVICE_NAME -f"
|
|
||||||
}
|
|
||||||
|
|
||||||
uninstall_service() {
|
|
||||||
echo "[+] Arrêt et suppression du service..."
|
|
||||||
sudo systemctl stop "$SERVICE_NAME" || true
|
|
||||||
sudo systemctl disable "$SERVICE_NAME" || true
|
|
||||||
sudo rm -f "$SERVICE_PATH"
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
rm -f "$PYTHON_SCRIPT"
|
|
||||||
echo "[✓] Désinstallation terminée."
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
uninstall)
|
|
||||||
uninstall_service
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
install_service
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
PYTHON_SCRIPT="$HOME/.local/bin/gamecube-pad.py"
|
|
||||||
SERVICE_DIR="$HOME/.config/systemd/user"
|
|
||||||
SERVICE_FILE="$SERVICE_DIR/gamecube-pad.service"
|
|
||||||
|
|
||||||
install_service() {
|
|
||||||
echo "[+] Installation des dépendances..."
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install -y python3-evdev python3-uinput xdotool wmctrl flatpak
|
|
||||||
|
|
||||||
echo "[+] Création du script Python watcher..."
|
|
||||||
mkdir -p "$(dirname "$PYTHON_SCRIPT")"
|
|
||||||
cat > "$PYTHON_SCRIPT" <<'EOF'
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
import evdev
|
|
||||||
import uinput
|
|
||||||
import subprocess
|
|
||||||
import time
|
|
||||||
import os
|
|
||||||
|
|
||||||
DEVICE_NAMES = ["8BitDo NGC Modkit"]
|
|
||||||
BUTTON_MAP = {
|
|
||||||
"304": "KEY_ENTER",
|
|
||||||
"305": "KEY_ESC",
|
|
||||||
"311": "KEY_LEFTALT",
|
|
||||||
"307": "KEY_RIGHT",
|
|
||||||
"308": "KEY_LEFT",
|
|
||||||
}
|
|
||||||
|
|
||||||
events = [
|
|
||||||
uinput.KEY_LEFT, uinput.KEY_RIGHT,
|
|
||||||
uinput.KEY_ENTER, uinput.KEY_ESC, uinput.KEY_LEFTALT
|
|
||||||
]
|
|
||||||
keyboard = uinput.Device(events)
|
|
||||||
|
|
||||||
def find_device():
|
|
||||||
for path in evdev.list_devices():
|
|
||||||
try:
|
|
||||||
dev = evdev.InputDevice(path)
|
|
||||||
if any(dn in dev.name for dn in DEVICE_NAMES):
|
|
||||||
return path
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
return None
|
|
||||||
|
|
||||||
def is_dolphin_running():
|
|
||||||
try:
|
|
||||||
output = subprocess.check_output(
|
|
||||||
["flatpak", "ps", "--columns=name"]
|
|
||||||
).decode()
|
|
||||||
return "org.DolphinEmu.dolphin-emu" in output
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def handle_device(dev_path):
|
|
||||||
dev = evdev.InputDevice(dev_path)
|
|
||||||
try:
|
|
||||||
for event in dev.read_loop():
|
|
||||||
if event.type == evdev.ecodes.EV_KEY:
|
|
||||||
key_code = str(event.code)
|
|
||||||
if key_code in BUTTON_MAP:
|
|
||||||
keyboard.emit(getattr(uinput, BUTTON_MAP[key_code]), event.value)
|
|
||||||
except OSError:
|
|
||||||
dev.close()
|
|
||||||
raise
|
|
||||||
|
|
||||||
def main():
|
|
||||||
connected = False
|
|
||||||
time.sleep(5) # délai pour que uinput et le serveur graphique soient prêts
|
|
||||||
while True:
|
|
||||||
dev_path = find_device()
|
|
||||||
if dev_path and not connected:
|
|
||||||
print(f"[+] Manette connectée: {dev_path}")
|
|
||||||
connected = True
|
|
||||||
if not is_dolphin_running():
|
|
||||||
try:
|
|
||||||
subprocess.Popen(["flatpak", "run", "org.DolphinEmu.dolphin-emu"])
|
|
||||||
except Exception as e:
|
|
||||||
print(f"[!] Impossible de lancer Dolphin: {e}")
|
|
||||||
try:
|
|
||||||
handle_device(dev_path)
|
|
||||||
except OSError:
|
|
||||||
print("[-] Manette déconnectée")
|
|
||||||
connected = False
|
|
||||||
try:
|
|
||||||
subprocess.Popen(["flatpak", "kill", "org.DolphinEmu.dolphin-emu"])
|
|
||||||
except Exception as e:
|
|
||||||
print(f"[!] Impossible de tuer Dolphin: {e}")
|
|
||||||
elif not dev_path and connected:
|
|
||||||
print("[-] Manette déconnectée")
|
|
||||||
connected = False
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x "$PYTHON_SCRIPT"
|
|
||||||
|
|
||||||
echo "[+] Création du service systemd utilisateur..."
|
|
||||||
mkdir -p "$SERVICE_DIR"
|
|
||||||
cat > "$SERVICE_FILE" <<EOF
|
|
||||||
[Unit]
|
|
||||||
Description=Pad Dolphin Watcher Service (User)
|
|
||||||
After=graphical.target dev-uinput.device
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStartPre=/bin/sleep 10
|
|
||||||
ExecStart=$PYTHON_SCRIPT
|
|
||||||
WorkingDirectory=$HOME
|
|
||||||
Restart=always
|
|
||||||
RestartSec=3
|
|
||||||
StandardOutput=journal+console
|
|
||||||
StandardError=journal+console
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "[+] Activation du service utilisateur..."
|
|
||||||
systemctl --user daemon-reload
|
|
||||||
systemctl --user enable gamecube-pad.service
|
|
||||||
systemctl --user start gamecube-pad.service
|
|
||||||
|
|
||||||
echo "[✓] Installation terminée."
|
|
||||||
echo "Consulte les logs avec : journalctl --user-unit gamecube-pad.service -f"
|
|
||||||
}
|
|
||||||
|
|
||||||
uninstall_service() {
|
|
||||||
echo "[+] Arrêt et suppression du service utilisateur..."
|
|
||||||
systemctl --user stop gamecube-pad.service || true
|
|
||||||
systemctl --user disable gamecube-pad.service || true
|
|
||||||
rm -f "$SERVICE_FILE"
|
|
||||||
rm -f "$PYTHON_SCRIPT"
|
|
||||||
systemctl --user daemon-reload
|
|
||||||
echo "[✓] Désinstallation terminée."
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
uninstall)
|
|
||||||
uninstall_service
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
install_service
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
77
gamecube-pad/install.sh
Executable file
77
gamecube-pad/install.sh
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PYTHON_SCRIPT="$HOME/.local/bin/gamecube-pad.py"
|
||||||
|
AUTOSTART_DIR="$HOME/.config/autostart"
|
||||||
|
AUTOSTART_FILE="$AUTOSTART_DIR/gamecube-pad.desktop"
|
||||||
|
|
||||||
|
SILENT=false
|
||||||
|
if [[ "$1" == "silent" ]]; then
|
||||||
|
SILENT=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
log() {
|
||||||
|
if [ "$SILENT" = false ]; then
|
||||||
|
echo "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_and_install_deps() {
|
||||||
|
for pkg in evdev uinput; do
|
||||||
|
if ! python3 -c "import $pkg" &>/dev/null; then
|
||||||
|
log "[!] Dépendance manquante : $pkg. Installation avec pip..."
|
||||||
|
python3 -m pip install --user "$pkg" &>/dev/null
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for cmd in xdotool wmctrl; do
|
||||||
|
if ! command -v "$cmd" &>/dev/null; then
|
||||||
|
log "[!] Commande manquante : $cmd. Merci de l’installer via votre gestionnaire de paquets."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
install_script() {
|
||||||
|
check_and_install_deps
|
||||||
|
|
||||||
|
log "[+] Copie du script Python..."
|
||||||
|
mkdir -p "$(dirname "$PYTHON_SCRIPT")"
|
||||||
|
cp "$HOME/.linux-env/gamecube-pad/gamecube-pad.py" "$PYTHON_SCRIPT"
|
||||||
|
chmod +x "$PYTHON_SCRIPT"
|
||||||
|
|
||||||
|
log "[+] Création du fichier autostart..."
|
||||||
|
mkdir -p "$AUTOSTART_DIR"
|
||||||
|
cat > "$AUTOSTART_FILE" <<EOF
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Exec=$PYTHON_SCRIPT
|
||||||
|
Hidden=false
|
||||||
|
NoDisplay=false
|
||||||
|
X-GNOME-Autostart-enabled=true
|
||||||
|
Name=GameCube Pad
|
||||||
|
Comment=Lance le script GameCube Pad au démarrage
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log "[✓] Installation terminée. Le script se lancera automatiquement à l'ouverture de session."
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstall_script() {
|
||||||
|
log "[+] Suppression du script Python et autostart..."
|
||||||
|
rm -f "$PYTHON_SCRIPT"
|
||||||
|
rm -f "$AUTOSTART_FILE"
|
||||||
|
log "[✓] Désinstallation terminée."
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
uninstall)
|
||||||
|
uninstall_script
|
||||||
|
;;
|
||||||
|
silent)
|
||||||
|
SILENT=true
|
||||||
|
uninstall_script &>/dev/null
|
||||||
|
install_script &>/dev/null
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
install_script
|
||||||
|
;;
|
||||||
|
esac
|
||||||
22
install.sh
22
install.sh
@@ -1,10 +1,16 @@
|
|||||||
# desktop apps
|
#!/bin/bash
|
||||||
cp ./applications/*/*.desktop ~/.local/share/applications/
|
set -e
|
||||||
cp ./applications/*/*.sh ~/.local/bin/
|
|
||||||
cp ./applications/*/*.svg ~/.local/share/icons/
|
|
||||||
|
|
||||||
chmod +x ~/.local/share/applications/*.desktop
|
# Chemin de base : le dossier où se trouve ce script
|
||||||
chmod +x ~/.local/bin/*.sh
|
BASE_DIR="$(dirname "$(realpath "$0")")"
|
||||||
|
|
||||||
update-desktop-database ~/.local/share/applications/
|
echo "[+] Recherche et exécution des install.sh..."
|
||||||
# gtk-update-icon-cache ~/.local/share/icons/ # inutile sauf si tu fais un vrai thème d’icônes
|
|
||||||
|
# Boucle récursive sur tous les fichiers install.sh
|
||||||
|
find "$BASE_DIR" -type f -name "install.sh" ! -path "$BASE_DIR/install.sh" | while read -r script; do
|
||||||
|
echo "[+] Lancement : $script"
|
||||||
|
chmod +x "$script"
|
||||||
|
"$script"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[✓] Tous les install.sh ont été exécutés."
|
||||||
|
|||||||
Reference in New Issue
Block a user