added new gemini creations
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
import logging
|
||||
from .samba_manager import SambaManager
|
||||
from .config import Settings
|
||||
from smb.smb_structs import OperationFailure
|
||||
|
||||
# --- Dedicated logger for ComicsManager ---
|
||||
comics_logger = logging.getLogger('comics_manager')
|
||||
comics_logger.setLevel(logging.INFO)
|
||||
comics_logger.propagate = False
|
||||
if not comics_logger.handlers:
|
||||
comics_log_handler = logging.FileHandler("logs/comics_organization.log", mode='a')
|
||||
comics_log_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
|
||||
comics_logger.addHandler(comics_log_handler)
|
||||
comics_logger.addHandler(logging.StreamHandler())
|
||||
|
||||
# --- Disable noisy pysmb logger ---
|
||||
# Temporarily set the pysmb logger levels to CRITICAL to silence its output.
|
||||
# This needs to be set *after* basicConfig if pysmb initializes its loggers earlier.
|
||||
try:
|
||||
logging.getLogger("smb").setLevel(logging.CRITICAL)
|
||||
logging.getLogger("smb.SMBConnection").setLevel(logging.CRITICAL)
|
||||
except Exception:
|
||||
# Handle cases where the logger might not be fully initialized yet
|
||||
pass
|
||||
# ---
|
||||
|
||||
class ComicsManager:
|
||||
def __init__(self, settings: Settings):
|
||||
self.settings = settings
|
||||
self.db = None # ComicsManager doesn't use DB
|
||||
self.samba_manager = SambaManager(
|
||||
settings.samba_server_ip,
|
||||
"isolation",
|
||||
settings.samba_username,
|
||||
settings.samba_password,
|
||||
)
|
||||
self.comics_root = "/comics/toberead"
|
||||
self.comics_dest_root = "/comics/manga"
|
||||
|
||||
def _get_series_name(self, filename):
|
||||
base_name, _ = os.path.splitext(filename)
|
||||
# This regex is more aggressive at cleaning up chapter/volume numbers and other noise.
|
||||
# It looks for common patterns like 'ch.10', 'v02', '123', etc.
|
||||
pattern = re.compile(r'[-_\s]*(v(ol)?|c(h)?|chapter|issue|ep|episode)[-_\s]*\d+.*|[-_\s]+\d+$', re.IGNORECASE)
|
||||
match = pattern.search(base_name)
|
||||
if match:
|
||||
return base_name[:match.start()].strip('-_ ')
|
||||
return base_name.strip('-_ ')
|
||||
|
||||
def organize_comics(self):
|
||||
comics_logger.info("Starting comics organization process...")
|
||||
try:
|
||||
items_in_toberead = self.samba_manager.list_path(self.comics_root)
|
||||
if "error" in items_in_toberead:
|
||||
raise Exception(f"Failed to list files in 'toberead': {items_in_toberead['error']}")
|
||||
|
||||
series_chapters = defaultdict(list)
|
||||
for item in items_in_toberead:
|
||||
if not item["is_directory"]:
|
||||
series_name = self._get_series_name(item["name"])
|
||||
series_chapters[series_name].append(item)
|
||||
|
||||
comics_logger.info(f"Found {len(series_chapters)} series to process.")
|
||||
|
||||
for series_name, chapters in series_chapters.items():
|
||||
comics_logger.info(f"Processing series: {series_name}")
|
||||
# Ensure paths use forward slashes for Samba operations
|
||||
final_series_folder_path = f"{self.comics_dest_root}/{series_name}".replace("\", "/")
|
||||
|
||||
try:
|
||||
self.samba_manager.create_directory(final_series_folder_path)
|
||||
comics_logger.info(f"Created directory: {final_series_folder_path}")
|
||||
except OperationFailure as e:
|
||||
# Specific check for FILE_OBJECT_NAME_COLLISION if directory already exists
|
||||
if "FILE_OBJECT_NAME_COLLISION" in str(e):
|
||||
comics_logger.info(f"Directory {final_series_folder_path} already exists. Skipping creation.")
|
||||
else:
|
||||
comics_logger.error(f"Could not create directory {final_series_folder_path}: {e}")
|
||||
|
||||
for chapter_item in chapters:
|
||||
# Sanitize original path coming from list_path
|
||||
original_path = chapter_item["path"].replace("\", "/")
|
||||
original_filename = chapter_item["name"]
|
||||
|
||||
path_to_move = ""
|
||||
filename_to_move = ""
|
||||
|
||||
if original_filename.lower().endswith('.zip'):
|
||||
cbz_filename = os.path.splitext(original_filename)[0] + '.cbz'
|
||||
temp_cbz_path = f"{self.comics_root}/{cbz_filename}".replace("\", "/")
|
||||
|
||||
try:
|
||||
self.samba_manager.rename_file(original_path, temp_cbz_path)
|
||||
path_to_move = temp_cbz_path
|
||||
filename_to_move = cbz_filename
|
||||
comics_logger.info(f"Renamed {original_filename} to {cbz_filename}")
|
||||
except OperationFailure as e:
|
||||
comics_logger.error(f"Failed to rename ZIP {original_filename} to CBZ: {e}")
|
||||
continue # Skip to next chapter if rename fails
|
||||
|
||||
elif original_filename.lower().endswith('.cbz'):
|
||||
# If it's already a .cbz, it's ready to be moved
|
||||
path_to_move = original_path
|
||||
filename_to_move = original_filename
|
||||
else:
|
||||
comics_logger.warning(f"Skipping non-zip/cbz file: {original_filename}")
|
||||
continue
|
||||
|
||||
# Final destination path for the CBZ file
|
||||
final_cbz_path = f"{final_series_folder_path}/{filename_to_move}".replace("\", "/")
|
||||
|
||||
try:
|
||||
self.samba_manager.rename_file(path_to_move, final_cbz_path)
|
||||
comics_logger.info(f"Moved {filename_to_move} to {final_series_folder_path}")
|
||||
except OperationFailure as e:
|
||||
comics_logger.error(f"Failed to move {filename_to_move} to {final_series_folder_path}: {e}")
|
||||
|
||||
except Exception as e:
|
||||
comics_logger.error(f"An unexpected error occurred during comics organization: {e}", exc_info=True)
|
||||
|
||||
finally:
|
||||
comics_logger.info("Comics organization process finished.")
|
||||
self.samba_manager.close()
|
||||
|
||||
return
|
||||
Reference in New Issue
Block a user