From df2d4b27f686185318abf089703f1867aa93d698 Mon Sep 17 00:00:00 2001 From: NotForMyCv <155258061+NotForMyCV@users.noreply.github.com> Date: Sun, 4 Aug 2024 23:36:37 +0100 Subject: [PATCH] [discordPresence] Added performers option and minor throttling --- plugins/discordPresence/README.md | 1 + plugins/discordPresence/discordPresence.js | 84 +++++++++++++-------- plugins/discordPresence/discordPresence.yml | 2 +- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/plugins/discordPresence/README.md b/plugins/discordPresence/README.md index fae394d1..fe1a6c97 100644 --- a/plugins/discordPresence/README.md +++ b/plugins/discordPresence/README.md @@ -50,3 +50,4 @@ Below are a list of available variable names: - `{url}` - `{studio_name}` - `{file_duration}` +- `{performers}` diff --git a/plugins/discordPresence/discordPresence.js b/plugins/discordPresence/discordPresence.js index 2dcf70c7..07073448 100644 --- a/plugins/discordPresence/discordPresence.js +++ b/plugins/discordPresence/discordPresence.js @@ -16,20 +16,17 @@ * @typedef {{ * id, title, code, details, director, urls?: string[], date, rating100, o_counter, * organized, interactive, interactive_speed, created_at, updated_at, resume_time, - * last_played_at, play_duration, play_count, files: {duration:number}[], studio?: {id, name} + * last_played_at, play_duration, play_count, files: {duration:number}[], + * studio?: {id, name}, performers: {name, gender}[] * }} SceneData */ /** - * @typedef {{ studio_name: string, url: string, file_duration: string } - * & Omit + * @typedef {{ studio_name: string, url: string, file_duration: string, performers: string } + * & Omit * } FlattenedSceneData */ - /** - * @typedef {{ data: { findScene: SceneData | null } }} GQLSceneDataResponse - */ - const SCENE_GQL_QUERY = ` query FindScene($id: ID!) { findScene(id: $id) { @@ -58,6 +55,7 @@ play_count files { duration } studio { name } + performers { name, gender } } `; @@ -82,6 +80,19 @@ console.debug("Discord Presence Plugin: loaded config", CONFIG); + function throttle(mainFunction, delay) { + let timerFlag = null; + + return (...args) => { + if (timerFlag === null) { + mainFunction(...args); + timerFlag = setTimeout(() => { + timerFlag = null; + }, delay); + } + }; + } + const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const player = () => document.querySelector("#VideoJsPlayer video"); @@ -92,23 +103,6 @@ /** @type {WebSocket} */ let ws; const wsAlive = () => ws && ws.readyState === 1; - const videoListener = (video) => { - SCENE_ID = parseInt(location.pathname.split("/")[2]); - video.addEventListener("playing", setDiscordActivity); - video.addEventListener("play", setDiscordActivity); - video.addEventListener("timeupdate", setDiscordActivity); - video.addEventListener("seeked", setDiscordActivity); - video.addEventListener("ended", clearDiscordActivity); - }; - - const unbindVideoListener = (video) => { - video.removeEventListener("playing", setDiscordActivity); - video.removeEventListener("play", setDiscordActivity); - video.removeEventListener("timeupdate", setDiscordActivity); - video.removeEventListener("seeked", setDiscordActivity); - video.removeEventListener("ended", clearDiscordActivity); - }; - // Start ws connection to RPC server and add video listener // Will retry on disconnection/error after 10s async function start() { @@ -167,7 +161,7 @@ query: SCENE_GQL_QUERY, }; - /** @type {GQLSceneDataResponse} */ + /** @type {SceneData} */ const sceneData = await csLib .callGQL(reqData) .then((data) => data.findScene); @@ -178,17 +172,21 @@ studio_name: sceneData.studio?.name ?? "Unknown Studio", url: sceneData.urls?.length ? sceneData.urls[0] : "", file_duration: sceneData.files?.length ? sceneData.files[0].duration : 0, + performers: sceneData.performers.length + ? sceneData.performers.map((performer) => performer.name).join(", ") + : "Unlisted Performer(s)", }; delete sceneData.urls; delete sceneData.studio; delete sceneData.files; + delete sceneData.performers; cachedSceneData = { ...sceneData, ...newProps }; return cachedSceneData; } - function clearDiscordActivity() { + const clearDiscordActivity = () => { if (!!SCENE_ID === false || !wsAlive()) { return; } @@ -200,9 +198,9 @@ clearActivity: true, }) ); - } + }; - async function setDiscordActivity(event) { + const setDiscordActivity = throttle(async (event) => { if (event?.type === "timeupdate") { if (!WAITING_FOR_REFRESH) { return; @@ -249,7 +247,7 @@ presence: body, }) ); - } + }, 1000); /** * Performs string replacement on templated config vars with scene data @@ -258,6 +256,32 @@ */ function replaceVars(templateStr, sceneData) { const pattern = /{\s*(\w+?)\s*}/g; - return templateStr.replace(pattern, (_, token) => sceneData[token] ?? ""); + + const replacedStr = templateStr + .replace(pattern, (_, token) => sceneData[token] ?? "") + .trim(); + + if (replacedStr.length <= 128) { + return replacedStr; + } + + return replacedStr.substring(0, 125) + "..."; } + + const videoListener = (video) => { + SCENE_ID = parseInt(location.pathname.split("/")[2]); + video.addEventListener("playing", setDiscordActivity); + video.addEventListener("play", setDiscordActivity); + video.addEventListener("timeupdate", setDiscordActivity); + video.addEventListener("seeked", setDiscordActivity); + video.addEventListener("ended", clearDiscordActivity); + }; + + const unbindVideoListener = (video) => { + video.removeEventListener("playing", setDiscordActivity); + video.removeEventListener("play", setDiscordActivity); + video.removeEventListener("timeupdate", setDiscordActivity); + video.removeEventListener("seeked", setDiscordActivity); + video.removeEventListener("ended", clearDiscordActivity); + }; })(); diff --git a/plugins/discordPresence/discordPresence.yml b/plugins/discordPresence/discordPresence.yml index 6a27da16..65cad628 100644 --- a/plugins/discordPresence/discordPresence.yml +++ b/plugins/discordPresence/discordPresence.yml @@ -2,7 +2,7 @@ name: Discord Presence description: Sets currently playing scene data as your Discord status. See README for prerequisites and config options (blue hyperlink next to enable/disable button) url: https://github.com/stashapp/CommunityScripts/tree/main/plugins/discordPresence # requires: CommunityScriptsUILibrary -version: 1.2 +version: 1.3 settings: discordClientId: displayName: Custom Discord application ID