From d51cfe12d8f2e8327d423c16125bf91f7a5bce85 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 17 Aug 2026 09:42:59 -0400 Subject: [PATCH] Filter out male performers across Stash matching, AI prompts, candidate buttons and Intellisense --- qbittorrent_performer_sorter.html | 38 +++++++++++---------- server.py | 57 +++++++++++++++++++------------ 2 files changed, 55 insertions(+), 40 deletions(-) diff --git a/qbittorrent_performer_sorter.html b/qbittorrent_performer_sorter.html index 3b17e78..1649584 100644 --- a/qbittorrent_performer_sorter.html +++ b/qbittorrent_performer_sorter.html @@ -2658,17 +2658,17 @@ fileNames = torrent.innerFiles.map(f => f.name).slice(0, 15); } - const prompt = `Analyze the following adult video torrent title and internal files to identify ALL performers / actors. + const prompt = `Analyze the following adult video torrent title and internal files to identify ALL FEMALE performers / actresses. Torrent Name: "${torrent.name}" Internal Files: ${JSON.stringify(fileNames)} CRITICAL INSTRUCTIONS: -1. Extract EVERY distinct performer / actor mentioned. -2. If multiple performers appear (e.g. "Alison Rey Reagan Foxx" or "Kendra Lust and Lisa Ann"), you MUST return EACH individual person as a separate entry in the "all_performers" array: ["Alison Rey", "Reagan Foxx"]. +1. Extract ONLY distinct FEMALE performers / actresses mentioned. Completely OMIT and ignore all male performers, male actors, and directors. +2. If multiple female performers appear (e.g. "Alison Rey Reagan Foxx" or "Kendra Lust and Lisa Ann"), you MUST return EACH individual female as a separate entry in "all_performers": ["Alison Rey", "Reagan Foxx"]. 3. NEVER combine multiple performers into one 4-word name (e.g. NEVER output "Alison Rey Reagan Foxx" as a single name). 4. Ignore studio names (Brazzers, NaughtyAmerica, Blacked, Vixen, Tushy, PureTaboo, RealityKings, BangBros, TeamSkeet, EvilAngel, MissaX, etc.), resolutions, release groups, and codecs. -5. List all detected performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning. +5. List all detected female performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning. Return ONLY valid JSON matching this schema: { @@ -2719,15 +2719,16 @@ Return ONLY valid JSON matching this schema: return `[Item ${idx + 1}] ID: "${t.hash}"\nName: "${t.name}"\nFiles: ${JSON.stringify(fileNames)}`; }).join('\n\n'); - const prompt = `Analyze the following ${batchTorrents.length} adult video torrents and identify ALL performers / actors for EACH item. + const prompt = `Analyze the following ${batchTorrents.length} adult video torrents and identify ALL FEMALE performers / actresses for EACH item. ${itemsListStr} CRITICAL INSTRUCTIONS: -1. For each item, extract EVERY distinct performer / actor name. If multiple performers appear (e.g. "Alison Rey Reagan Foxx", "Kendra Lust and Lisa Ann"), list EACH person separately in "all_performers": ["Alison Rey", "Reagan Foxx"]. -2. NEVER combine two performers into a single 4-word string (e.g. NEVER output "Alison Rey Reagan Foxx"). -3. Ignore studio names (Brazzers, NaughtyAmerica, Blacked, Vixen, Tushy, PureTaboo, RealityKings, BangBros, TeamSkeet, EvilAngel, MissaX, etc.), scene numbers, resolutions, and codecs. -4. List all detected performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning. +1. For each item, extract ONLY distinct FEMALE performers / actresses. Completely OMIT and ignore all male performers, male actors, and directors. +2. If multiple female performers appear (e.g. "Alison Rey Reagan Foxx", "Kendra Lust and Lisa Ann"), list EACH female person separately in "all_performers": ["Alison Rey", "Reagan Foxx"]. +3. NEVER combine two performers into a single 4-word string (e.g. NEVER output "Alison Rey Reagan Foxx"). +4. Ignore studio names (Brazzers, NaughtyAmerica, Blacked, Vixen, Tushy, PureTaboo, RealityKings, BangBros, TeamSkeet, EvilAngel, MissaX, etc.), scene numbers, resolutions, and codecs. +5. List all detected female performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning. Return ONLY valid JSON matching: { @@ -3346,16 +3347,16 @@ Return ONLY valid JSON matching: async function analyzeSmbFileWithAI(fileItem) { const destRoot = (smbDestRootInput ? smbDestRootInput.value.trim() : '/mnt/isolation/videos').replace(/\/+$/, '') || '/mnt/isolation/videos'; - const prompt = `Analyze the following adult video filename to identify ALL performers / actors. + const prompt = `Analyze the following adult video filename to identify ALL FEMALE performers / actresses. Filename: "${fileItem.name}" CRITICAL INSTRUCTIONS: -1. Extract EVERY distinct video performer / actor mentioned. -2. If multiple performers appear (e.g. "Alison Rey Reagan Foxx" or "Kendra Lust and Lisa Ann"), you MUST return EACH individual person as a separate entry in the "all_performers" array: ["Alison Rey", "Reagan Foxx"]. +1. Extract ONLY distinct FEMALE video performers / actresses mentioned. Completely OMIT and ignore all male performers, male actors, and directors. +2. If multiple female performers appear (e.g. "Alison Rey Reagan Foxx" or "Kendra Lust and Lisa Ann"), you MUST return EACH individual female as a separate entry in "all_performers": ["Alison Rey", "Reagan Foxx"]. 3. NEVER combine multiple performers into one 4-word name (e.g. NEVER output "Alison Rey Reagan Foxx" as a single name). 4. Ignore studio names (Brazzers, NaughtyAmerica, Blacked, Vixen, Tushy, PureTaboo, RealityKings, BangBros, TeamSkeet, EvilAngel, MissaX, Family Roleplay, Spy Fam, etc.), resolutions, release groups, and codecs. -5. List all detected performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning. +5. List all detected female performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning. Return ONLY valid JSON matching this schema: { @@ -3400,15 +3401,16 @@ Return ONLY valid JSON matching this schema: return `[Item ${idx + 1}] ID: "${f.path}"\nFilename: "${f.name}"`; }).join('\n\n'); - const prompt = `Analyze the following ${batchFiles.length} adult video filenames and identify ALL performers / actors for EACH item. + const prompt = `Analyze the following ${batchFiles.length} adult video filenames and identify ALL FEMALE performers / actresses for EACH item. ${itemsListStr} CRITICAL INSTRUCTIONS: -1. For each item, extract EVERY distinct performer / actor name. If multiple performers appear (e.g. "Alison Rey Reagan Foxx", "Kendra Lust and Lisa Ann"), list EACH person separately in "all_performers": ["Alison Rey", "Reagan Foxx"]. -2. NEVER combine two performers into a single 4-word string (e.g. NEVER output "Alison Rey Reagan Foxx"). -3. Ignore studio names (Brazzers, NaughtyAmerica, Blacked, Vixen, Tushy, PureTaboo, RealityKings, BangBros, TeamSkeet, EvilAngel, MissaX, Family Roleplay, Spy Fam, etc.), scene numbers, resolutions, and codecs. -4. List all detected performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning. +1. For each item, extract ONLY distinct FEMALE performers / actresses. Completely OMIT and ignore all male performers, male actors, and directors. +2. If multiple female performers appear (e.g. "Alison Rey Reagan Foxx", "Kendra Lust and Lisa Ann"), list EACH female person separately in "all_performers": ["Alison Rey", "Reagan Foxx"]. +3. NEVER combine two performers into a single 4-word string (e.g. NEVER output "Alison Rey Reagan Foxx"). +4. Ignore studio names (Brazzers, NaughtyAmerica, Blacked, Vixen, Tushy, PureTaboo, RealityKings, BangBros, TeamSkeet, EvilAngel, MissaX, Family Roleplay, Spy Fam, etc.), scene numbers, resolutions, and codecs. +5. List all detected female performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning. Return ONLY a valid JSON object with an array named "results": { diff --git a/server.py b/server.py index ae9cd1c..f2ec2ce 100644 --- a/server.py +++ b/server.py @@ -180,22 +180,26 @@ def parse_stash_scene_data(scene, match_strategy='exact_path'): if not performers: return None - females = [p['name'] for p in performers if p.get('gender') == 'FEMALE'] - males = [p['name'] for p in performers if p.get('gender') == 'MALE'] - others = [p['name'] for p in performers if p.get('gender') not in ('FEMALE', 'MALE')] + females = [p for p in performers if p.get('gender') == 'FEMALE'] + non_males = [p for p in performers if p.get('gender') not in ('FEMALE', 'MALE')] - # Priority: Females first as primary, then others, then males - ordered_names = females + others + males - if not ordered_names: - ordered_names = [p['name'] for p in performers] + # Priority: NEVER include male performers if any female or non-male performers are present + eligible_performers = females if females else (non_males if non_males else performers) formatted_candidates = [] seen = set() - for name in ordered_names: + for p in eligible_performers: + name = p.get('name', '') fmt = format_performer_slug(name) if fmt and fmt not in seen: seen.add(fmt) - formatted_candidates.append({'raw': name, 'formatted': fmt}) + formatted_candidates.append({ + 'raw': name, + 'formatted': fmt, + 'id': p.get('id'), + 'gender': p.get('gender'), + 'image': p.get('image_path') + }) if not formatted_candidates: return None @@ -217,8 +221,8 @@ def parse_stash_scene_data(scene, match_strategy='exact_path'): 'studio': studio_name, 'primaryPerformer': primary_formatted, 'allPerformers': formatted_candidates, - 'femalePerformers': [format_performer_slug(n) for n in females], - 'malePerformers': [format_performer_slug(n) for n in males], + 'femalePerformers': [p['formatted'] for p in formatted_candidates if p.get('gender') == 'FEMALE'], + 'malePerformers': [], 'confidence': 'verified', 'reasoning': reasoning, 'matchStrategy': match_strategy @@ -781,11 +785,11 @@ class RobustProxyHandler(http.server.SimpleHTTPRequestHandler): except Exception as e: print(f"Error merging performers from DB: {e}") - # Also merge performers from Stash database if online + # Also merge female performers from Stash database if online try: - stash_q = '{ allPerformers { name } }' - res = execute_stash_graphql(stash_q, timeout=2) - for p in res.get('data', {}).get('allPerformers', []): + stash_q = '{ findPerformers(performer_filter: { gender: { value: FEMALE, modifier: EQUALS } }, filter: { per_page: -1 }) { performers { name } } }' + res = execute_stash_graphql(stash_q, timeout=3) + for p in res.get('data', {}).get('findPerformers', {}).get('performers', []): slug = format_performer_slug(p.get('name')) if slug: performers_set.add(slug) @@ -807,13 +811,22 @@ class RobustProxyHandler(http.server.SimpleHTTPRequestHandler): p_id = params.get('id', [''])[0] stash_url = params.get('url', [''])[0] - content_type, img_bytes = fetch_performer_image_data(name, p_id, stash_url) - self.send_response(200) - self.send_header('Content-Type', content_type) - self.send_header('Cache-Control', 'public, max-age=86400') - self.send_cors_headers() - self.end_headers() - self.wfile.write(img_bytes) + try: + content_type, img_bytes = fetch_performer_image_data(name, p_id, stash_url) + self.send_response(200) + self.send_header('Content-Type', content_type) + self.send_header('Cache-Control', 'public, max-age=86400') + self.send_cors_headers() + self.end_headers() + self.wfile.write(img_bytes) + except (BrokenPipeError, ConnectionResetError): + pass + except Exception as e: + try: + self.send_response(500) + self.end_headers() + except Exception: + pass # ==================== Stash Server API Handlers ==================== def handle_stash_status(self):