-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
441 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
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,39 @@ | ||
import sys | ||
import re | ||
# Log messages sent from a script scraper 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 or e - corresponding to trace, debug, info, | ||
# warning and error levels respectively), then special character | ||
# STX. | ||
# | ||
# The log.trace, log.debug, log.info, log.warning, and log.error methods, and their equivalent | ||
# formatted methods are intended for use by script scraper instances to transmit log | ||
# messages. | ||
# | ||
|
||
def __log(level_char: bytes, s): | ||
if level_char: | ||
lvl_char = "\x01{}\x02".format(level_char.decode()) | ||
s = re.sub(r"data:image.+?;base64(.+?')","[...]",str(s)) | ||
for x in s.split("\n"): | ||
print(lvl_char, x, file=sys.stderr, flush=True) | ||
|
||
|
||
def trace(s): | ||
__log(b't', s) | ||
|
||
|
||
def debug(s): | ||
__log(b'd', s) | ||
|
||
|
||
def info(s): | ||
__log(b'i', s) | ||
|
||
|
||
def warning(s): | ||
__log(b'w', s) | ||
|
||
|
||
def error(s): | ||
__log(b'e', s) |
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==2.30.0 | ||
pystashlib==0.4.4 |
182 changes: 182 additions & 0 deletions
182
plugins/stashStashboxSceneCount/stashStashboxSceneCount.js
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,182 @@ | ||
(function() { | ||
'use strict'; | ||
|
||
const { | ||
stash, | ||
Stash, | ||
waitForElementId, | ||
waitForElementClass, | ||
waitForElementByXpath, | ||
getElementByXpath, | ||
getClosestAncestor, | ||
updateTextInput, | ||
} = window.stash7dJx1qP; | ||
|
||
async function runGetStashboxPerformerSceneCountTask(endpoint, api_key, stashId) { | ||
if (endpoint !== 'https://stashdb.org/graphql') return; | ||
return stash.runPluginTask("stashStashboxSceneCount", "Get Stashbox Performer Scene Count", [{"key":"endpoint", "value":{"str": endpoint}}, {"key":"api_key", "value":{"str": api_key}}, {"key":"stash_id", "value":{"str": stashId}}]); | ||
} | ||
|
||
async function runGetStashboxStudioSceneCountTask(endpoint, api_key, stashId) { | ||
if (endpoint !== 'https://stashdb.org/graphql') return; | ||
return stash.runPluginTask("stashStashboxSceneCount", "Get Stashbox Studio Scene Count", [{"key":"endpoint", "value":{"str": endpoint}}, {"key":"api_key", "value":{"str": api_key}}, {"key":"stash_id", "value":{"str": stashId}}]); | ||
} | ||
|
||
async function getPerformer() { | ||
const performerId = window.location.pathname.split('/').find((o, i, arr) => i > 1 && arr[i - 1] == 'performers'); | ||
const reqData = { | ||
"operationName": "FindPerformer", | ||
"variables": { | ||
"id": performerId | ||
}, | ||
"query": `query FindPerformer($id: ID!) { | ||
findPerformer(id: $id) { | ||
id | ||
stash_ids { | ||
endpoint | ||
stash_id | ||
} | ||
} | ||
}` | ||
}; | ||
const result = await stash.callGQL(reqData); | ||
return result?.data?.findPerformer; | ||
} | ||
|
||
async function getStudio() { | ||
const studioId = window.location.pathname.split('/').find((o, i, arr) => i > 1 && arr[i - 1] == 'studios'); | ||
const reqData = { | ||
"operationName": "FindStudio", | ||
"variables": { | ||
"id": studioId | ||
}, | ||
"query": `query FindStudio($id: ID!) { | ||
findStudio(id: $id) { | ||
id | ||
stash_ids { | ||
endpoint | ||
stash_id | ||
} | ||
} | ||
}` | ||
}; | ||
const result = await stash.callGQL(reqData); | ||
return result?.data?.findStudio; | ||
} | ||
|
||
async function getPerformerScenes(endpoint) { | ||
const performerId = window.location.pathname.split('/').find((o, i, arr) => i > 1 && arr[i - 1] == 'performers'); | ||
const reqData = { | ||
"operationName": "FindScenes", | ||
"variables": { | ||
"filter": { | ||
"q": "", | ||
"page": 1, | ||
"per_page": 20, | ||
"sort": "random_41127446", | ||
"direction": "DESC" | ||
}, | ||
"scene_filter": { | ||
"stash_id_endpoint": { | ||
"endpoint": endpoint, | ||
"stash_id": "", | ||
"modifier": "NOT_NULL" | ||
}, | ||
"performers": { | ||
"value": [performerId], | ||
"excludes": [], | ||
"modifier": "INCLUDES_ALL" | ||
} | ||
} | ||
}, | ||
"query": `query FindScenes($filter: FindFilterType, $scene_filter: SceneFilterType, $scene_ids: [Int!]) { | ||
findScenes(filter: $filter, scene_filter: $scene_filter, scene_ids: $scene_ids) { | ||
count | ||
} | ||
}` | ||
}; | ||
const result = await stash.callGQL(reqData); | ||
return result?.data?.findScenes.count; | ||
} | ||
|
||
async function getStudioScenes(endpoint, includeSubsidiaryStudios) { | ||
const studioId = window.location.pathname.split('/').find((o, i, arr) => i > 1 && arr[i - 1] == 'studios'); | ||
const reqData = { | ||
"operationName": "FindScenes", | ||
"variables": { | ||
"filter": { | ||
"q": "", | ||
"page": 1, | ||
"per_page": 20, | ||
"sort": "random_41127446", | ||
"direction": "DESC" | ||
}, | ||
"scene_filter": { | ||
"stash_id_endpoint": { | ||
"endpoint": endpoint, | ||
"stash_id": "", | ||
"modifier": "NOT_NULL" | ||
}, | ||
"studios": { | ||
"value": [studioId], | ||
"excludes": [], | ||
"modifier": "INCLUDES_ALL" | ||
} | ||
} | ||
}, | ||
"query": `query FindScenes($filter: FindFilterType, $scene_filter: SceneFilterType, $scene_ids: [Int!]) { | ||
findScenes(filter: $filter, scene_filter: $scene_filter, scene_ids: $scene_ids) { | ||
count | ||
} | ||
}` | ||
}; | ||
if (includeSubsidiaryStudios) { | ||
reqData.variables.scene_filter.studios.depth = -1; | ||
} | ||
const result = await stash.callGQL(reqData); | ||
return result?.data?.findScenes.count; | ||
} | ||
|
||
async function performerPageHandler() { | ||
const settings = await stash.getPluginConfig('stashStashboxSceneCount'); | ||
if (settings?.performers) { | ||
const performer = await getPerformer(); | ||
const data = await stash.getStashBoxes(); | ||
for (const { endpoint, stash_id } of performer.stash_ids) { | ||
const sceneCount = await getPerformerScenes(endpoint); | ||
const api_key = data.data.configuration.general.stashBoxes.find(o => o.endpoint = endpoint).api_key; | ||
await runGetStashboxPerformerSceneCountTask(endpoint, api_key, stash_id); | ||
const stashBoxSceneCount = await stash.pollLogsForMessage(`[Plugin / Stash Stashbox Scene Count] ${stash_id}: `); | ||
const el = getElementByXpath(`//span[@class='stash-id-pill']/a[text()='${stash_id}']`); | ||
if (el) { | ||
//el.innerText = `${stash_id} ${sceneCount}/${stashBoxSceneCount}`; | ||
el.innerText = `${stash_id} ${stashBoxSceneCount}`; | ||
} | ||
} | ||
} | ||
} | ||
stash.addEventListener('page:performer:any', performerPageHandler); | ||
stash.addEventListener('page:performer:details:expanded', performerPageHandler); | ||
|
||
async function studioPageHandler() { | ||
const settings = await stash.getPluginConfig('stashStashboxSceneCount'); | ||
if (settings?.studios) { | ||
const studio = await getStudio(); | ||
const data = await stash.getStashBoxes(); | ||
for (const { endpoint, stash_id } of studio.stash_ids) { | ||
const sceneCount = await getStudioScenes(endpoint, settings?.includeSubsidiaryStudios); | ||
const api_key = data.data.configuration.general.stashBoxes.find(o => o.endpoint = endpoint).api_key; | ||
await runGetStashboxStudioSceneCountTask(endpoint, api_key, stash_id); | ||
const stashBoxSceneCount = await stash.pollLogsForMessage(`[Plugin / Stash Stashbox Scene Count] ${stash_id}: `); | ||
const el = getElementByXpath(`//span[@class='stash-id-pill']/a[text()='${stash_id}']`); | ||
if (el) { | ||
//el.innerText = `${stash_id} ${sceneCount}/${stashBoxSceneCount}`; | ||
el.innerText = `${stash_id} ${stashBoxSceneCount}`; | ||
} | ||
} | ||
} | ||
} | ||
stash.addEventListener('page:studio:any', studioPageHandler); | ||
stash.addEventListener('page:studio:details:expanded', studioPageHandler); | ||
|
||
})(); |
86 changes: 86 additions & 0 deletions
86
plugins/stashStashboxSceneCount/stashStashboxSceneCount.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,86 @@ | ||
import json | ||
import log | ||
import sys | ||
from stashbox_scene_counts import stashbox_performer_scene_count, stashbox_studio_scene_count | ||
try: | ||
from stashlib.stash_database import StashDatabase | ||
from stashlib.stash_interface import StashInterface | ||
except ModuleNotFoundError: | ||
print("If you have pip (normally installed with python), run this command in a terminal (cmd): pip install pystashlib)", file=sys.stderr) | ||
sys.exit() | ||
|
||
json_input = json.loads(sys.stdin.read()) | ||
name = json_input['args']['name'] | ||
|
||
client = StashInterface(json_input["server_connection"]) | ||
|
||
def get_database_config(): | ||
result = client.callGraphQL("""query Configuration { configuration { general { databasePath, blobsPath, blobsStorage } } }""") | ||
database_path = result["configuration"]["general"]["databasePath"] | ||
blobs_path = result["configuration"]["general"]["blobsPath"] | ||
blobs_storage = result["configuration"]["general"]["blobsStorage"] | ||
log.debug(f"databasePath: {database_path}") | ||
return database_path, blobs_path, blobs_storage | ||
|
||
settings = client.callGraphQL("""query Configuration { configuration { plugins } }""")['configuration']['plugins'] | ||
if settings and 'stashStashboxSceneCount' in settings: | ||
pluginSettings = settings['stashStashboxSceneCount'] | ||
else: | ||
pluginSettings = {} | ||
|
||
try: | ||
db = StashDatabase(*get_database_config()) | ||
except Exception as e: | ||
log.error(str(e)) | ||
sys.exit(0) | ||
|
||
endpoint = json_input['args']['endpoint'] | ||
api_key = json_input['args']['api_key'] | ||
stash_id = json_input['args']['stash_id'] | ||
|
||
if name == 'stashbox_performer_scene_count': | ||
log.debug(f"stashbox_performer_scene_count: endpoint={endpoint}, stash_id={stash_id}") | ||
scene_count = stashbox_performer_scene_count(endpoint, api_key, stash_id) | ||
# pluginSettings['performerCount'] = scene_count | ||
# variables = { | ||
# "plugin_id": "stashStashboxSceneCount", | ||
# "input": pluginSettings | ||
# } | ||
# # log.debug(f"{stash_id}: {scene_count}") | ||
# client.callGraphQL("""mutation ConfigurePlugin($plugin_id: ID!, $input: Map!) { configurePlugin(plugin_id: $plugin_id, input: $input) }""", variables) | ||
database_scene_count = db.fetchone("""SELECT COUNT(DISTINCT b.stash_id) | ||
FROM scenes a | ||
JOIN scene_stash_ids b ON a.id = b.scene_id | ||
JOIN performers_scenes c ON a.id = c.scene_id | ||
JOIN performer_stash_ids d ON c.performer_id = d.performer_id | ||
WHERE d.stash_id = ?""", (stash_id, ))[0] | ||
log.debug(f"{stash_id}: {database_scene_count}/{scene_count}") | ||
elif name == 'stashbox_studio_scene_count': | ||
log.debug(f"stashbox_studio_scene_count: endpoint={endpoint}, stash_id={stash_id}") | ||
include_subsidiary_studios = 'includeSubsidiaryStudios' in pluginSettings and pluginSettings['includeSubsidiaryStudios'] | ||
log.debug(f"include_subsidiary_studios: {include_subsidiary_studios}") | ||
scene_count = stashbox_studio_scene_count(endpoint, api_key, stash_id, include_subsidiary_studios) | ||
# pluginSettings['studioCount'] = scene_count | ||
# variables = { | ||
# "plugin_id": "stashStashboxSceneCount", | ||
# "input": pluginSettings | ||
# } | ||
# # log.debug(f"{stash_id}: {scene_count}") | ||
# client.callGraphQL("""mutation ConfigurePlugin($plugin_id: ID!, $input: Map!) { configurePlugin(plugin_id: $plugin_id, input: $input) }""", variables) | ||
if not include_subsidiary_studios: | ||
database_scene_count = db.fetchone("""SELECT COUNT(DISTINCT b.stash_id) | ||
FROM scenes a | ||
JOIN scene_stash_ids b ON a.id = b.scene_id | ||
JOIN studio_stash_ids c ON c.studio_id = a.studio_id | ||
WHERE c.stash_id = ?""", (stash_id, ))[0] | ||
else: | ||
database_scene_count = db.fetchone("""SELECT COUNT(DISTINCT b.stash_id) | ||
FROM scenes a | ||
JOIN scene_stash_ids b ON a.id = b.scene_id | ||
JOIN studio_stash_ids c ON c.studio_id = a.studio_id | ||
JOIN studios d ON d.id = c.studio_id | ||
JOIN studio_stash_ids e ON e.studio_id = d.parent_id | ||
WHERE e.stash_id = ?""", (stash_id, ))[0] | ||
log.debug(f"{stash_id}: {database_scene_count}/{scene_count}") | ||
|
||
db.close() |
38 changes: 38 additions & 0 deletions
38
plugins/stashStashboxSceneCount/stashStashboxSceneCount.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: Stash Stashbox Scene Count | ||
# requires: stashUserscriptLibrary7dJx1qP | ||
description: Adds stashbox scene counts to performers and studios | ||
version: 0.1.0 | ||
ui: | ||
requires: | ||
- stashUserscriptLibrary7dJx1qP | ||
javascript: | ||
- stashStashboxSceneCount.js | ||
settings: | ||
performers: | ||
displayName: Display scene count on performers page | ||
type: BOOLEAN | ||
studios: | ||
displayName: Display scene count on studios page | ||
type: BOOLEAN | ||
includeSubsidiaryStudios: | ||
displayName: Include subsidiary studios | ||
type: BOOLEAN | ||
exec: | ||
- python | ||
- "{pluginDir}/stashStashboxSceneCount.py" | ||
interface: raw | ||
tasks: | ||
- name: Get Stashbox Performer Scene Count | ||
description: Gets stashbox performer scene count | ||
defaultArgs: | ||
name: stashbox_performer_scene_count | ||
endpoint: null | ||
api_key: null | ||
stash_id: null | ||
- name: Get Stashbox Studio Scene Count | ||
description: Gets stashbox studio scene count | ||
defaultArgs: | ||
name: stashbox_studio_scene_count | ||
endpoint: null | ||
api_key: null | ||
stash_id: null |
Oops, something went wrong.