z230
This commit is contained in:
182
Seedbox/81 DeleteWhatWeHaveUltraCC1.py
Normal file
182
Seedbox/81 DeleteWhatWeHaveUltraCC1.py
Normal file
@@ -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()
|
||||
Reference in New Issue
Block a user