diff --git a/Seedbox/50 MrtveTorrenty.py b/Seedbox/50 MrtveTorrenty.py new file mode 100644 index 0000000..430bc43 --- /dev/null +++ b/Seedbox/50 MrtveTorrenty.py @@ -0,0 +1,152 @@ +import pymysql +import qbittorrentapi +from datetime import datetime, timedelta + +# ============================================================ +# CONFIG +# ============================================================ + +DRY_RUN = True # ← změň na False až si ověříš výstup + +DEAD_AFTER_HOURS = 72 # torrent musí být v qB alespoň tolik hodin +DEAD_PROGRESS_THRESHOLD = 95.0 # pokud je progress < tato % po uplynutí doby → dead + +QBT_URL = "https://vladob.zen.usbx.me/qbittorrent" +QBT_USER = "vladob" +QBT_PASS = "jCni3U6d#y4bfcm" + +DB_CONFIG = { + "host": "192.168.1.50", + "port": 3306, + "user": "root", + "password": "Vlado9674+", + "database": "torrents", + "charset": "utf8mb4", + "autocommit": True, +} + +# ============================================================ +# CONNECT +# ============================================================ + +def connect_qbt(): + qbt = qbittorrentapi.Client( + host=QBT_URL, + username=QBT_USER, + password=QBT_PASS, + VERIFY_WEBUI_CERTIFICATE=False + ) + qbt.auth_log_in() + return qbt + + +def connect_db(): + return pymysql.connect(**DB_CONFIG) + + +# ============================================================ +# MAIN +# ============================================================ + +def main(): + + print("=" * 60) + print("MRTVÉ TORRENTY — UltraCC Seedbox cleanup") + print(f"DRY_RUN = {DRY_RUN}") + print(f"Kritéria : v qB déle než {DEAD_AFTER_HOURS}h A progress < {DEAD_PROGRESS_THRESHOLD}%") + print("=" * 60) + + qbt = connect_qbt() + db = connect_db() + cursor = db.cursor() + + torrents = qbt.torrents_info() + + now = datetime.now() + deadline = now - timedelta(hours=DEAD_AFTER_HOURS) + + dead_count = 0 + skip_count = 0 + error_count = 0 + + for t in torrents: + + # Přeskočit dokončené (ty řeší skript 40) + if t.completion_on: + skip_count += 1 + continue + + added_on = t.added_on # unix timestamp + if not added_on: + skip_count += 1 + continue + + added_dt = datetime.fromtimestamp(added_on) + progress_pct = float(t.progress) * 100.0 + + # Torrent ještě není dost starý + if added_dt > deadline: + skip_count += 1 + continue + + # Progress je OK (téměř hotov) → přeskočit + if progress_pct >= DEAD_PROGRESS_THRESHOLD: + skip_count += 1 + continue + + # ── Torrent splňuje kritéria "mrtvý" ────────────────── + thash = t.hash.lower() + age_hours = (now - added_dt).total_seconds() / 3600 + + print(f"\n💀 MRTVÝ: {t.name}") + print(f" Přidán : {added_dt} ({age_hours:.1f}h zpět)") + print(f" Progress : {progress_pct:.1f}%") + print(f" Stav : {t.state}") + print(f" Seeds : {t.num_seeds} Peers: {t.num_leechs}") + + if DRY_RUN: + print(f" [DRY] Smazal bych z qBittorrentu a označil v DB jako incomplete") + dead_count += 1 + continue + + # Smazat z qBittorrentu (i soubory — nekompletní data jsou k ničemu) + try: + qbt.torrents_delete(torrent_hashes=thash, delete_files=True) + print(f" ✔ Smazán z qBittorrentu") + except Exception as e: + print(f" ❌ Smazání selhalo: {e}") + error_count += 1 + continue + + # Označit v DB jako incomplete + cursor.execute(""" + UPDATE torrents + SET + qb_state = 'incomplete', + qb_progress = %s, + qb_last_update = NOW() + WHERE torrent_hash = %s + """, (progress_pct, thash)) + + if cursor.rowcount > 0: + print(f" ✔ DB → incomplete (progress={progress_pct:.1f}%)") + else: + print(f" ⚠ DB: žádný řádek pro hash {thash}") + + dead_count += 1 + + # ============================================================ + # SUMMARY + # ============================================================ + print("\n" + "=" * 60) + print(f"Mrtvé torrenty zpracováno : {dead_count}") + print(f"Přeskočeno : {skip_count}") + print(f"Chyby : {error_count}") + print(f"DRY_RUN : {DRY_RUN}") + print("=" * 60) + + db.close() + + +if __name__ == "__main__": + main()