-
-
Notifications
You must be signed in to change notification settings - Fork 151
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding a new plugin to automatically download performer images from s…
…tashdb or any other stashbox. Add the tag [Stashbox Performer Gallery] to a performer to start the backgroud job. The images will be downloaded and added to a gallery for the database. You can then go into the gallery and add the tag [Set Profile Image] to an image with exactly 1 performer to set that image as the profile image.
- Loading branch information
Tweeticoats
authored and
Tweeticoats
committed
Jan 22, 2024
1 parent
dd46fa2
commit 5ab546e
Showing
3 changed files
with
267 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
requests | ||
stashapp-tools |
227 changes: 227 additions & 0 deletions
227
plugins/stashdb-performer-gallery/stashdb-performer-gallery.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
import stashapi.log as log | ||
from stashapi.stashapp import StashInterface | ||
from stashapi.stashbox import StashBoxInterface | ||
import os | ||
import sys | ||
import requests | ||
import json | ||
import time | ||
import math | ||
import requests | ||
from pathlib import Path | ||
import base64 | ||
|
||
|
||
per_page = 100 | ||
request_s = requests.Session() | ||
stash_boxes={} | ||
|
||
|
||
|
||
def processImages(img): | ||
log.debug('image: %s' % ( img, )) | ||
for file in [x['path'] for x in img['visual_files']]: | ||
if settings['path'] in file: | ||
index_file=Path(Path(file).parent) / (Path(file).stem +'.json') | ||
log.debug(index_file) | ||
if index_file.exists(): | ||
log.debug('loading index file %s' % (index_file,)) | ||
with open(index_file) as f: | ||
index = json.load(f) | ||
|
||
index['id']=img['id'] | ||
|
||
stash.update_image(index) | ||
|
||
|
||
|
||
def processPerformers(): | ||
performers=stash.find_performers(f={"tags": {"depth": 0, "excludes": [], "modifier": "INCLUDES_ALL", "value": [ tag_stashbox_performer_gallery ]}}) | ||
for performer in performers: | ||
processPerformer(performer) | ||
|
||
def processPerformer( performer): | ||
dir=Path(settings['path']) / performer['id'] | ||
dir.mkdir(parents=True, exist_ok=True) | ||
for sid in performer['stash_ids']: | ||
log.debug(sid) | ||
processPerformerStashid(sid['endpoint'],sid['stash_id'],performer) | ||
def get_stashbox(endpoint): | ||
# if endpoint in stash_boxes: | ||
# return stash_boxes[endpoint] | ||
for sbx_config in stash.get_configuration()['general']['stashBoxes']: | ||
if sbx_config['endpoint']==endpoint: | ||
stashbox = StashBoxInterface({'endpoint': sbx_config['endpoint'], 'api_key': sbx_config['api_key']}) | ||
stash_boxes[endpoint] = stashbox | ||
return stashbox | ||
|
||
def processPerformerStashid(endpoint,stashid,p): | ||
log.info('processing performer %s, %s endpoint: %s, stash id: %s' % (p['name'],p['id'],endpoint,stashid,)) | ||
|
||
index_file=os.path.join(settings['path'], p['id'],'index.json') | ||
if os.path.exists(index_file): | ||
with open(os.path.join(settings['path'], p['id'],'index.json')) as f: | ||
index= json.load(f) | ||
else: | ||
index={'files': {},'galleries':{},'performer_id':p['id']} | ||
|
||
modified=False | ||
stashbox=get_stashbox(endpoint) | ||
if stashbox: | ||
query="""id | ||
name | ||
images { | ||
id | ||
url | ||
} | ||
""" | ||
perf=stashbox.find_performer(stashid,fragment=query) | ||
log.debug(perf) | ||
if endpoint not in index['galleries']: | ||
gallery_input={ | ||
'title': '%s - %s ' % (p['name'], endpoint[8:-8],), | ||
'urls':['%s/performers/%s' % (endpoint[:-8],stashid,)], | ||
'tag_ids':[tag_stashbox_performer_gallery], | ||
'performer_ids':[p['id']] | ||
} | ||
gal=stash.create_gallery(gallery_input) | ||
log.info('Created gallery %s' % (gal,)) | ||
index['galleries'][endpoint]=gal | ||
|
||
modified=True | ||
#check if the gallery still exists and has not been deleted | ||
current_gal=stash.find_gallery(index['galleries'][endpoint]) | ||
log.debug('current: %s' % (current_gal,)) | ||
if current_gal is None: | ||
log.debug('deleted?') | ||
gallery_input={ | ||
'title': '%s - %s ' % (p['name'], endpoint[:-8],), | ||
'urls':['%s/performers/%s' % (endpoint[:-8],stashid,)], | ||
'tag_ids':[tag_stashbox_performer_gallery], | ||
'performer_ids':[p['id']] | ||
} | ||
|
||
|
||
gal=stash.create_gallery(gallery_input) | ||
log.info('Created gallery %s' % (gal,)) | ||
index['galleries'][endpoint]=gal | ||
modified=True | ||
if modified: | ||
with open(index_file, 'w') as f: | ||
json.dump(index, f) | ||
|
||
for img in perf['images']: | ||
image_index=Path(settings['path'])/ p['id'] /(img['id']+'.json') | ||
if not image_index.exists(): | ||
with open(image_index, 'w') as f: | ||
image_data={ | ||
'title':img['id'], | ||
'urls':[img['url']], | ||
'performer_ids':[p['id']], | ||
'tag_ids':[tag_stashbox_performer_gallery], | ||
'gallery_ids':[index['galleries'][endpoint]], | ||
} | ||
json.dump(image_data, f) | ||
filename = Path(settings['path']) / p['id'] / (img['id'] + '.jpg') | ||
if not os.path.exists(filename): | ||
log.info('Downloading image %s to %s' % (img['url'], filename,)) | ||
r = requests.get(img['url']) | ||
with open(filename, "xb") as f: | ||
f.write(r.content) | ||
f.close() | ||
# modified=True | ||
else: | ||
log.debug('image already downloaded') | ||
|
||
else: | ||
log.error('endpoint %s not configured, skipping' % (endpoint,)) | ||
|
||
|
||
def setPerformerPicture(img): | ||
if len(img['performers'])==1: | ||
log.debug(img['paths']['image']) | ||
res=request_s.get(img['paths']['image']) | ||
log.debug(res.headers['Content-Type']) | ||
if res.status_code==200: | ||
encoded = base64.b64encode(res.content).decode() | ||
new_performer ={ | ||
'id':img['performers'][0]['id'], | ||
'image':'data:{0};base64,{1}'.format(res.headers['Content-Type'], encoded) | ||
} | ||
log.info('updating performer with tagged image %s' % (new_performer['id'],)) | ||
stash.update_performer(new_performer) | ||
|
||
|
||
def processQueue(): | ||
for id in settings['queue'].split(','): | ||
if len(id) > 0: | ||
p=stash.find_performer(id) | ||
processPerformer(p) | ||
#queue has not changed since we started, clear setting | ||
if stash.get_configuration()['plugins']['stashdb-performer-gallery']==settings['queue']: | ||
stash.configure_plugin('stashdb-performer-gallery',{'queue':''}) | ||
stash.metadata_scan(paths=[settings['path']]) | ||
stash.run_plugin_task('stashdb-performer-gallery','relink missing images') | ||
else: | ||
# update remove the completed entries from the queue string leaving the unprocessed and schedule the task again | ||
log.debug('updating queue') | ||
stash.configure_plugin('stashdb-performer-gallery',{'queue':stash.get_configuration()['plugins']['stashdb-performer-gallery']['queue'].removeprefix(settings['queue'])}) | ||
stash.run_plugin_task('stashdb-performer-gallery','Process Performers') | ||
|
||
def relink_images(): | ||
images=stash.find_images(f= {"path": {"modifier": "INCLUDES","value": settings['path']},"performer_count": {"modifier": "EQUALS","value": 0}}) | ||
log.debug(images) | ||
for img in images: | ||
processImages(img) | ||
|
||
json_input = json.loads(sys.stdin.read()) | ||
|
||
FRAGMENT_SERVER = json_input["server_connection"] | ||
stash = StashInterface(FRAGMENT_SERVER) | ||
|
||
config=stash.get_configuration()['plugins'] | ||
settings={ | ||
'path':'/download_dir', | ||
} | ||
if 'stashdb-performer-gallery' in config: | ||
settings.update(config['stashdb-performer-gallery']) | ||
#log.info('config: %s ' % (settings,)) | ||
|
||
|
||
tag_stashbox_performer_gallery = stash.find_tag('[Stashbox Performer Gallery]', create=True).get("id") | ||
tag_performer_image = stash.find_tag('[Set Profile Image]', create=True).get("id") | ||
|
||
if 'stasdb-performer-gallery' in config: | ||
settings.update(config['stasdb-performer-gallery']) | ||
|
||
|
||
|
||
if 'mode' in json_input['args']: | ||
PLUGIN_ARGS = json_input['args']["mode"] | ||
if 'performer' in json_input['args']: | ||
p=stash.find_performer(json_input['args']['performer']) | ||
if tag_stashbox_performer_gallery in [x['id'] for x in p['tags']]: | ||
processPerformer(p) | ||
stash.metadata_scan(paths=[settings['path']]) | ||
stash.run_plugin_task('stashdb-performer-gallery','relink missing images',args={}) | ||
elif 'processPerformers' in PLUGIN_ARGS: | ||
processPerformers() | ||
stash.metadata_scan([settings['path']]) | ||
stash.run_plugin_task('stashdb-performer-gallery','relink missing images',args={}) | ||
elif 'processImages' in PLUGIN_ARGS: | ||
relink_images() | ||
|
||
|
||
elif 'hookContext' in json_input['args']: | ||
id=json_input['args']['hookContext']['id'] | ||
if json_input['args']['hookContext']['type']=='Image.Create.Post': | ||
img=stash.find_image(image_in=id) | ||
processImages(img) | ||
if json_input['args']['hookContext']['type']=='Image.Update.Post': | ||
img=stash.find_image(image_in=id) | ||
if tag_performer_image in [x['id'] for x in img['tags']]: | ||
setPerformerPicture(img) | ||
if json_input['args']['hookContext']['type']=='Performer.Update.Post': | ||
stash.run_plugin_task('stashdb-performer-gallery','Process Performers',args={'performer':id}) | ||
|
||
|
38 changes: 38 additions & 0 deletions
38
plugins/stashdb-performer-gallery/stashdb-performer-gallery.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
name: stashdb performer gallery | ||
description: Automatically download performer images from stashdb or other stash-boxes. Add the [Stashbox Performer Gallery] tag to a performer and it will create a gallery of images from that stash-box database. Apply the tag [Set Profile Image] to an image to set it as the profile image of that performer. Note you will need to configure the download path and add this as a path under settings > library | ||
version: 0.1 | ||
url: https://github.com/stashapp/CommunityScripts/ | ||
exec: | ||
- python | ||
- "{pluginDir}/stashdb-performer-gallery.py" | ||
interface: raw | ||
settings: | ||
path: | ||
displayName: Download parent folder | ||
description: Download location for files, note this should be in a different folder to stash and in a folder covered by stash. You may need to create a new library path to cover this directory. | ||
type: STRING | ||
|
||
hooks: | ||
- name: modify performer | ||
description: Download galleries on performer update if the [performer gallery] tag is applied | ||
triggeredBy: | ||
- Performer.Update.Post | ||
- name: image add | ||
description: Add images | ||
triggeredBy: | ||
- Image.Create.Post | ||
- name: set profile images | ||
description: Set profile images py adding the [Set Profile Image] tag to the image, there must be exactly 1 performer tagged on the image. | ||
triggeredBy: | ||
- Image.Update.Post | ||
|
||
|
||
tasks: | ||
- name: 'Process Performers' | ||
description: Fetch performer images for performers with the [performer gallery] tag | ||
defaultArgs: | ||
mode: processPerformers | ||
- name: 'relink missing images' | ||
description: reprocess missing images | ||
defaultArgs: | ||
mode: processImages |