diff --git a/Seedbox/70 Manager.py b/Seedbox/70 Manager.py index 2cb6671..d550f26 100644 --- a/Seedbox/70 Manager.py +++ b/Seedbox/70 Manager.py @@ -35,16 +35,6 @@ STUCK_AFTER_HOURS = 168 # progress >= 95% ale < 100% po 7 dnech → dea # }, CLIENTS = [ -{ - "name": "UltraCC Seedbox", - "max_concurrent": 30, - "qbt": { - "host": "https://vladob.zen.usbx.me/qbittorrent", - "username": "vladob", - "password": "jCni3U6d#y4bfcm", - "VERIFY_WEBUI_CERTIFICATE": False, - }, -}, { "name": "Local qBittorrent", "max_concurrent": 30, @@ -55,6 +45,16 @@ CLIENTS = [ "password": "adminadmin", }, }, + { + "name": "UltraCC Seedbox", + "max_concurrent": 30, + "qbt": { + "host": "https://vladob.zen.usbx.me/qbittorrent", + "username": "vladob", + "password": "jCni3U6d#y4bfcm", + "VERIFY_WEBUI_CERTIFICATE": False, + }, + }, ] DB_CONFIG = { diff --git a/Seedbox/95 IncrementalImport.py b/Seedbox/95 IncrementalImport.py index f370502..8f99ce5 100644 --- a/Seedbox/95 IncrementalImport.py +++ b/Seedbox/95 IncrementalImport.py @@ -160,16 +160,21 @@ def parse_page(html): # DOWNLOAD .TORRENT FILE # ============================================================ -def download_torrent(session, url): - try: - r = session.get(url, timeout=15) - r.raise_for_status() - if len(r.content) < 20: - return None - return r.content - except Exception as e: - print(f" ⚠️ Stažení selhalo: {e}") - return None +def download_torrent(session, url, retries=10, retry_delay=10): + for attempt in range(1, retries + 1): + try: + r = session.get(url, timeout=15) + r.raise_for_status() + if len(r.content) < 20: + raise ValueError(f"Odpověď příliš krátká ({len(r.content)} B)") + return r.content + except Exception as e: + if attempt < retries: + print(f" ⚠️ Pokus {attempt}/{retries} selhal: {e} — čekám {retry_delay}s") + time.sleep(retry_delay) + else: + print(f" ✖ Všechny pokusy ({retries}) selhaly: {e}") + return None # ============================================================ diff --git a/Seedbox/96 RetryFailedDownloads.py b/Seedbox/96 RetryFailedDownloads.py new file mode 100644 index 0000000..e6df2d8 --- /dev/null +++ b/Seedbox/96 RetryFailedDownloads.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +96 RetryFailedDownloads — sktorrent.eu +- Najde torrenty v DB, kde torrent_content IS NULL (stažení selhalo) +- Pokusí se je znovu stáhnout z download_url +- Nevyžaduje Selenium — stačí requests + cookies +""" + +import pymysql +import requests +import json +import time +import sys +from pathlib import Path +from datetime import datetime + +# ============================================================ +# CONFIG +# ============================================================ + +COOKIE_FILE = Path(__file__).parent.parent / "sktorrent_cookies.json" +BACKUP_DIR = Path(__file__).parent.parent / "saved_torrents" + +SLEEP_BETWEEN = 2.0 # pauza mezi stáženími + +DB_CONFIG = { + "host": "192.168.1.76", + "port": 3306, + "user": "root", + "password": "Vlado9674+", + "database": "torrents", + "charset": "utf8mb4", + "autocommit": True, +} + +# ============================================================ +# HELPERS +# ============================================================ + +def build_session(): + if not COOKIE_FILE.exists(): + raise FileNotFoundError(f"Cookie soubor nenalezen: {COOKIE_FILE}") + with open(COOKIE_FILE, "r", encoding="utf-8") as f: + cookies = json.load(f) + session = requests.Session() + session.headers["User-Agent"] = ( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" + ) + for c in cookies: + session.cookies.set(c["name"], c["value"], domain=c.get("domain", "")) + return session + + +def sanitize_filename(name: str) -> str: + import re + clean = re.sub(r'[<>:"/\\|?*]', '', name) + return clean.strip()[:100] + + +# ============================================================ +# MAIN +# ============================================================ + +def main(): + sys.stdout.reconfigure(encoding="utf-8") + + print("=" * 60) + print("RETRY FAILED DOWNLOADS — sktorrent.eu") + print(f"Spuštěno: {datetime.now():%Y-%m-%d %H:%M:%S}") + print("=" * 60) + + BACKUP_DIR.mkdir(exist_ok=True) + + db = pymysql.connect(**DB_CONFIG) + cursor = db.cursor() + + cursor.execute( + "SELECT torrent_hash, title_visible, download_url " + "FROM torrents " + "WHERE torrent_content IS NULL AND download_url IS NOT NULL " + "ORDER BY added_datetime DESC" + ) + rows = cursor.fetchall() + + if not rows: + print("Žádné chybějící .torrent soubory — vše je staženo.") + db.close() + return + + print(f"Nalezeno {len(rows)} torrentů bez obsahu:\n") + for i, (t_hash, title, url) in enumerate(rows, 1): + print(f" {i}. {title}") + print() + + session = build_session() + + success = 0 + failed = 0 + + for i, (t_hash, title, url) in enumerate(rows, 1): + print(f"[{i}/{len(rows)}] {title}") + print(f" URL: {url}") + + try: + r = session.get(url, timeout=20) + + if r.status_code == 404: + print(" ✖ 404 — soubor na serveru neexistuje (přeskakuji)") + failed += 1 + continue + + if r.status_code == 403: + print(" ✖ 403 — cookie pravděpodobně expiraly, zastav a obnov přihlášení") + failed += 1 + break + + r.raise_for_status() + content = r.content + + if len(content) < 20: + print(f" ✖ Odpověď příliš krátká ({len(content)} B) — přeskakuji") + failed += 1 + continue + + # Ulož do DB + cursor.execute( + "UPDATE torrents SET torrent_content = %s WHERE torrent_hash = %s", + (content, t_hash) + ) + + # Ulož na disk + fname = f"{sanitize_filename(title)}_{t_hash[:6]}.torrent" + fpath = BACKUP_DIR / fname + fpath.write_bytes(content) + + print(f" ✔ Staženo ({len(content):,} B) → {fname}") + success += 1 + + except Exception as e: + print(f" ✖ Chyba: {e}") + failed += 1 + + if i < len(rows): + time.sleep(SLEEP_BETWEEN) + + db.close() + + print() + print("=" * 60) + print(f"Hotovo: {datetime.now():%Y-%m-%d %H:%M:%S}") + print(f"Úspěšně staženo : {success}") + print(f"Selhalo / 404 : {failed}") + print("=" * 60) + + +if __name__ == "__main__": + main() diff --git a/saved_torrents/Harry Potter and the Goblet of Fire - UK Dolby Atmos Mix - J K Rowling_7cbe2f.torrent b/saved_torrents/Harry Potter and the Goblet of Fire - UK Dolby Atmos Mix - J K Rowling_7cbe2f.torrent new file mode 100644 index 0000000..48323c0 Binary files /dev/null and b/saved_torrents/Harry Potter and the Goblet of Fire - UK Dolby Atmos Mix - J K Rowling_7cbe2f.torrent differ diff --git a/saved_torrents/Jeffrey Archer - A jak to bylo dál... (2022)_9719d0.torrent b/saved_torrents/Jeffrey Archer - A jak to bylo dál... (2022)_9719d0.torrent new file mode 100644 index 0000000..59f049d Binary files /dev/null and b/saved_torrents/Jeffrey Archer - A jak to bylo dál... (2022)_9719d0.torrent differ diff --git a/saved_torrents/Jeffrey Archer - Věc cti (2022)_6e6607.torrent b/saved_torrents/Jeffrey Archer - Věc cti (2022)_6e6607.torrent new file mode 100644 index 0000000..d0f5347 Binary files /dev/null and b/saved_torrents/Jeffrey Archer - Věc cti (2022)_6e6607.torrent differ