z230
This commit is contained in:
+10
-10
@@ -35,16 +35,6 @@ STUCK_AFTER_HOURS = 168 # progress >= 95% ale < 100% po 7 dnech → dea
|
|||||||
# },
|
# },
|
||||||
|
|
||||||
CLIENTS = [
|
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",
|
"name": "Local qBittorrent",
|
||||||
"max_concurrent": 30,
|
"max_concurrent": 30,
|
||||||
@@ -55,6 +45,16 @@ CLIENTS = [
|
|||||||
"password": "adminadmin",
|
"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 = {
|
DB_CONFIG = {
|
||||||
|
|||||||
@@ -160,16 +160,21 @@ def parse_page(html):
|
|||||||
# DOWNLOAD .TORRENT FILE
|
# DOWNLOAD .TORRENT FILE
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def download_torrent(session, url):
|
def download_torrent(session, url, retries=10, retry_delay=10):
|
||||||
try:
|
for attempt in range(1, retries + 1):
|
||||||
r = session.get(url, timeout=15)
|
try:
|
||||||
r.raise_for_status()
|
r = session.get(url, timeout=15)
|
||||||
if len(r.content) < 20:
|
r.raise_for_status()
|
||||||
return None
|
if len(r.content) < 20:
|
||||||
return r.content
|
raise ValueError(f"Odpověď příliš krátká ({len(r.content)} B)")
|
||||||
except Exception as e:
|
return r.content
|
||||||
print(f" ⚠️ Stažení selhalo: {e}")
|
except Exception as e:
|
||||||
return None
|
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
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|||||||
@@ -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()
|
||||||
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user