Hey there
I have thousands of zip galleries and a lot of them have a performer name in the zip filename. Is there a way to scan galleries and automatically link them to a performer when that performer name appears in the zip filename? Something similar to what is done when scraping scenes with “auto tag”.
I searched the plugins for gallery related stuff but noting like that.
Thanks!
p.s.
I looked at the DB structure and I realized this could be done directly in SQL (or in python) as the filenames are there and there is that performers_galleries table also. Not sure how to do it though. Any help on this would be greatly appreciated.
So I wrote a python script to do it. I made 2 backups the DB, ran the script on one of those and replaced the “main” DB with the modified backup. It linked some ~13000 galleries to their performers!
The script takes the DB as parameter.
The script only considers performers whose names have at least 2 “words”, otherwise it was really messy.
Enjoy 
import sqlite3
from collections import defaultdict
import logging
import sys
import os
# Validate command-line arguments
if len(sys.argv) < 2:
print("Usage: python link_performers.py <database_file>")
sys.exit(1)
db_path = sys.argv[1]
if not os.path.exists(db_path):
print(f"Error: Database file '{db_path}' not found.")
sys.exit(1)
# Set up loggers
logger = logging.getLogger("PerformerGalleryLinker")
logger.setLevel(logging.INFO)
# File handler (log only insertions)
file_handler = logging.FileHandler("performer_gallery_matches.log", mode='w')
file_handler.setLevel(logging.INFO)
file_formatter = logging.Formatter("%(asctime)s - %(message)s")
file_handler.setFormatter(file_formatter)
# Console handler (log all matches)
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
console_formatter = logging.Formatter("%(message)s")
console_handler.setFormatter(console_formatter)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# Connect to the SQLite database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Step 1: Load all performers (with more than one word in their name)
cursor.execute("SELECT id, name FROM performers")
performers = [(pid, name) for pid, name in cursor.fetchall() if name and len(name.strip().split()) > 1]
# Step 2: Load all files and their associated galleries
cursor.execute("""
SELECT gf.gallery_id, f.id AS file_id, f.basename
FROM galleries_files gf
JOIN files f ON gf.file_id = f.id
""")
gallery_file_links = cursor.fetchall()
# Step 3: Build a mapping from gallery_id to list of basenames
gallery_to_files = defaultdict(list)
for gallery_id, file_id, basename in gallery_file_links:
gallery_to_files[gallery_id].append((file_id, basename))
# Step 4: Match performer names to file basenames and insert links
inserted_links = []
for performer_id, performer_name in performers:
name_lower = performer_name.lower()
for gallery_id, file_info_list in gallery_to_files.items():
matched_file = None
for file_id, basename in file_info_list:
if basename and name_lower in basename.lower():
matched_file = basename
break
if matched_file:
# Check if the link already exists
cursor.execute("""
SELECT 1 FROM performers_galleries
WHERE gallery_id = ? AND performer_id = ?
""", (gallery_id, performer_id))
if cursor.fetchone() is None:
cursor.execute("""
INSERT INTO performers_galleries (gallery_id, performer_id)
VALUES (?, ?)
""", (gallery_id, performer_id))
inserted_links.append((gallery_id, performer_id))
msg = (f"Inserted: Performer '{performer_name}' (ID {performer_id}) "
f"-> Gallery {gallery_id} (matched in file '{matched_file}')")
logger.info(msg) # Logged to both file and screen
else:
msg = (f"Skipped (already exists): Performer '{performer_name}' (ID {performer_id}) "
f"-> Gallery {gallery_id} (matched in file '{matched_file}')")
console_handler.stream.write(msg + "\n") # Log only to screen
# Finalize
conn.commit()
conn.close()
# Summary
logger.info(f"\nInserted {len(inserted_links)} performer-gallery links.")
if inserted_links:
logger.info(f"Sample inserted links: {inserted_links[:10]}")
logger.info("Log written to performer_gallery_matches.log")
2 Likes