z230
This commit is contained in:
136
Syncthing/01 LocalCleanerBasedOnRemoteHash.py
Normal file
136
Syncthing/01 LocalCleanerBasedOnRemoteHash.py
Normal file
@@ -0,0 +1,136 @@
|
||||
import os
|
||||
import pymysql
|
||||
import sys
|
||||
import blake3 # Nutné: pip install blake3
|
||||
|
||||
# ==============================
|
||||
# ⚙️ NASTAVENÍ
|
||||
# ==============================
|
||||
LOCAL_ROOT = r"U:\#Syncthing"
|
||||
|
||||
# !!! AŽ SI BUDEŠ JISTÝ, ZMĚŇ NA True !!!
|
||||
DELETE_MODE = False
|
||||
|
||||
# Hledáme shodu pouze v souborech, které jsou na serveru v této cestě:
|
||||
REMOTE_FOLDER_FILTER = "/#ColdData/Porno/"
|
||||
|
||||
# DB Nastavení
|
||||
DB_HOST = "192.168.1.76"
|
||||
DB_PORT = 3307
|
||||
DB_USER = "root"
|
||||
DB_PASS = "Vlado9674+"
|
||||
DB_NAME = "torrents"
|
||||
DB_TABLE = "file_md5_index"
|
||||
|
||||
|
||||
# ==============================
|
||||
|
||||
def get_db_connection():
|
||||
try:
|
||||
return pymysql.connect(
|
||||
host=DB_HOST, port=DB_PORT, user=DB_USER, password=DB_PASS,
|
||||
database=DB_NAME, cursorclass=pymysql.cursors.DictCursor
|
||||
)
|
||||
except Exception as e:
|
||||
sys.exit(f"❌ Chyba DB: {e}")
|
||||
|
||||
|
||||
def calculate_blake3(file_path):
|
||||
"""Spočítá BLAKE3 hash souboru"""
|
||||
h = blake3.blake3()
|
||||
try:
|
||||
with open(file_path, "rb") as f:
|
||||
while True:
|
||||
chunk = f.read(4 * 1024 * 1024) # 4MB chunks
|
||||
if not chunk:
|
||||
break
|
||||
h.update(chunk)
|
||||
return h.digest()
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
print(f"🚀 TERMINÁTOR: Mazání podle obsahu (BLAKE3)")
|
||||
print(f" 📂 Zdroj: {LOCAL_ROOT}")
|
||||
print(f" 🎯 DB filtr: {REMOTE_FOLDER_FILTER}")
|
||||
print(f" 🛠 Mód: {'🔴 OSTRÝ (MAZÁNÍ)' if DELETE_MODE else '🟢 SIMULACE (BEZPEČNÝ)'}")
|
||||
print("=====================================================")
|
||||
|
||||
# 1. NAČTENÍ HASHŮ Z DB
|
||||
print("📡 Stahuji hashe ze serveru...")
|
||||
remote_hashes = set()
|
||||
|
||||
conn = get_db_connection()
|
||||
with conn.cursor() as cursor:
|
||||
sql = f"SELECT blake3 FROM {DB_TABLE} WHERE full_path LIKE %s"
|
||||
cursor.execute(sql, (f"%{REMOTE_FOLDER_FILTER}%",))
|
||||
rows = cursor.fetchall()
|
||||
|
||||
for row in rows:
|
||||
remote_hashes.add(row['blake3'])
|
||||
|
||||
print(f"✅ V paměti mám {len(remote_hashes):,} unikátních hashů ze serveru.")
|
||||
print("=====================================================")
|
||||
|
||||
# 2. SKENOVÁNÍ A MAZÁNÍ
|
||||
count_scanned = 0
|
||||
count_match = 0
|
||||
size_freed = 0
|
||||
|
||||
for root, dirs, files in os.walk(LOCAL_ROOT):
|
||||
# Přeskočit syncthing složky
|
||||
if ".stfolder" in dirs: dirs.remove(".stfolder")
|
||||
if ".stversions" in dirs: dirs.remove(".stversions")
|
||||
|
||||
for filename in files:
|
||||
file_path = os.path.join(root, filename)
|
||||
count_scanned += 1
|
||||
|
||||
# Výpis práce
|
||||
print(f"⏳ [{count_scanned}] Zpracovávám: {filename}")
|
||||
|
||||
# Spočítat lokální hash
|
||||
local_hash = calculate_blake3(file_path)
|
||||
|
||||
if local_hash is None:
|
||||
print(f" ⚠️ Chyba čtení souboru!")
|
||||
continue
|
||||
|
||||
# Zobrazíme kousek hashe pro kontrolu (převedeme na hex text)
|
||||
hash_preview = local_hash.hex()[:8]
|
||||
|
||||
# JE TEN HASH V DATABÁZI?
|
||||
if local_hash in remote_hashes:
|
||||
count_match += 1
|
||||
file_size = os.path.getsize(file_path)
|
||||
size_freed += file_size
|
||||
|
||||
print(f" ✅ SHODA (Hash: {hash_preview}...) -> {'🗑️ MAŽU' if DELETE_MODE else '📦 NAŠEL BYCH'}")
|
||||
|
||||
if DELETE_MODE:
|
||||
try:
|
||||
os.remove(file_path)
|
||||
# Pokus o smazání prázdné složky
|
||||
try:
|
||||
os.rmdir(root)
|
||||
except:
|
||||
pass
|
||||
except OSError as e:
|
||||
print(f" ❌ Chyba mazání: {e}")
|
||||
else:
|
||||
print(f" ❌ Žádná shoda (Hash: {hash_preview}...) -> Nechávám být")
|
||||
|
||||
print("\n\n📊 VÝSLEDEK")
|
||||
print("=====================================================")
|
||||
print(f"🔎 Prošlo rukama: {count_scanned:,} souborů")
|
||||
print(f"🗑️ Smazáno/Shoda: {count_match:,} souborů")
|
||||
print(f"💾 Ušetřené místo: {size_freed / (1024 * 1024):.2f} MB")
|
||||
print("=====================================================")
|
||||
|
||||
if not DELETE_MODE and count_match > 0:
|
||||
print("💡 TIP: Až budeš připraven, změň v kódu: DELETE_MODE = True")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user