Initial commit of Plex metadata agent to pull Stash data (#15)

Full bundle is included, put into "3rd party' directory to segment from Stash based scripts
This commit is contained in:
Darklyter
2021-09-27 19:59:41 -04:00
committed by GitHub
parent fd44b90da1
commit 52cc6cbfc2
4 changed files with 288 additions and 0 deletions

View File

@@ -0,0 +1,192 @@
import os
import re
import time
import string
import thread
import threading
import copy
import json
import dateutil.parser as dateparser
from urllib2 import HTTPError
from urllib2 import quote
from datetime import datetime
from lxml import etree
# preferences
preference = Prefs
DEBUG = preference['debug']
if DEBUG:
Log('Agent debug logging is enabled!')
else:
Log('Agent debug logging is disabled!')
def ValidatePrefs():
pass
def Start():
Log("Stash metadata agent started")
HTTP.Headers['Accept'] = 'application/json'
HTTP.CacheTime = 0.1
ValidatePrefs()
def HttpReq(url, authenticate=True, retry=True):
Log("Requesting: %s" % url)
api_string = ''
if Prefs['APIKey']:
api_string = '&apikey=%s' % Prefs['APIKey']
if Prefs['UseHTTPS']:
connectstring = 'https://%s:%s/graphql?query=%s%s'
else:
connectstring = 'http://%s:%s/graphql?query=%s%s'
try:
connecttoken = connectstring % (Prefs['Hostname'], Prefs['Port'], url, api_string)
Log(connecttoken)
return JSON.ObjectFromString(
HTTP.Request(connecttoken).content)
except Exception, e:
if not retry:
raise e
return HttpReq(url, authenticate, False)
class StashPlexAgent(Agent.Movies):
name = 'Stash Plex Agent'
languages = [Locale.Language.English]
primary_provider = True
accepts_from = [
'com.plexapp.agents.xbmcnfo'
]
def search(self, results, media, lang):
DEBUG = Prefs['debug']
file_query = r"""query{findScenes(scene_filter:{path:{value:"\"<FILENAME>\"",modifier:INCLUDES}}){scenes{id,title,date,studio{id,name}}}}"""
mediaFile = media.items[0].parts[0].file
filename = String.Unquote(mediaFile).encode('utf8', 'ignore')
filename = os.path.splitext(os.path.basename(filename))[0]
if filename:
filename = str(quote(filename.encode('UTF-8')))
query = file_query.replace("<FILENAME>", filename)
request = HttpReq(query)
if DEBUG:
Log(request)
movie_data = request['data']['findScenes']['scenes']
score = 100 if len(movie_data) == 1 else 85
for scene in movie_data:
if scene['date']:
title = scene['title'] + ' - ' + scene['date']
else:
title = scene['title']
Log("Title Found: " + title + " Score: " + str(score) + " ID:" + scene['id'])
results.Append(MetadataSearchResult(id = str(scene['id']), name = title, score = int(score), lang = lang))
def update(self, metadata, media, lang, force=False):
DEBUG = Prefs['debug']
Log("update(%s)" % metadata.id)
mid = metadata.id
id_query = "query{findScene(id:%s){path,id,title,details,url,date,rating,paths{screenshot,stream}studio{id,name,image_path,parent_studio{id,name,details}}tags{id,name}performers{name,image_path}movies{movie{name}}}}"
data = HttpReq(id_query % mid)
data = data['data']['findScene']
metadata.collections.clear()
if data['date']:
try:
Log("Trying to parse:" + data["date"])
date=dateparser().parse(data["date"])
except Exception as ex:
Log(ex)
date=None
pass
# Set the date and year if found.
if date is not None:
metadata.originally_available_at = date
metadata.year = date.year
# Get the title
if data['title']:
metadata.title = data["title"]
# Get the Studio
if not data["studio"] is None:
metadata.studio = data["studio"]["name"]
# Get the rating
if not data["rating"] is None:
metadata.rating = float(data["rating"]) * 2
if Prefs["CreateRatingTags"]:
if int(data["rating"]) > 0:
rating = str(int(data["rating"]))
ratingstring = "Rating: " + rating + " Stars"
try:
metadata.collections.add(ratingstring)
except:
pass
# Set the summary
if data['details']:
summary=data["details"].replace("\n"," ").replace("\r", "").replace("\t","")
metadata.summary = summary
# Set series and add to collections
if Prefs["CreateCollectionTags"]:
if not data["studio"] is None:
site="Site: " + data["studio"]["name"]
try:
metadata.collections.add(site)
except:
pass
if not data["studio"]["parent_studio"] is None:
site="Studio: " + data["studio"]["parent_studio"]["name"]
else:
site="Studio: " + data["studio"]["name"]
try:
metadata.collections.add(site)
except:
pass
# Add the genres
metadata.genres.clear()
if Prefs["IgnoreTags"]:
ignore_tags = Prefs["IgnoreTags"].split(",")
ignore_tags = list(map(lambda x: x.strip(), ignore_tags))
try:
if data["tags"]:
genres = data["tags"]
for genre in genres:
if not genre["id"] in ignore_tags and "ambiguous" not in genre["name"].lower():
metadata.genres.add(genre["name"])
except:
pass
# Add the performers
metadata.roles.clear()
# Create and populate role with actor's name
try:
if data["performers"]:
api_string = ""
if Prefs['APIKey']:
api_string = '&apikey=%s' % Prefs['APIKey']
models=data["performers"]
for model in models:
if DEBUG:
Log("Pulling Model: " + model["name"] + " With Image: " + model["image_path"])
role = metadata.roles.new()
role.name=model["name"]
role.photo=model["image_path"] + api_string
except:
pass
# Add posters and fan art.
if not data["paths"]["screenshot"] is None:
api_string = ""
if Prefs['APIKey']:
api_string = '&apikey=%s' % Prefs['APIKey']
try:
thumb = HTTP.Request(data["paths"]["screenshot"] + api_string)
metadata.posters[data["paths"]["screenshot"] + api_string] = Proxy.Preview(thumb)
metadata.art[data["paths"]["screenshot"] + api_string] = Proxy.Preview(thumb)
except:
pass

View File

@@ -0,0 +1,50 @@
[
{
"id": "Hostname",
"label": "The host for Stash",
"type": "text",
"default": "127.0.0.1"
},
{
"id": "Port",
"label": "The port for Stash",
"type": "text",
"default": "9999"
},
{
"id": "UseHTTPS",
"label": "Use HTTPS instead of HTTP to connect",
"type": "bool",
"default": false
},
{
"id": "APIKey",
"label": "The API Key for Stash if Authentication is enabled",
"type": "text",
"default": ""
},
{
"id": "IgnoreTags",
"label": "Stash Tag ID numbers to ignore (comma separated, 0 to disable)",
"type": "text",
"default": "1,2"
},
{
"id": "CreateCollectionTags",
"label": "Auto create Plex Collection tags for Site and Studio",
"type": "bool",
"default": true
},
{
"id": "CreateRatingTags",
"label": "Auto create Plex Collection tags for Stash star rating",
"type": "bool",
"default": false
},
{
"id": "debug",
"label": "Use debug logging",
"type": "bool",
"default": false
},
]

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>StashPlexAgent</string>
<key>CFBundleIdentifier</key>
<string>com.plexapp.agents.stashplexagent</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>PlexFrameworkVersion</key>
<string>2</string>
<key>PlexPluginClass</key>
<string>Agent</string>
<key>PlexPluginMode</key>
<string>AlwaysOn</string>
<key>PlexPluginCodePolicy</key>
<string>Elevated</string>
</dict>
</plist>

View File

@@ -0,0 +1,18 @@
# StashPlexAgent.bundle
A very simplistic Plex agent to pull metadata from Stash.
Scenes are matched based on filename (without path or extension) against the Stash "Path", so files must be scanned into Stash with their current filename.
Preferences are set under the plugin, or in the library definition (if you set it as the primary agent for the library). I'm using "Video Files Scanner" with it.
By default it will create Plex "Site: <STUDIO>" and "Studio: <STUDIO PARENT>" collection tags, but this can be disabled in preferences. (If the studio doesn't have a parent then the primary studio will be used instead and be in both tags)
Also Stash "Tags" are placed into Plex "Genres"
You can also set tag numbers to ignore on import, I've left mine in as an example. You probably want to change these unless your "temporary" tags miraculously line up with mine. (Also initially you might need to try saving a couple of times. Plex seems to not want to initally keep changes in this field for some reason)
For installing just download the bundle and put it into your "\PlexMediaServer\Plex Media Server\Plug-ins" folder. (The entire bundle as a directory... "\StashPlexAgent.bundle")
I guarantee there will be problems. When they pop up feel free to get with me (@Darklyter) on either the TPDB or Stash Discord channels.
Also this agent only handles scenes currently. I haven't played with movies in Stash yet, but can take a look if there is interest. Currently the Plex ADE agent handles that for me.