z230
This commit is contained in:
150
Syncthing/03 Terminator.py
Normal file
150
Syncthing/03 Terminator.py
Normal file
@@ -0,0 +1,150 @@
|
||||
import os
|
||||
import pymysql
|
||||
import sys
|
||||
import json
|
||||
from tqdm import tqdm
|
||||
|
||||
# ==============================
|
||||
# ⚙️ NASTAVENÍ
|
||||
# ==============================
|
||||
CACHE_FILE = "local_hashes.jsonl"
|
||||
|
||||
# !!! ZMĚŇ NA True PRO SKUTEČNÉ MAZÁNÍ !!!
|
||||
DELETE_MODE = True
|
||||
|
||||
# Filtr DB (Hledáme shodu jen v této složce na serveru)
|
||||
REMOTE_FOLDER_FILTER = "/#ColdData/Porno/"
|
||||
|
||||
DB_CONFIG = {
|
||||
"host": "192.168.1.76",
|
||||
"port": 3307,
|
||||
"user": "root",
|
||||
"password": "Vlado9674+",
|
||||
"database": "torrents",
|
||||
}
|
||||
|
||||
|
||||
# ==============================
|
||||
|
||||
def get_remote_hashes():
|
||||
print("📡 Stahuji hashe z DB (filtr: " + REMOTE_FOLDER_FILTER + ")...")
|
||||
hashes = set()
|
||||
try:
|
||||
conn = pymysql.connect(**DB_CONFIG, cursorclass=pymysql.cursors.DictCursor)
|
||||
with conn.cursor() as cursor:
|
||||
# Stáhneme hashe souborů, které jsou v cílové složce
|
||||
sql = f"SELECT blake3 FROM file_md5_index WHERE full_path LIKE %s"
|
||||
cursor.execute(sql, (f"%{REMOTE_FOLDER_FILTER}%",))
|
||||
|
||||
for row in cursor.fetchall():
|
||||
# DB vrací bytes, my potřebujeme HEX string (stejný jako v JSONL)
|
||||
hashes.add(row['blake3'].hex())
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
sys.exit(f"❌ Chyba DB: {e}")
|
||||
return hashes
|
||||
|
||||
|
||||
def count_lines(filename):
|
||||
"""Spočítá řádky pro progress bar"""
|
||||
print("⏳ Sčítám záznamy v cache...", end="\r")
|
||||
with open(filename, "r", encoding="utf-8") as f:
|
||||
return sum(1 for _ in f)
|
||||
|
||||
|
||||
def main():
|
||||
print("🚀 KROK 2: Terminátor (Mazání podle cache)")
|
||||
print(f"📂 Cache soubor: {CACHE_FILE}")
|
||||
print(f"🛠 Mód: {'🔴 OSTRÝ (MAZÁNÍ)' if DELETE_MODE else '🟢 SIMULACE (JEN VÝPIS)'}")
|
||||
print("===================================")
|
||||
|
||||
if not os.path.exists(CACHE_FILE):
|
||||
sys.exit("❌ Cache soubor neexistuje! Spusť nejdřív KROK 1.")
|
||||
|
||||
# 1. Stáhnout DB
|
||||
remote_hashes = get_remote_hashes()
|
||||
print(f"✅ DB načtena: {len(remote_hashes):,} unikátních hashů ze serveru.")
|
||||
|
||||
# 2. Spočítat řádky pro progress bar
|
||||
total_lines = count_lines(CACHE_FILE)
|
||||
print(f"✅ Cache obsahuje: {total_lines:,} lokálních souborů ke kontrole.")
|
||||
|
||||
print("🔍 Jdu porovnávat...")
|
||||
|
||||
count_deleted = 0
|
||||
freed_space = 0
|
||||
errors = 0
|
||||
|
||||
# Otevření souboru pro logování smazaných (volitelné)
|
||||
log_name = "deleted_files.log" if DELETE_MODE else "would_delete.log"
|
||||
|
||||
with open(CACHE_FILE, "r", encoding="utf-8") as f_in, \
|
||||
open(log_name, "w", encoding="utf-8") as f_log:
|
||||
|
||||
# Progress bar
|
||||
with tqdm(total=total_lines, unit="file", dynamic_ncols=True) as pbar:
|
||||
|
||||
for line in f_in:
|
||||
pbar.update(1)
|
||||
line = line.strip()
|
||||
if not line: continue
|
||||
|
||||
try:
|
||||
data = json.loads(line)
|
||||
local_hash = data["h"]
|
||||
file_path = data["p"]
|
||||
except:
|
||||
continue # Vadný řádek
|
||||
|
||||
# Kontrola existence souboru (mohli jsme ho už smazat ručně)
|
||||
if not os.path.exists(file_path):
|
||||
continue
|
||||
|
||||
# --- HLAVNÍ LOGIKA ---
|
||||
if local_hash in remote_hashes:
|
||||
# SHODA! Soubor je na serveru -> SMAZAT lokálně
|
||||
|
||||
try:
|
||||
size = os.path.getsize(file_path)
|
||||
|
||||
if DELETE_MODE:
|
||||
os.remove(file_path)
|
||||
status = "SMAZÁNO"
|
||||
# Pokus o smazání prázdné složky
|
||||
try:
|
||||
os.rmdir(os.path.dirname(file_path))
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
status = "NAŠEL BYCH"
|
||||
|
||||
count_deleted += 1
|
||||
freed_space += size
|
||||
|
||||
# Zápis do logu
|
||||
f_log.write(f"{file_path}\n")
|
||||
|
||||
# Aktualizace popisku (jen občas, aby to neblikalo moc rychle)
|
||||
if count_deleted % 10 == 0:
|
||||
pbar.set_description(f"Mazání: {count_deleted} files")
|
||||
|
||||
except OSError as e:
|
||||
errors += 1
|
||||
# print(f"❌ Chyba u {file_path}: {e}")
|
||||
|
||||
print("\n\n📊 VÝSLEDEK")
|
||||
print("===================================")
|
||||
print(f"🔎 Zkontrolováno: {total_lines:,}")
|
||||
print(f"🗑️ {'Smazáno' if DELETE_MODE else 'K smazání'}: {count_deleted:,}")
|
||||
print(f"💾 Ušetřeno místo: {freed_space / (1024 * 1024 * 1024):.2f} GB")
|
||||
print(f"📝 Seznam souborů: '{log_name}'")
|
||||
|
||||
if errors > 0:
|
||||
print(f"⚠️ Chyb při mazání: {errors}")
|
||||
|
||||
if not DELETE_MODE and count_deleted > 0:
|
||||
print("\n💡 LÍBÍ SE TI VÝSLEDEK? Změň nahoře: DELETE_MODE = True")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user