diff --git a/Seedbox/80 DeleteWhatWeHaveUltraCC2.py b/Seedbox/80 DeleteWhatWeHaveUltraCC2.py new file mode 100644 index 0000000..87f1a97 --- /dev/null +++ b/Seedbox/80 DeleteWhatWeHaveUltraCC2.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Projde /mnt/user/torrents/ultracc, pro každý soubor spočítá blake3 +a porovná s tabulkou file_md5_index. Pokud je hash nalezen → soubor smaže. +Po smazání souborů odstraní prázdné adresáře. +""" + +import os +import sys +import blake3 +import pymysql +import paramiko +from pathlib import Path + +# ============================================================ +# CONFIG +# ============================================================ + +SCAN_DIR = "//tower/torrents/ultracc2" + +SSH_CONFIG = { + "hostname": "192.168.1.76", + "port": 22, + "username": "root", + "password": "7309208104", +} + +ULTRACC_DIRS = [ + "/mnt/user/Torrents/UltraCC", + "/mnt/user/Torrents/UltraCC1", + "/mnt/user/Torrents/UltraCC2", +] + +DB_CONFIG = { + "host": "192.168.1.76", + "port": 3306, + "user": "root", + "password": "Vlado9674+", + "database": "torrents", + "charset": "utf8mb4", +} + +CHUNK_SIZE = 8 * 1024 * 1024 # 8 MB +DRY_RUN = False # True = pouze vypíše, nesmaže + +# ============================================================ +# HELPERS +# ============================================================ + +def compute_blake3(path: Path) -> bytes: + """Vrátí blake3 digest jako 32 raw bytes.""" + h = blake3.blake3() + with open(path, "rb") as f: + while True: + chunk = f.read(CHUNK_SIZE) + if not chunk: + break + h.update(chunk) + return h.digest() + + +def hash_in_db(cursor, digest: bytes): + """Vrátí (host_name, full_path) prvního záznamu s daným hashem, nebo None.""" + cursor.execute( + "SELECT host_name, full_path FROM file_md5_index WHERE blake3 = %s LIMIT 1", + (digest,) + ) + return cursor.fetchone() # None nebo (host_name, full_path) + + +def remove_empty_dirs(root: str) -> int: + """Rekurzivně smaže prázdné adresáře pod root. Vrátí počet smazaných.""" + removed = 0 + for dirpath, dirnames, filenames in os.walk(root, topdown=False): + if dirpath == root: + continue + try: + os.rmdir(dirpath) + print(f" [rmdir] {dirpath}") + removed += 1 + except OSError: + pass + return removed + + +# ============================================================ +# MAIN +# ============================================================ + +def set_ultracc_permissions(): + """Přes SSH nastaví na Tower chown nobody:users + chmod 777 pro všechny UltraCC adresáře.""" + print("Nastavuji práva na Tower (UltraCC*)...") + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(**SSH_CONFIG) + for d in ULTRACC_DIRS: + _, out, err = ssh.exec_command( + 'chown -R nobody:users "%s" && chmod -R 777 "%s" && echo OK' % (d, d) + ) + result = out.read().decode().strip() + error = err.read().decode().strip() + if result == "OK": + print(f" [OK] {d}") + else: + print(f" [CHYBA] {d}: {error}") + ssh.close() + print() + + +def main(): + dry_run = DRY_RUN + + set_ultracc_permissions() + + if dry_run: + print("=== DRY RUN — nic se nesmaže ===\n") + + conn = pymysql.connect(**DB_CONFIG) + cursor = conn.cursor() + + scan_root = Path(SCAN_DIR) + if not scan_root.exists(): + print(f"CHYBA: Adresář neexistuje: {SCAN_DIR}") + sys.exit(1) + + files_checked = 0 + files_deleted = 0 + files_kept = 0 + bytes_deleted = 0 + + for file_path in scan_root.rglob("*"): + if not file_path.is_file(): + continue + + files_checked += 1 + size = file_path.stat().st_size + + try: + digest = compute_blake3(file_path) + except OSError as e: + print(f" [CHYBA čtení] {file_path}: {e}") + continue + + db_match = hash_in_db(cursor, digest) + if db_match: + db_host, db_path = db_match + print(f" [SMAZAT] {file_path} ({size:,} B)") + print(f" ↳ originál v DB: [{db_host}] {db_path}") + if not dry_run: + try: + file_path.unlink() + files_deleted += 1 + bytes_deleted += size + except OSError as e: + print(f" [CHYBA smazání] {file_path}: {e}") + else: + files_deleted += 1 + bytes_deleted += size + else: + print(f" [zachovat] {file_path} ({size:,} B)") + files_kept += 1 + + cursor.close() + conn.close() + + print() + print(f"Zkontrolováno: {files_checked} souborů") + print(f"Ke smazání: {files_deleted} souborů ({bytes_deleted / 1024**3:.2f} GB)") + print(f"Zachováno: {files_kept} souborů") + + if not dry_run and files_deleted > 0: + print("\nOdstraňuji prázdné adresáře...") + removed = remove_empty_dirs(SCAN_DIR) + print(f"Odstraněno prázdných adresářů: {removed}") + + if dry_run: + print("\n(Dry run — žádné změny nebyly provedeny)") + + +if __name__ == "__main__": + main() diff --git a/Seedbox/80 DeleteWhatWeHave.py b/Seedbox/81 DeleteWhatWeHaveUltraCC.py similarity index 70% rename from Seedbox/80 DeleteWhatWeHave.py rename to Seedbox/81 DeleteWhatWeHaveUltraCC.py index cea7359..a6c3e16 100644 --- a/Seedbox/80 DeleteWhatWeHave.py +++ b/Seedbox/81 DeleteWhatWeHaveUltraCC.py @@ -10,6 +10,7 @@ import os import sys import blake3 import pymysql +import paramiko from pathlib import Path # ============================================================ @@ -18,6 +19,19 @@ from pathlib import Path SCAN_DIR = "//tower/torrents/ultracc" +SSH_CONFIG = { + "hostname": "192.168.1.76", + "port": 22, + "username": "root", + "password": "7309208104", +} + +ULTRACC_DIRS = [ + "/mnt/user/Torrents/UltraCC", + "/mnt/user/Torrents/UltraCC1", + "/mnt/user/Torrents/UltraCC2", +] + DB_CONFIG = { "host": "192.168.1.76", "port": 3306, @@ -28,7 +42,7 @@ DB_CONFIG = { } CHUNK_SIZE = 8 * 1024 * 1024 # 8 MB -DRY_RUN = True # True = pouze vypíše, nesmaže +DRY_RUN = False # True = pouze vypíše, nesmaže # ============================================================ # HELPERS @@ -46,12 +60,13 @@ def compute_blake3(path: Path) -> bytes: return h.digest() -def hash_in_db(cursor, digest: bytes) -> bool: +def hash_in_db(cursor, digest: bytes): + """Vrátí (host_name, full_path) prvního záznamu s daným hashem, nebo None.""" cursor.execute( - "SELECT 1 FROM file_md5_index WHERE blake3 = %s LIMIT 1", + "SELECT host_name, full_path FROM file_md5_index WHERE blake3 = %s LIMIT 1", (digest,) ) - return cursor.fetchone() is not None + return cursor.fetchone() # None nebo (host_name, full_path) def remove_empty_dirs(root: str) -> int: @@ -73,9 +88,31 @@ def remove_empty_dirs(root: str) -> int: # MAIN # ============================================================ +def set_ultracc_permissions(): + """Přes SSH nastaví na Tower chown nobody:users + chmod 777 pro všechny UltraCC adresáře.""" + print("Nastavuji práva na Tower (UltraCC*)...") + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(**SSH_CONFIG) + for d in ULTRACC_DIRS: + _, out, err = ssh.exec_command( + 'chown -R nobody:users "%s" && chmod -R 777 "%s" && echo OK' % (d, d) + ) + result = out.read().decode().strip() + error = err.read().decode().strip() + if result == "OK": + print(f" [OK] {d}") + else: + print(f" [CHYBA] {d}: {error}") + ssh.close() + print() + + def main(): dry_run = DRY_RUN + set_ultracc_permissions() + if dry_run: print("=== DRY RUN — nic se nesmaže ===\n") @@ -105,8 +142,11 @@ def main(): print(f" [CHYBA čtení] {file_path}: {e}") continue - if hash_in_db(cursor, digest): + db_match = hash_in_db(cursor, digest) + if db_match: + db_host, db_path = db_match print(f" [SMAZAT] {file_path} ({size:,} B)") + print(f" ↳ originál v DB: [{db_host}] {db_path}") if not dry_run: try: file_path.unlink() diff --git a/Seedbox/81 DeleteWhatWeHaveUltraCC1.py b/Seedbox/81 DeleteWhatWeHaveUltraCC1.py new file mode 100644 index 0000000..5b8304c --- /dev/null +++ b/Seedbox/81 DeleteWhatWeHaveUltraCC1.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Projde /mnt/user/torrents/ultracc, pro každý soubor spočítá blake3 +a porovná s tabulkou file_md5_index. Pokud je hash nalezen → soubor smaže. +Po smazání souborů odstraní prázdné adresáře. +""" + +import os +import sys +import blake3 +import pymysql +import paramiko +from pathlib import Path + +# ============================================================ +# CONFIG +# ============================================================ + +SCAN_DIR = "//tower/torrents/ultracc1" + +SSH_CONFIG = { + "hostname": "192.168.1.76", + "port": 22, + "username": "root", + "password": "7309208104", +} + +ULTRACC_DIRS = [ + "/mnt/user/Torrents/UltraCC", + "/mnt/user/Torrents/UltraCC1", + "/mnt/user/Torrents/UltraCC2", +] + +DB_CONFIG = { + "host": "192.168.1.76", + "port": 3306, + "user": "root", + "password": "Vlado9674+", + "database": "torrents", + "charset": "utf8mb4", +} + +CHUNK_SIZE = 8 * 1024 * 1024 # 8 MB +DRY_RUN = False # True = pouze vypíše, nesmaže + +# ============================================================ +# HELPERS +# ============================================================ + +def compute_blake3(path: Path) -> bytes: + """Vrátí blake3 digest jako 32 raw bytes.""" + h = blake3.blake3() + with open(path, "rb") as f: + while True: + chunk = f.read(CHUNK_SIZE) + if not chunk: + break + h.update(chunk) + return h.digest() + + +def hash_in_db(cursor, digest: bytes): + """Vrátí (host_name, full_path) prvního záznamu s daným hashem, nebo None.""" + cursor.execute( + "SELECT host_name, full_path FROM file_md5_index WHERE blake3 = %s LIMIT 1", + (digest,) + ) + return cursor.fetchone() # None nebo (host_name, full_path) + + +def remove_empty_dirs(root: str) -> int: + """Rekurzivně smaže prázdné adresáře pod root. Vrátí počet smazaných.""" + removed = 0 + for dirpath, dirnames, filenames in os.walk(root, topdown=False): + if dirpath == root: + continue + try: + os.rmdir(dirpath) + print(f" [rmdir] {dirpath}") + removed += 1 + except OSError: + pass + return removed + + +# ============================================================ +# MAIN +# ============================================================ + +def set_ultracc_permissions(): + """Přes SSH nastaví na Tower chown nobody:users + chmod 777 pro všechny UltraCC adresáře.""" + print("Nastavuji práva na Tower (UltraCC*)...") + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(**SSH_CONFIG) + for d in ULTRACC_DIRS: + _, out, err = ssh.exec_command( + 'chown -R nobody:users "%s" && chmod -R 777 "%s" && echo OK' % (d, d) + ) + result = out.read().decode().strip() + error = err.read().decode().strip() + if result == "OK": + print(f" [OK] {d}") + else: + print(f" [CHYBA] {d}: {error}") + ssh.close() + print() + + +def main(): + dry_run = DRY_RUN + + set_ultracc_permissions() + + if dry_run: + print("=== DRY RUN — nic se nesmaže ===\n") + + conn = pymysql.connect(**DB_CONFIG) + cursor = conn.cursor() + + scan_root = Path(SCAN_DIR) + if not scan_root.exists(): + print(f"CHYBA: Adresář neexistuje: {SCAN_DIR}") + sys.exit(1) + + files_checked = 0 + files_deleted = 0 + files_kept = 0 + bytes_deleted = 0 + + for file_path in scan_root.rglob("*"): + if not file_path.is_file(): + continue + + files_checked += 1 + size = file_path.stat().st_size + + try: + digest = compute_blake3(file_path) + except OSError as e: + print(f" [CHYBA čtení] {file_path}: {e}") + continue + + db_match = hash_in_db(cursor, digest) + if db_match: + db_host, db_path = db_match + print(f" [SMAZAT] {file_path} ({size:,} B)") + print(f" ↳ originál v DB: [{db_host}] {db_path}") + if not dry_run: + try: + file_path.unlink() + files_deleted += 1 + bytes_deleted += size + except OSError as e: + print(f" [CHYBA smazání] {file_path}: {e}") + else: + files_deleted += 1 + bytes_deleted += size + else: + print(f" [zachovat] {file_path} ({size:,} B)") + files_kept += 1 + + cursor.close() + conn.close() + + print() + print(f"Zkontrolováno: {files_checked} souborů") + print(f"Ke smazání: {files_deleted} souborů ({bytes_deleted / 1024**3:.2f} GB)") + print(f"Zachováno: {files_kept} souborů") + + if not dry_run and files_deleted > 0: + print("\nOdstraňuji prázdné adresáře...") + removed = remove_empty_dirs(SCAN_DIR) + print(f"Odstraněno prázdných adresářů: {removed}") + + if dry_run: + print("\n(Dry run — žádné změny nebyly provedeny)") + + +if __name__ == "__main__": + main()