#!/usr/bin/env python3 """Regenerate all thumbnails for Fansly attachments.""" import os import sys import subprocess import io from pathlib import Path from PIL import Image # Bootstrap PostgreSQL adapter before any sqlite3 imports sys.path.insert(0, '/opt/media-downloader') from modules.db_bootstrap import bootstrap_database bootstrap_database() import sqlite3 # Database path (routed to PostgreSQL via pgadapter) DB_PATH = '/opt/media-downloader/database/media_downloader.db' THUMB_CACHE = Path('/opt/media-downloader/cache/thumbnails/large') MAX_SIZE = (800, 800) def generate_thumbnail(file_path, file_type): """Generate thumbnail for image or video.""" try: if file_type == 'image': with Image.open(file_path) as img: img.thumbnail(MAX_SIZE, Image.LANCZOS) if img.mode in ('RGBA', 'P'): img = img.convert('RGB') buffer = io.BytesIO() img.save(buffer, format='JPEG', quality=85) return buffer.getvalue() elif file_type == 'video': cmd = [ 'ffmpeg', '-y', '-ss', '1', '-i', str(file_path), '-vframes', '1', '-f', 'image2pipe', '-vcodec', 'mjpeg', '-' ] result = subprocess.run(cmd, capture_output=True, timeout=30) if result.returncode == 0 and result.stdout: with Image.open(io.BytesIO(result.stdout)) as img: img.thumbnail(MAX_SIZE, Image.LANCZOS) if img.mode in ('RGBA', 'P'): img = img.convert('RGB') buffer = io.BytesIO() img.save(buffer, format='JPEG', quality=85) return buffer.getvalue() except Exception as e: print(f" Error: {e}") return None def main(): THUMB_CACHE.mkdir(parents=True, exist_ok=True) conn = sqlite3.connect(DB_PATH) cursor = conn.execute(""" SELECT a.id, a.local_path, a.file_type FROM paid_content_attachments a JOIN paid_content_posts p ON a.post_id = p.id JOIN paid_content_creators c ON p.creator_id = c.id WHERE c.service_id = 'fansly_direct' AND a.status = 'completed' AND a.local_path IS NOT NULL ORDER BY a.id """) attachments = cursor.fetchall() conn.close() print(f"Regenerating thumbnails for {len(attachments)} files...") generated = 0 failed = 0 missing = 0 for i, (att_id, local_path, file_type) in enumerate(attachments): if i % 100 == 0: print(f"Progress: {i}/{len(attachments)} (generated: {generated}, failed: {failed})") file_path = Path(local_path) if not file_path.exists(): missing += 1 continue thumb_data = generate_thumbnail(file_path, file_type) if thumb_data: thumb_file = THUMB_CACHE / f"{att_id}.jpg" thumb_file.write_bytes(thumb_data) generated += 1 else: failed += 1 print(f" Failed: {att_id} - {local_path}") print(f"\nDone!") print(f" Generated: {generated}") print(f" Failed: {failed}") print(f" Missing files: {missing}") if __name__ == '__main__': main()