Skip to content

Commit 294bb17

Browse files
authored
Tag galleries from images (#622)
1 parent 322536c commit 294bb17

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
stashapp-tools
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import stashapi.log as log
2+
from stashapi.stashapp import StashInterface
3+
import sys
4+
import json
5+
6+
def processAll():
7+
exclusion_marker_tag_id = None
8+
if settings["excludeWithTag"] != "":
9+
exclussion_marker_tag = stash.find_tag(settings["excludeWithTag"])
10+
if exclussion_marker_tag is not None:
11+
exclusion_marker_tag_id = exclussion_marker_tag['id']
12+
13+
query = {
14+
"image_count": {
15+
"modifier": "NOT_EQUALS",
16+
"value": 0,
17+
},
18+
}
19+
if settings['excludeOrganized']:
20+
query["organized"] = False
21+
if exclusion_marker_tag_id is not None:
22+
query["tags"] = {
23+
"value": [exclusion_marker_tag_id],
24+
"modifier": "EXCLUDES"
25+
}
26+
27+
total_count = stash.find_galleries(f=query, filter={"page": 0, "per_page": 0}, get_count=True)[0]
28+
i = 0
29+
while i < total_count:
30+
log.progress((i / total_count))
31+
32+
galleries = stash.find_galleries(f=query, filter={"page": i, "per_page": 1})
33+
if len(galleries) == 0:
34+
break
35+
gallery = galleries[0]
36+
37+
processGallery(gallery)
38+
39+
i = i + 1
40+
41+
42+
def processGallery(gallery : dict):
43+
tags = []
44+
performersIds = []
45+
should_tag = True
46+
if settings["excludeWithTag"] != "":
47+
for tag in gallery["tags"]:
48+
if tag["name"] == settings["excludeWithTag"]:
49+
should_tag = False
50+
break
51+
52+
if settings['excludeOrganized']:
53+
if gallery['organized']:
54+
should_tag = False
55+
56+
if should_tag:
57+
existing_tag_ids = {t['id'] for t in gallery['tags']}
58+
existing_performer_ids = {p['id'] for p in gallery['performers']}
59+
60+
images = stash.find_gallery_images(gallery['id'], fragment='tags { id name } performers { id name }')
61+
if len(images) > 0:
62+
tag_ids = set()
63+
tag_names = set()
64+
65+
performer_ids = set()
66+
performer_names = set()
67+
68+
for image in images:
69+
image_tag_ids = [tag['id'] for tag in image['tags']]
70+
image_tag_names = [tag['name'] for tag in image['tags']]
71+
tag_ids.update(image_tag_ids)
72+
tag_names.update(image_tag_names)
73+
74+
image_performer_ids = [performer['id'] for performer in image['performers']]
75+
image_performer_names = [performer['name'] for performer in image['performers']]
76+
performer_ids.update(image_performer_ids)
77+
performer_names.update(image_performer_names)
78+
79+
new_tags_ids = tag_ids - existing_tag_ids
80+
new_performer_ids = performer_ids - existing_performer_ids
81+
82+
if len(new_tags_ids) > 0 or len(new_performer_ids) > 0:
83+
log.info(f"updating gallery {gallery['id']} from {len(images)} images with tags {tag_names} ({len(new_tags_ids)} new) and performers {performer_names} ({len(new_performer_ids)} new)")
84+
stash.update_galleries({"ids": gallery['id'], "tag_ids": {"mode": "ADD", "ids": list(new_tags_ids)}, "performer_ids": {"mode": "ADD", "ids": list(new_performer_ids)}})
85+
86+
87+
json_input = json.loads(sys.stdin.read())
88+
FRAGMENT_SERVER = json_input["server_connection"]
89+
stash = StashInterface(FRAGMENT_SERVER)
90+
config = stash.get_configuration()
91+
settings = {
92+
"excludeWithTag": "",
93+
"excludeOrganized": False
94+
}
95+
if "tagGalleriesFromImages" in config["plugins"]:
96+
settings.update(config["plugins"]["tagGalleriesFromImages"])
97+
98+
if "mode" in json_input["args"]:
99+
PLUGIN_ARGS = json_input["args"]["mode"]
100+
if "processAll" in PLUGIN_ARGS:
101+
processAll()
102+
elif "hookContext" in json_input["args"]:
103+
id = json_input["args"]["hookContext"]['id']
104+
if (
105+
(
106+
json_input["args"]["hookContext"]["type"] == "Gallery.Update.Post"
107+
or json_input["args"]["hookContext"]["type"] == "Gallery.Create.Post"
108+
) and "inputFields" in json_input["args"]["hookContext"]
109+
and len(json_input["args"]["hookContext"]["inputFields"]) > 2
110+
):
111+
gallery = stash.find_gallery(id)
112+
processGallery(gallery)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Tag galleries from images
2+
description: tags galleries with tags of contained images.
3+
version: 0.1
4+
exec:
5+
- python
6+
- "{pluginDir}/tagGalleriesFromImages.py"
7+
interface: raw
8+
9+
hooks:
10+
- name: update gallery
11+
description: Will tag galleries with tags of contained images
12+
triggeredBy:
13+
- Gallery.Update.Post
14+
- Gallery.Create.Post
15+
16+
settings:
17+
excludeOrganized:
18+
displayName: Exclude galleries marked as organized
19+
description: Do not automatically tag galleries if it is marked as organized
20+
type: BOOLEAN
21+
excludeWithTag:
22+
displayName: Exclude galleries with tag from Hook
23+
description: Do not automatically tag galleries if the gallery has this tag
24+
type: STRING
25+
26+
tasks:
27+
- name: "Tag all galleries"
28+
description: Loops through all galleries, and applies the tags of the contained images. Can take a long time on large db's.
29+
defaultArgs:
30+
mode: processAll

0 commit comments

Comments
 (0)