tuning job log views and deep scan archive processing.
This commit is contained in:
@@ -846,8 +846,69 @@ def is_first_volume(path: str) -> bool:
|
||||
|
||||
return True
|
||||
|
||||
def extract_archive_name(filename: str) -> str:
|
||||
"""
|
||||
Extract a clean archive name from a filename by removing common prefixes.
|
||||
|
||||
Handles patterns like:
|
||||
- "43387617_attachment_83109081_October 2020 Rewards.rar" -> "October 2020 Rewards"
|
||||
- "01_Archive Name.zip" -> "Archive Name"
|
||||
- "Archive Name.rar" -> "Archive Name"
|
||||
|
||||
Returns the cleaned name without extension.
|
||||
"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
# Remove extension
|
||||
stem = Path(filename).stem
|
||||
|
||||
# Pattern 1: Gallery-DL style "{id}_attachment_{id}_{name}" or "{id}_{name}"
|
||||
# Match one or more numeric_prefix patterns at the start
|
||||
cleaned = re.sub(r'^(\d+_)+(attachment_)?(\d+_)?', '', stem)
|
||||
|
||||
# Pattern 2: Simple numeric prefix "01_name" or "001_name"
|
||||
if cleaned == stem: # No match from pattern 1
|
||||
cleaned = re.sub(r'^\d+_', '', stem)
|
||||
|
||||
# If we stripped everything or got empty, fall back to original stem
|
||||
if not cleaned.strip():
|
||||
cleaned = stem
|
||||
|
||||
return cleaned.strip()
|
||||
|
||||
|
||||
def compute_archive_tag_name(artist: str, archive_filename: str) -> str:
|
||||
"""
|
||||
Generate an archive tag name in the format: '{artist}:{archive_name}'
|
||||
|
||||
Examples:
|
||||
- artist="InCaseArt", filename="43387617_attachment_83109081_October 2020 Rewards.rar"
|
||||
-> "InCaseArt:October 2020 Rewards"
|
||||
|
||||
If a tag with the same name already exists, appends a numeric suffix.
|
||||
"""
|
||||
archive_name = extract_archive_name(archive_filename)
|
||||
base_tag = f"{artist}:{archive_name}"
|
||||
|
||||
# Check if tag already exists
|
||||
existing = Tag.query.filter_by(name=base_tag, kind='archive').first()
|
||||
if not existing:
|
||||
return base_tag
|
||||
|
||||
# Tag exists, add numeric suffix
|
||||
n = 2
|
||||
while True:
|
||||
candidate = f"{base_tag} ({n})"
|
||||
if not Tag.query.filter_by(name=candidate, kind='archive').first():
|
||||
return candidate
|
||||
n += 1
|
||||
|
||||
|
||||
def compute_next_archive_tag_name(artist: str, width: int = ARCHIVE_NUM_WIDTH) -> str:
|
||||
"""
|
||||
DEPRECATED: Use compute_archive_tag_name() instead.
|
||||
|
||||
Return a unique incremental tag name like: 'archive:{artist}/0001', '0002', ...
|
||||
- Looks only at Tag(kind='archive') with names starting 'archive:{artist}/'
|
||||
- Finds max numeric suffix and returns next number (zero-padded).
|
||||
|
||||
@@ -83,6 +83,72 @@ def find_sidecar_json(image_path: str) -> Optional[str]:
|
||||
return None
|
||||
|
||||
|
||||
def find_archive_sidecar(archive_path: str) -> Optional[str]:
|
||||
"""
|
||||
Find the Gallery-DL sidecar JSON file for an archive.
|
||||
|
||||
Gallery-DL names sidecars based on the archive's content filename,
|
||||
which may differ from the archive filename due to prefixes added
|
||||
during download (e.g., "02_HolyMeh July 2023.rar" -> "HolyMeh July 2023.json").
|
||||
|
||||
Args:
|
||||
archive_path: Path to the archive file (e.g., "02_Filename.rar")
|
||||
|
||||
Returns:
|
||||
Path to the sidecar JSON if found, None otherwise.
|
||||
"""
|
||||
archive_path = Path(archive_path)
|
||||
parent_dir = archive_path.parent
|
||||
stem = archive_path.stem # filename without extension
|
||||
|
||||
# Pattern 1: Exact stem match (most common case)
|
||||
# e.g., "HolyMeh July 2023.rar" -> "HolyMeh July 2023.json"
|
||||
stem_json = parent_dir / f"{stem}.json"
|
||||
if stem_json.exists():
|
||||
return str(stem_json)
|
||||
|
||||
# Pattern 2: Strip numeric prefix from archive name
|
||||
# e.g., "02_HolyMeh July 2023.rar" -> "HolyMeh July 2023.json"
|
||||
stem_no_prefix = re.sub(r'^\d+_', '', stem)
|
||||
if stem_no_prefix != stem:
|
||||
alt_json = parent_dir / f"{stem_no_prefix}.json"
|
||||
if alt_json.exists():
|
||||
return str(alt_json)
|
||||
|
||||
# Pattern 3: Look for any JSON in the directory that references this archive
|
||||
# by checking the 'file_name' or 'filename' field in the JSON
|
||||
for json_file in parent_dir.glob("*.json"):
|
||||
try:
|
||||
with open(json_file, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Check if this JSON references our archive
|
||||
# Gallery-DL uses 'file.file_name' or 'filename' + 'extension'
|
||||
file_info = data.get("file", {})
|
||||
json_filename = file_info.get("file_name", "")
|
||||
if not json_filename:
|
||||
# Try filename + extension pattern
|
||||
fn = data.get("filename", "")
|
||||
ext = data.get("extension", "")
|
||||
if fn and ext:
|
||||
json_filename = f"{fn}.{ext}"
|
||||
|
||||
# Compare with archive filename (with or without prefix)
|
||||
archive_filename = archive_path.name
|
||||
archive_filename_no_prefix = re.sub(r'^\d+_', '', archive_filename)
|
||||
|
||||
if json_filename and (
|
||||
json_filename == archive_filename or
|
||||
json_filename == archive_filename_no_prefix
|
||||
):
|
||||
return str(json_file)
|
||||
|
||||
except (json.JSONDecodeError, IOError):
|
||||
continue
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def load_sidecar_metadata(json_path: str) -> Optional[dict]:
|
||||
"""Load and parse a Gallery-DL sidecar JSON file."""
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user