102 lines
2.5 KiB
Python
102 lines
2.5 KiB
Python
# processors/validator.py
|
|
|
|
import os
|
|
import zipfile
|
|
import rarfile
|
|
from core.constants import IMAGE_EXTENSIONS, TRASH_FILES
|
|
|
|
|
|
IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp"}
|
|
TRASH_FILES = {"thumbs.db", ".ds_store"}
|
|
|
|
class ValidationResult:
|
|
def __init__(self, path):
|
|
self.path = path
|
|
self.is_valid = True
|
|
self.errors = []
|
|
self.warnings = []
|
|
self.images = []
|
|
self.real_format = None # "rar", "zip", None
|
|
|
|
def add_error(self, msg):
|
|
self.is_valid = False
|
|
self.errors.append(msg)
|
|
|
|
def add_warning(self, msg):
|
|
self.warnings.append(msg)
|
|
|
|
def __str__(self):
|
|
status = "OK" if self.is_valid else "ERROR"
|
|
return f"[{status}] {self.path}"
|
|
|
|
|
|
def try_open_rar(path):
|
|
try:
|
|
archive = rarfile.RarFile(path, "r")
|
|
archive.namelist() # fuerza lectura
|
|
return archive
|
|
except:
|
|
return None
|
|
|
|
|
|
def try_open_zip(path):
|
|
try:
|
|
archive = zipfile.ZipFile(path, "r")
|
|
archive.namelist()
|
|
return archive
|
|
except:
|
|
return None
|
|
|
|
|
|
def validate_comic(path):
|
|
result = ValidationResult(path)
|
|
ext = os.path.splitext(path)[1].lower()
|
|
|
|
archive = None
|
|
|
|
# 1) Intentar abrir como RAR
|
|
if ext == ".cbr":
|
|
archive = try_open_rar(path)
|
|
if archive:
|
|
result.real_format = "rar"
|
|
else:
|
|
# 2) Intentar abrir como ZIP (CBZ renombrado)
|
|
archive = try_open_zip(path)
|
|
if archive:
|
|
result.real_format = "zip"
|
|
result.add_warning("El archivo tiene extensión .cbr pero es un ZIP (CBZ renombrado)")
|
|
else:
|
|
result.add_error("No se pudo abrir como RAR ni como ZIP")
|
|
return result
|
|
|
|
# 3) Si es CBZ, abrir como ZIP
|
|
elif ext == ".cbz":
|
|
archive = try_open_zip(path)
|
|
if archive:
|
|
result.real_format = "zip"
|
|
else:
|
|
result.add_error("No se pudo abrir el archivo ZIP")
|
|
return result
|
|
|
|
else:
|
|
result.add_error("Extensión no reconocida")
|
|
return result
|
|
|
|
# 4) Validar contenido
|
|
file_list = archive.namelist()
|
|
|
|
for f in file_list:
|
|
name = f.lower()
|
|
_, fext = os.path.splitext(name)
|
|
|
|
if fext in IMAGE_EXTENSIONS:
|
|
result.images.append(f)
|
|
|
|
if os.path.basename(name) in TRASH_FILES:
|
|
result.add_warning(f"Archivo basura encontrado: {f}")
|
|
|
|
if not result.images:
|
|
result.add_error("No contiene imágenes válidas")
|
|
|
|
return result
|