140 lines
3.7 KiB
Python
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
|