Filter out male performers across Stash matching, AI prompts, candidate buttons and Intellisense
This commit is contained in:
@@ -2658,17 +2658,17 @@
|
|||||||
fileNames = torrent.innerFiles.map(f => f.name).slice(0, 15);
|
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}"
|
Torrent Name: "${torrent.name}"
|
||||||
Internal Files: ${JSON.stringify(fileNames)}
|
Internal Files: ${JSON.stringify(fileNames)}
|
||||||
|
|
||||||
CRITICAL INSTRUCTIONS:
|
CRITICAL INSTRUCTIONS:
|
||||||
1. Extract EVERY distinct performer / actor mentioned.
|
1. Extract ONLY distinct FEMALE performers / actresses mentioned. Completely OMIT and ignore all male performers, male actors, and directors.
|
||||||
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"].
|
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).
|
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.
|
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:
|
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)}`;
|
return `[Item ${idx + 1}] ID: "${t.hash}"\nName: "${t.name}"\nFiles: ${JSON.stringify(fileNames)}`;
|
||||||
}).join('\n\n');
|
}).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}
|
${itemsListStr}
|
||||||
|
|
||||||
CRITICAL INSTRUCTIONS:
|
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"].
|
1. For each item, extract ONLY distinct FEMALE performers / actresses. Completely OMIT and ignore all male performers, male actors, and directors.
|
||||||
2. NEVER combine two performers into a single 4-word string (e.g. NEVER output "Alison Rey Reagan Foxx").
|
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. Ignore studio names (Brazzers, NaughtyAmerica, Blacked, Vixen, Tushy, PureTaboo, RealityKings, BangBros, TeamSkeet, EvilAngel, MissaX, etc.), scene numbers, resolutions, and codecs.
|
3. NEVER combine two performers into a single 4-word string (e.g. NEVER output "Alison Rey Reagan Foxx").
|
||||||
4. List all detected performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning.
|
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:
|
Return ONLY valid JSON matching:
|
||||||
{
|
{
|
||||||
@@ -3346,16 +3347,16 @@ Return ONLY valid JSON matching:
|
|||||||
async function analyzeSmbFileWithAI(fileItem) {
|
async function analyzeSmbFileWithAI(fileItem) {
|
||||||
const destRoot = (smbDestRootInput ? smbDestRootInput.value.trim() : '/mnt/isolation/videos').replace(/\/+$/, '') || '/mnt/isolation/videos';
|
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}"
|
Filename: "${fileItem.name}"
|
||||||
|
|
||||||
CRITICAL INSTRUCTIONS:
|
CRITICAL INSTRUCTIONS:
|
||||||
1. Extract EVERY distinct video performer / actor mentioned.
|
1. Extract ONLY distinct FEMALE video performers / actresses mentioned. Completely OMIT and ignore all male performers, male actors, and directors.
|
||||||
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"].
|
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).
|
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.
|
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:
|
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}"`;
|
return `[Item ${idx + 1}] ID: "${f.path}"\nFilename: "${f.name}"`;
|
||||||
}).join('\n\n');
|
}).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}
|
${itemsListStr}
|
||||||
|
|
||||||
CRITICAL INSTRUCTIONS:
|
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"].
|
1. For each item, extract ONLY distinct FEMALE performers / actresses. Completely OMIT and ignore all male performers, male actors, and directors.
|
||||||
2. NEVER combine two performers into a single 4-word string (e.g. NEVER output "Alison Rey Reagan Foxx").
|
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. Ignore studio names (Brazzers, NaughtyAmerica, Blacked, Vixen, Tushy, PureTaboo, RealityKings, BangBros, TeamSkeet, EvilAngel, MissaX, Family Roleplay, Spy Fam, etc.), scene numbers, resolutions, and codecs.
|
3. NEVER combine two performers into a single 4-word string (e.g. NEVER output "Alison Rey Reagan Foxx").
|
||||||
4. List all detected performers in "all_performers", pick the primary performer in "primary_performer", assign confidence ('high'|'medium'|'low'), and short reasoning.
|
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":
|
Return ONLY a valid JSON object with an array named "results":
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -180,22 +180,26 @@ def parse_stash_scene_data(scene, match_strategy='exact_path'):
|
|||||||
if not performers:
|
if not performers:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
females = [p['name'] for p in performers if p.get('gender') == 'FEMALE']
|
females = [p for p in performers if p.get('gender') == 'FEMALE']
|
||||||
males = [p['name'] for p in performers if p.get('gender') == 'MALE']
|
non_males = [p for p in performers if p.get('gender') not in ('FEMALE', 'MALE')]
|
||||||
others = [p['name'] for p in performers if p.get('gender') not in ('FEMALE', 'MALE')]
|
|
||||||
|
|
||||||
# Priority: Females first as primary, then others, then males
|
# Priority: NEVER include male performers if any female or non-male performers are present
|
||||||
ordered_names = females + others + males
|
eligible_performers = females if females else (non_males if non_males else performers)
|
||||||
if not ordered_names:
|
|
||||||
ordered_names = [p['name'] for p in performers]
|
|
||||||
|
|
||||||
formatted_candidates = []
|
formatted_candidates = []
|
||||||
seen = set()
|
seen = set()
|
||||||
for name in ordered_names:
|
for p in eligible_performers:
|
||||||
|
name = p.get('name', '')
|
||||||
fmt = format_performer_slug(name)
|
fmt = format_performer_slug(name)
|
||||||
if fmt and fmt not in seen:
|
if fmt and fmt not in seen:
|
||||||
seen.add(fmt)
|
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:
|
if not formatted_candidates:
|
||||||
return None
|
return None
|
||||||
@@ -217,8 +221,8 @@ def parse_stash_scene_data(scene, match_strategy='exact_path'):
|
|||||||
'studio': studio_name,
|
'studio': studio_name,
|
||||||
'primaryPerformer': primary_formatted,
|
'primaryPerformer': primary_formatted,
|
||||||
'allPerformers': formatted_candidates,
|
'allPerformers': formatted_candidates,
|
||||||
'femalePerformers': [format_performer_slug(n) for n in females],
|
'femalePerformers': [p['formatted'] for p in formatted_candidates if p.get('gender') == 'FEMALE'],
|
||||||
'malePerformers': [format_performer_slug(n) for n in males],
|
'malePerformers': [],
|
||||||
'confidence': 'verified',
|
'confidence': 'verified',
|
||||||
'reasoning': reasoning,
|
'reasoning': reasoning,
|
||||||
'matchStrategy': match_strategy
|
'matchStrategy': match_strategy
|
||||||
@@ -781,11 +785,11 @@ class RobustProxyHandler(http.server.SimpleHTTPRequestHandler):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error merging performers from DB: {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:
|
try:
|
||||||
stash_q = '{ allPerformers { name } }'
|
stash_q = '{ findPerformers(performer_filter: { gender: { value: FEMALE, modifier: EQUALS } }, filter: { per_page: -1 }) { performers { name } } }'
|
||||||
res = execute_stash_graphql(stash_q, timeout=2)
|
res = execute_stash_graphql(stash_q, timeout=3)
|
||||||
for p in res.get('data', {}).get('allPerformers', []):
|
for p in res.get('data', {}).get('findPerformers', {}).get('performers', []):
|
||||||
slug = format_performer_slug(p.get('name'))
|
slug = format_performer_slug(p.get('name'))
|
||||||
if slug:
|
if slug:
|
||||||
performers_set.add(slug)
|
performers_set.add(slug)
|
||||||
@@ -807,6 +811,7 @@ class RobustProxyHandler(http.server.SimpleHTTPRequestHandler):
|
|||||||
p_id = params.get('id', [''])[0]
|
p_id = params.get('id', [''])[0]
|
||||||
stash_url = params.get('url', [''])[0]
|
stash_url = params.get('url', [''])[0]
|
||||||
|
|
||||||
|
try:
|
||||||
content_type, img_bytes = fetch_performer_image_data(name, p_id, stash_url)
|
content_type, img_bytes = fetch_performer_image_data(name, p_id, stash_url)
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header('Content-Type', content_type)
|
self.send_header('Content-Type', content_type)
|
||||||
@@ -814,6 +819,14 @@ class RobustProxyHandler(http.server.SimpleHTTPRequestHandler):
|
|||||||
self.send_cors_headers()
|
self.send_cors_headers()
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(img_bytes)
|
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 ====================
|
# ==================== Stash Server API Handlers ====================
|
||||||
def handle_stash_status(self):
|
def handle_stash_status(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user