Files
comic-manager/processors/cleaner.py
T

140 lines
3.7 KiB
Python

# processors/cleaner.py
import os
import zipfile
import rarfile
import tempfile
import shutil
from core.constants import TRASH_FILES
from processors.validator import try_open_rar, try_open_zip
class CleanResult:
def __init__(self, original_path):
self.original_path = original_path
self.cleaned_path = None
self.removed_files = []
self.repacked = False
self.converted_to_cbz = False
def pretty_removed_files(self):
if not self.removed_files:
return " No se eliminaron archivos\n"
msg = f" Archivos eliminados ({len(self.removed_files)}):\n"
for f in self.removed_files:
msg += f" - {f}\n"
return msg
def __str__(self):
msg = f"Limpieza de: {self.original_path}\n"
msg += self.pretty_removed_files()
if self.repacked:
msg += " Archivo reconstruido\n"
if self.converted_to_cbz:
msg += " Convertido a CBZ\n"
msg += f" Resultado final: {self.cleaned_path}"
return msg
# ------------------------------------------------------------
# 1) Limpieza de una carpeta ya extraída
# ------------------------------------------------------------
def clean_folder(folder_path):
"""
Elimina archivos basura dentro de una carpeta ya extraída.
Devuelve una lista con las rutas relativas de los archivos eliminados.
"""
removed = []
for root, _, files in os.walk(folder_path):
for f in files:
if f.lower() in TRASH_FILES:
full = os.path.join(root, f)
rel = os.path.relpath(full, folder_path)
os.remove(full)
removed.append(rel)
return removed
# ------------------------------------------------------------
# 2) Limpieza de un archivo completo (modo actual)
# ------------------------------------------------------------
def clean_comic(path, output_path=None):
"""
Limpia un archivo CBR/CBZ:
- elimina basura
- convierte CBR → CBZ
- reconstruye solo si es necesario
"""
result = CleanResult(path)
ext = os.path.splitext(path)[1].lower()
# 1) Abrir archivo
if ext == ".cbr":
archive = try_open_rar(path)
if archive:
real_format = "rar"
else:
archive = try_open_zip(path)
if archive:
real_format = "zip"
else:
raise Exception(f"No se puede abrir {path}")
elif ext == ".cbz":
archive = try_open_zip(path)
if archive:
real_format = "zip"
else:
raise Exception(f"No se puede abrir {path}")
# 2) Extraer a carpeta temporal
temp_dir = tempfile.mkdtemp()
archive.extractall(temp_dir)
archive.close()
# 3) Limpiar carpeta
removed = clean_folder(temp_dir)
result.removed_files = removed
# 4) Determinar si hay que reconstruir
changes_needed = False
if removed:
changes_needed = True
if ext == ".cbr":
changes_needed = True
result.converted_to_cbz = True
if not changes_needed:
result.cleaned_path = path
shutil.rmtree(temp_dir)
return result
# 5) Ruta final
if output_path:
final_path = output_path
else:
base, _ = os.path.splitext(path)
final_path = base + ".cbz"
result.cleaned_path = final_path
# 6) Reempaquetar como CBZ
with zipfile.ZipFile(final_path, "w", zipfile.ZIP_DEFLATED) as new_zip:
for root, _, files in os.walk(temp_dir):
for f in files:
full = os.path.join(root, f)
rel = os.path.relpath(full, temp_dir)
new_zip.write(full, rel)
result.repacked = True
shutil.rmtree(temp_dir)
return result