Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[markerTagToScene] Add all tags of Scene Marker to the Scene #152

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions plugins/markerTagToScene/log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import sys


# Log messages sent from a plugin instance are transmitted via stderr and are
# encoded with a prefix consisting of special character SOH, then the log
# level (one of t, d, i, w, e, or p - corresponding to trace, debug, info,
# warning, error and progress levels respectively), then special character
# STX.
#
# The LogTrace, LogDebug, LogInfo, LogWarning, and LogError methods, and their equivalent
# formatted methods are intended for use by plugin instances to transmit log
# messages. The LogProgress method is also intended for sending progress data.
#

def __prefix(level_char):
start_level_char = b'\x01'
end_level_char = b'\x02'

ret = start_level_char + level_char + end_level_char
return ret.decode()


def __log(level_char, s):
if level_char == "":
return

print(__prefix(level_char) + s + "\n", file=sys.stderr, flush=True)


def LogTrace(s):
__log(b't', s)


def LogDebug(s):
__log(b'd', s)


def LogInfo(s):
__log(b'i', s)


def LogWarning(s):
__log(b'w', s)


def LogError(s):
__log(b'e', s)


def LogProgress(p):
progress = min(max(0, p), 1)
__log(b'p', str(progress))
81 changes: 0 additions & 81 deletions plugins/markerTagToScene/markerTagToScene.js

This file was deleted.

141 changes: 141 additions & 0 deletions plugins/markerTagToScene/markerTagToScene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import json
import sys
import time
import requests
import log

ALL_TAGS = False

START_TIME = time.time()
FRAGMENT = json.loads(sys.stdin.read())

FRAGMENT_SERVER = FRAGMENT["server_connection"]
PLUGIN_DIR = FRAGMENT_SERVER["PluginDir"]

def callGraphQL(query, variables=None):
# Session cookie for authentication
graphql_port = str(FRAGMENT_SERVER['Port'])
graphql_scheme = FRAGMENT_SERVER['Scheme']
graphql_cookies = {'session': FRAGMENT_SERVER['SessionCookie']['Value']}
graphql_headers = {
"Accept-Encoding": "gzip, deflate, br",
"Content-Type": "application/json",
"Accept": "application/json",
"Connection": "keep-alive",
"DNT": "1"
}
graphql_domain = FRAGMENT_SERVER['Host']
if graphql_domain == "0.0.0.0":
graphql_domain = "localhost"
# Stash GraphQL endpoint
graphql_url = f"{graphql_scheme}://{graphql_domain}:{graphql_port}/graphql"

json = {'query': query}
if variables is not None:
json['variables'] = variables
try:
response = requests.post(graphql_url, json=json, headers=graphql_headers, cookies=graphql_cookies, timeout=20)
except Exception as e:
exit_plugin(err=f"[FATAL] Error with the graphql request {e}")
if response.status_code == 200:
result = response.json()
if result.get("error"):
for error in result["error"]["errors"]:
raise Exception(f"GraphQL error: {error}")
return None
if result.get("data"):
return result.get("data")
elif response.status_code == 401:
exit_plugin(err="HTTP Error 401, Unauthorised.")
else:
raise ConnectionError(f"GraphQL query failed: {response.status_code} - {response.content}")



def exit_plugin(msg=None, err=None):
if msg is None and err is None:
msg = "plugin ended"
log.LogDebug("Execution time: {}s".format(round(time.time() - START_TIME, 5)))
output_json = {"output": msg, "error": err}
print(json.dumps(output_json))
sys.exit()



def graphql_getSceneTags(sceneID):
query = """
query FindScene($id:ID!) {
findScene(id: $id) {
tags {
id
}
}
}
"""
variables = {
"id": sceneID
}
result = callGraphQL(query, variables)
findScene = result.get('findScene')
if findScene.get('tags') is not None:
return findScene.get('tags')

return []



def graphql_setSceneTags(sceneID, tagIDs: list):
query = """
mutation SceneUpdate($input: SceneUpdateInput!) {
sceneUpdate(input: $input) {
id
}
}
"""
variables = {
"input": {
"id": sceneID,
"tag_ids": tagIDs
}
}
result = callGraphQL(query, variables)
return result



def main():

CONTEXT = FRAGMENT['args']['hookContext']['input']
sceneID = CONTEXT['scene_id']
if not sceneID:
return

prevSceneTags = graphql_getSceneTags(sceneID)
prevSceneTagIDs = []
for prevSceneTag in prevSceneTags:
prevSceneTagIDs.append(prevSceneTag['id'])

nextTagIDs = []

# Primary tag
primaryTagID = CONTEXT['primary_tag_id']
if primaryTagID is not None:
nextTagIDs = set(prevSceneTagIDs + [primaryTagID])

# All tags
if ALL_TAGS:
tagIDs = CONTEXT['tag_ids']
if tagIDs is not None:
nextTagIDs = set(set(nextTagIDs) | set(prevSceneTagIDs) | set(tagIDs))

if len(prevSceneTagIDs) >= len(nextTagIDs):
log.LogDebug("No new tag added")
return

graphql_setSceneTags(sceneID, list(nextTagIDs))
log.LogDebug("Added new tags to scene " + sceneID)



if __name__ == '__main__':
main()
12 changes: 6 additions & 6 deletions plugins/markerTagToScene/markerTagToScene.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# example plugin config
name: Scene Marker Tags to Scene
description: Adds primary tag of Scene Marker to the Scene on marker create/update.
description: Adds primary tag and opt-in all tags of Scene Marker to the Scene on marker create/update.
url: https://github.com/stashapp/CommunityScripts
version: 1.0
version: 2.1.0
exec:
- markerTagToScene.js
interface: js
- python
- "{pluginDir}/markerTagToScene.py"
interface: raw
hooks:
- name: Update scene with scene marker tag
description: Adds primary tag of Scene Marker to the Scene on marker create/update.
description: Adds primary tag and opt-in all tags of Scene Marker to the Scene on marker create/update.
triggeredBy:
- SceneMarker.Create.Post
- SceneMarker.Update.Post