feat: Add 1-Click Batch Merge All for Performer and Tag Duplicates
This commit is contained in:
@@ -884,8 +884,12 @@ class RobustProxyHandler(http.server.SimpleHTTPRequestHandler):
|
||||
self.handle_stash_batch_commit_images()
|
||||
elif self.path == '/api/stash/performers/merge':
|
||||
self.handle_stash_performer_merge()
|
||||
elif self.path == '/api/stash/performers/batch-merge':
|
||||
self.handle_stash_performer_batch_merge()
|
||||
elif self.path == '/api/stash/tags/merge':
|
||||
self.handle_stash_tag_merge()
|
||||
elif self.path == '/api/stash/tags/batch-merge':
|
||||
self.handle_stash_tag_batch_merge()
|
||||
elif self.path == '/api/stash/transcodes/replace':
|
||||
self.handle_stash_transcode_replace()
|
||||
elif self.path == '/api/stash/transcodes/batch-replace':
|
||||
@@ -2435,6 +2439,51 @@ class RobustProxyHandler(http.server.SimpleHTTPRequestHandler):
|
||||
except Exception as e:
|
||||
self.send_json_response(500, {"error": str(e)})
|
||||
|
||||
def handle_stash_performer_batch_merge(self):
|
||||
content_length = int(self.headers.get('Content-Length', 0))
|
||||
post_data = self.rfile.read(content_length)
|
||||
try:
|
||||
payload = json.loads(post_data.decode('utf-8'))
|
||||
stash_url = payload.get('stash_url') or DEFAULT_STASH_URL
|
||||
clusters = payload.get('clusters', [])
|
||||
|
||||
if not clusters:
|
||||
self.send_json_response(400, {"error": "No clusters provided for batch merge"})
|
||||
return
|
||||
|
||||
merged_count = 0
|
||||
errors = []
|
||||
mutation = '''
|
||||
mutation PerformerMerge($input: PerformerMergeInput!) {
|
||||
performerMerge(input: $input) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
'''
|
||||
for c in clusters:
|
||||
source_ids = [str(sid) for sid in c.get('source_ids', [])]
|
||||
dest_id = str(c.get('destination_id'))
|
||||
if not source_ids or not dest_id:
|
||||
continue
|
||||
try:
|
||||
res = execute_stash_graphql(mutation, stash_url, variables={"input": {"source": source_ids, "destination": dest_id}}, timeout=20)
|
||||
if res.get('data', {}).get('performerMerge'):
|
||||
merged_count += 1
|
||||
elif res.get('errors'):
|
||||
errors.append({"destination_id": dest_id, "error": str(res.get('errors'))})
|
||||
except Exception as ex:
|
||||
errors.append({"destination_id": dest_id, "error": str(ex)})
|
||||
|
||||
self.send_json_response(200, {
|
||||
"success": True,
|
||||
"merged_count": merged_count,
|
||||
"total_requested": len(clusters),
|
||||
"errors": errors
|
||||
})
|
||||
except Exception as e:
|
||||
self.send_json_response(500, {"error": str(e)})
|
||||
|
||||
# ==================== Missing Metadata Radar Handlers ====================
|
||||
def handle_stash_missing_metadata(self):
|
||||
parsed = urllib.parse.urlparse(self.path)
|
||||
@@ -2618,6 +2667,51 @@ class RobustProxyHandler(http.server.SimpleHTTPRequestHandler):
|
||||
except Exception as e:
|
||||
self.send_json_response(500, {"error": str(e)})
|
||||
|
||||
def handle_stash_tag_batch_merge(self):
|
||||
content_length = int(self.headers.get('Content-Length', 0))
|
||||
post_data = self.rfile.read(content_length)
|
||||
try:
|
||||
payload = json.loads(post_data.decode('utf-8'))
|
||||
stash_url = payload.get('stash_url') or DEFAULT_STASH_URL
|
||||
clusters = payload.get('clusters', [])
|
||||
|
||||
if not clusters:
|
||||
self.send_json_response(400, {"error": "No clusters provided for batch merge"})
|
||||
return
|
||||
|
||||
merged_count = 0
|
||||
errors = []
|
||||
mutation = '''
|
||||
mutation TagsMerge($input: TagsMergeInput!) {
|
||||
tagsMerge(input: $input) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
'''
|
||||
for c in clusters:
|
||||
source_ids = [str(sid) for sid in c.get('source_ids', [])]
|
||||
dest_id = str(c.get('destination_id'))
|
||||
if not source_ids or not dest_id:
|
||||
continue
|
||||
try:
|
||||
res = execute_stash_graphql(mutation, stash_url, variables={"input": {"source": source_ids, "destination": dest_id}}, timeout=20)
|
||||
if res.get('data', {}).get('tagsMerge'):
|
||||
merged_count += 1
|
||||
elif res.get('errors'):
|
||||
errors.append({"destination_id": dest_id, "error": str(res.get('errors'))})
|
||||
except Exception as ex:
|
||||
errors.append({"destination_id": dest_id, "error": str(ex)})
|
||||
|
||||
self.send_json_response(200, {
|
||||
"success": True,
|
||||
"merged_count": merged_count,
|
||||
"total_requested": len(clusters),
|
||||
"errors": errors
|
||||
})
|
||||
except Exception as e:
|
||||
self.send_json_response(500, {"error": str(e)})
|
||||
|
||||
# ==================== Stash Transcode Correlator & Storage Saver Handlers ====================
|
||||
def handle_stash_transcode_scan(self):
|
||||
parsed = urllib.parse.urlparse(self.path)
|
||||
|
||||
Reference in New Issue
Block a user