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

[discordPresence] Added performers option and minor throttling #385

Merged
merged 1 commit into from
Aug 4, 2024
Merged
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
1 change: 1 addition & 0 deletions plugins/discordPresence/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ Below are a list of available variable names:
- `{url}`
- `{studio_name}`
- `{file_duration}`
- `{performers}`
84 changes: 54 additions & 30 deletions plugins/discordPresence/discordPresence.js
Original file line number Diff line number Diff line change
Expand Up @@ -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<SceneData, ['urls', 'files', 'studio']>
* @typedef {{ studio_name: string, url: string, file_duration: string, performers: string }
* & Omit<SceneData, ['urls', 'files', 'studio', 'performers']>
* } FlattenedSceneData
*/

/**
* @typedef {{ data: { findScene: SceneData | null } }} GQLSceneDataResponse
*/

const SCENE_GQL_QUERY = `
query FindScene($id: ID!) {
findScene(id: $id) {
Expand Down Expand Up @@ -58,6 +55,7 @@
play_count
files { duration }
studio { name }
performers { name, gender }
}
`;

Expand All @@ -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");

Expand All @@ -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() {
Expand Down Expand Up @@ -167,7 +161,7 @@
query: SCENE_GQL_QUERY,
};

/** @type {GQLSceneDataResponse} */
/** @type {SceneData} */
const sceneData = await csLib
.callGQL(reqData)
.then((data) => data.findScene);
Expand All @@ -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;
}
Expand All @@ -200,9 +198,9 @@
clearActivity: true,
})
);
}
};

async function setDiscordActivity(event) {
const setDiscordActivity = throttle(async (event) => {
if (event?.type === "timeupdate") {
if (!WAITING_FOR_REFRESH) {
return;
Expand Down Expand Up @@ -249,7 +247,7 @@
presence: body,
})
);
}
}, 1000);

/**
* Performs string replacement on templated config vars with scene data
Expand All @@ -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);
};
})();
2 changes: 1 addition & 1 deletion plugins/discordPresence/discordPresence.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down