import filters for pixiv sidecars, tag filtering, and favicon generation
This commit is contained in:
+944
-944
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@ def find_sidecar_json(image_path: str) -> Optional[str]:
|
||||
Gallery-DL creates JSON files with various naming patterns:
|
||||
- Patreon: {filename}.json in same directory
|
||||
- HentaiFoundry: {artist}-{index}-{title}.json (may differ from image filename)
|
||||
- Pixiv: {id}_p{num}.json for image named {id}_{title}_{num}.png
|
||||
- UUID-based: {uuid}.json where UUID is extracted from filename
|
||||
|
||||
Returns the path to the sidecar JSON if found, None otherwise.
|
||||
@@ -50,7 +51,19 @@ def find_sidecar_json(image_path: str) -> Optional[str]:
|
||||
if direct_json.exists():
|
||||
return str(direct_json)
|
||||
|
||||
# Pattern 3: Extract UUID from filename and look for {uuid}.json
|
||||
# Pattern 3: Pixiv naming pattern
|
||||
# Image: {id}_{title}_{num}.png (e.g., "115358744_Koseki Bijou (Bunny)_00.png")
|
||||
# JSON: {id}_p{num}.json (e.g., "115358744_p0.json")
|
||||
# Extract the leading numeric ID and trailing index
|
||||
pixiv_match = re.match(r'^(\d{6,12})_.*_(\d{2})$', stem)
|
||||
if pixiv_match:
|
||||
pixiv_id = pixiv_match.group(1)
|
||||
pixiv_num = int(pixiv_match.group(2)) # Convert "00" to 0
|
||||
pixiv_json = parent_dir / f"{pixiv_id}_p{pixiv_num}.json"
|
||||
if pixiv_json.exists():
|
||||
return str(pixiv_json)
|
||||
|
||||
# Pattern 4: Extract UUID from filename and look for {uuid}.json
|
||||
# Common patterns: "01_UUID", "UUID", "{num}_{UUID}"
|
||||
uuid_pattern = re.compile(r'([A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12})', re.IGNORECASE)
|
||||
match = uuid_pattern.search(stem)
|
||||
@@ -60,7 +73,7 @@ def find_sidecar_json(image_path: str) -> Optional[str]:
|
||||
if uuid_json.exists():
|
||||
return str(uuid_json)
|
||||
|
||||
# Pattern 4: Just the stem without prefix numbers
|
||||
# Pattern 5: Just the stem without prefix numbers
|
||||
# e.g., "01_filename" -> look for "filename.json"
|
||||
stem_no_prefix = re.sub(r'^\d+_', '', stem)
|
||||
if stem_no_prefix != stem:
|
||||
@@ -68,7 +81,7 @@ def find_sidecar_json(image_path: str) -> Optional[str]:
|
||||
if alt_json.exists():
|
||||
return str(alt_json)
|
||||
|
||||
# Pattern 5: Extract numeric ID from filename and find JSON with same ID
|
||||
# Pattern 6: Extract numeric ID from filename and find JSON with same ID
|
||||
# Handles HentaiFoundry where image is "hentaifoundry_1000220_title.jpg"
|
||||
# but JSON is "Artist-1000220-title.json"
|
||||
# Look for a 5-7 digit number that could be a post ID
|
||||
@@ -165,7 +178,7 @@ def load_sidecar_metadata(json_path: str) -> Optional[dict]:
|
||||
|
||||
def extract_platform(metadata: dict) -> Optional[str]:
|
||||
"""Extract the platform name from metadata."""
|
||||
# Check common fields
|
||||
# Check common fields (covers Pixiv which uses "category": "pixiv")
|
||||
if "category" in metadata:
|
||||
return metadata["category"].lower()
|
||||
|
||||
@@ -179,6 +192,8 @@ def extract_platform(metadata: dict) -> Optional[str]:
|
||||
return "subscribestar"
|
||||
if "discord.com" in url:
|
||||
return "discord"
|
||||
if "pixiv.net" in url or "pximg.net" in url:
|
||||
return "pixiv"
|
||||
|
||||
return None
|
||||
|
||||
@@ -195,8 +210,13 @@ def extract_artist(metadata: dict) -> Optional[str]:
|
||||
if "artist" in metadata:
|
||||
return metadata["artist"]
|
||||
|
||||
# For hentaifoundry
|
||||
if "user" in metadata:
|
||||
# For Pixiv - user is an object with name and account fields
|
||||
if "user" in metadata and isinstance(metadata["user"], dict):
|
||||
# Prefer account (username) over display name for consistency
|
||||
return metadata["user"].get("account") or metadata["user"].get("name")
|
||||
|
||||
# For hentaifoundry - user is a string
|
||||
if "user" in metadata and isinstance(metadata["user"], str):
|
||||
return metadata["user"]
|
||||
|
||||
return None
|
||||
@@ -238,6 +258,7 @@ def extract_description(metadata: dict) -> Optional[str]:
|
||||
- Patreon: 'content' (may be HTML)
|
||||
- SubscribeStar: 'content' (may be HTML)
|
||||
- HentaiFoundry: 'description' (plain text)
|
||||
- Pixiv: 'caption' (plain text or HTML)
|
||||
"""
|
||||
# Try description first (HentaiFoundry uses this)
|
||||
if "description" in metadata:
|
||||
@@ -245,6 +266,12 @@ def extract_description(metadata: dict) -> Optional[str]:
|
||||
if desc and isinstance(desc, str) and desc.strip():
|
||||
return desc.strip()
|
||||
|
||||
# Try caption (Pixiv uses this)
|
||||
if "caption" in metadata:
|
||||
caption = metadata["caption"]
|
||||
if caption and isinstance(caption, str) and caption.strip():
|
||||
return caption.strip()
|
||||
|
||||
# Try content (Patreon/SubscribeStar use this)
|
||||
if "content" in metadata:
|
||||
content = metadata["content"]
|
||||
@@ -268,14 +295,23 @@ def extract_source_url(metadata: dict) -> Optional[str]:
|
||||
- Patreon: 'url' (direct post link)
|
||||
- SubscribeStar: construct from author_name and post_id
|
||||
- HentaiFoundry: construct from user and index
|
||||
- Pixiv: construct from id
|
||||
"""
|
||||
platform = extract_platform(metadata)
|
||||
|
||||
# Direct URL field (Patreon)
|
||||
# Construct URL for Pixiv (do this first to avoid using the pximg.net image URL)
|
||||
if platform == "pixiv":
|
||||
post_id = metadata.get("id")
|
||||
if post_id:
|
||||
return f"https://www.pixiv.net/artworks/{post_id}"
|
||||
|
||||
# Direct URL field (Patreon) - but not for Pixiv where 'url' is the image URL
|
||||
if "url" in metadata:
|
||||
url = metadata["url"]
|
||||
if url and isinstance(url, str) and url.startswith("http"):
|
||||
return url
|
||||
# Skip pximg.net URLs (these are image URLs, not post URLs)
|
||||
if "pximg.net" not in url:
|
||||
return url
|
||||
|
||||
# Construct URL for SubscribeStar
|
||||
if platform == "subscribestar":
|
||||
@@ -298,6 +334,10 @@ def extract_attachment_count(metadata: dict) -> int:
|
||||
"""
|
||||
Extract the number of attachments/images in the post.
|
||||
"""
|
||||
# Pixiv: use page_count field
|
||||
if "page_count" in metadata:
|
||||
return int(metadata["page_count"])
|
||||
|
||||
# Patreon: check images array or post_metadata.image_order
|
||||
if "images" in metadata and isinstance(metadata["images"], list):
|
||||
return len(metadata["images"])
|
||||
@@ -319,7 +359,8 @@ def extract_date(metadata: dict) -> Optional[datetime]:
|
||||
Extract the publication/post date from metadata.
|
||||
Tries multiple common date fields and formats.
|
||||
"""
|
||||
date_fields = ["published_at", "date", "created_at", "timestamp"]
|
||||
# Pixiv uses create_date, others use published_at, date, etc.
|
||||
date_fields = ["published_at", "create_date", "date", "created_at", "timestamp"]
|
||||
|
||||
for field in date_fields:
|
||||
if field not in metadata:
|
||||
|
||||
Reference in New Issue
Block a user