From b8ebf92df364d0e3e18fa7b4e5374cf136599320 Mon Sep 17 00:00:00 2001 From: Andrei Jiroh Eugenio Halili Date: Tue, 22 Mar 2022 15:29:40 +0000 Subject: [PATCH] feat(global): add utility functions to library code + overhaul stuff A bit painful to test inside a Gitpod workspace through, but it worked, at least we'll not distrub Discord Support regarding approval for using RPC yet for now. Includes syntax fixes on state stuff and even improving parts of the code. README will be next btw. Signed-off-by: Andrei Jiroh Eugenio Halili --- app.js | 61 +++++++++++++++++++++++++++++++++---------------- lib/defaults.js | 10 ++++---- lib/teams.js | 45 +++++++++++++++++++++++++++++++----- lib/utils.js | 53 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 31 deletions(-) create mode 100644 lib/utils.js diff --git a/app.js b/app.js index cbde58c..874d2bb 100644 --- a/app.js +++ b/app.js @@ -1,22 +1,24 @@ const express = require("express") const app = new express() -const RPC = require('discord-rpc'); -const client = new RPC.Client({ transport: 'ipc' }); +const { AutoClient } = require("discord-auto-rpc") +const client = new AutoClient({ transport: 'ipc' }); const { defaultActivity } = require("./lib/defaults"); const { teamsIndex } = require("./lib/teams") const port = process.env.PORT || 60881 -const { getState, updateState, preloadState } = require("./lib/utils"); +const { getState, updateState, sixHoursAgo, timestampStart } = require("./lib/utils"); const fs = require("node:fs"); -const { get } = require("node:http"); - -app.get("/changeTeams/regular-participant/:teamSlug", (res, req) => { - if (req.teamSlug == "sprecators") { +app.get("/changeTeams/regular-participant/:teamSlug", (req, res) => { + if (req.params.teamSlug == "spectator") { client.setActivity({ pid: process.pid, - activity: teamsIndex.regularEvents.sprecators + activity: teamsIndex.regularEvents.spectator + }) + updateState(teamsIndex.regularEvents.spectator) + res.json({ + ok: true, + state: getState() }) - updateState(teamsIndex.regularEvents.sprecators) } else { res.status(404).json({ ok: false, @@ -29,16 +31,29 @@ app.get("/getState", (req, res) => { res.json(getState()) }) -app.get("/getState/preloaded", (req, res) => { - res.json(preloadState) -}) - client.on('ready', async () => { - fs.stat('rpcState.json', function(err, stat) { + fs.stat('rpcState.json', (err, stat) => { + if (err == null) { + resetStartTimestamp = { + details: getState().details, + assets: getState().assets, + state: getState().state, + buttons: getState().buttons, + timestamps: { + start: timestampStart() + } + } console.log('info: State file exists, preloading from previous state'); - client.request("SET_ACTIVITY", { pid: process.pid, activity: getState() }); + /** Check if timestamp.start from getState is longer than six hours to trigger reset. */ + if (sixHoursAgo > getState().timestamps.start) { + console.log("info: timestamp.start from state file is less than 6 hours ago, preloading") + client.request("SET_ACTIVITY", { pid: process.pid, activity: getState() }); + } else if (sixHoursAgo < getState().timestamps.start) { + console.log('info: timestamp.start from state file is longer than 6 hours, resetting...') + updateState(resetStartTimestamp) + } } else { client.request("SET_ACTIVITY", { pid: process.pid, activity: defaultActivity }); console.log("info: Using default activity for state due to file issues"); @@ -46,14 +61,20 @@ client.on('ready', async () => { } }); }); -client.on('connected', async () => { - console.log("info: Connected to Discord RPC"); +client.once('connected', async () => { + console.log("info: Connected to Discord local RPC server"); }); app.listen(port, () => { console.log("info: REST API is up at http://localhost:"+port+", see README.md and docs directory") - console.log("info: for the API docs.") + console.log("info: for the API docs. Please do not make API calls yet until the API server successfully") + console.log("info: connects to Discord RPC to avoid issues..") }) - // Uses the unofficial MCC.Live OAuth client ID from Andrei Jiroh. -client.login({ clientId: "952456760948559932" }); +// Uses discord-auto-rpc behind the scenes to attempt to connect to RPC and wait until Discord is up. +client.endlessLogin({ clientId: "952456760948559932" }); + +module.exports = { + app, + client +} \ No newline at end of file diff --git a/lib/defaults.js b/lib/defaults.js index 844d368..fea4d6b 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -1,3 +1,5 @@ +const { timestampStart } = require("./utils") + let defaultActivity = { details: "Event starts soon", assets: { @@ -6,21 +8,19 @@ let defaultActivity = { small_image: "spectator", small_text: "Probably watching on Admin Stream soon" }, + state: "Idling behind the scenes", buttons: [ { "label": "Check event stats", "url": "https://mcc.live" }, { - "label": "View source", + "label": "Use this Custom RPC", "url": "https://gitlab.com/RecapTime/mcc-discord-rpc" } ], timestamps: { - // set start time to when it's started - start: Date.now(), - // TODO: Update the end time, assuming that @TubboLive leaks it again. - end: 1651032000000 // MCC20 in UTC time + start: timestampStart() } } diff --git a/lib/teams.js b/lib/teams.js index 3c21ac3..dd88f3e 100644 --- a/lib/teams.js +++ b/lib/teams.js @@ -1,10 +1,38 @@ +const { timestampStart } = require("./utils") + let teamsIndex = { regularEvents: { - sprecators: { - description: "Watching Admin Stream", + spectator: { + details: "On the Admin Stream", + state: "https://twitch.tv/TheNoxcrew", assets: { large_image: "mcc-twitter", - large_text: "MC Championship" + large_text: "MC Championship", + small_image: "spectator", + small_text: "Admin Stream" + }, + buttons: [ + { + "label": "Check event stats", + "url": "https://mcc.live" + }, + { + "label": "Use this Custom RPC", + "url": "https://gitlab.com/RecapTime/mcc-discord-rpc" + } + ], + timestamps: { + start: timestampStart() + } + }, + red: { + description: "Participating as a Red Rabbit", + state: "Join me over the stream", + assets: { + large_image: "mcc-twitter", + large_text: "MC Championship", + small_image: "red-rabbits", + small_text: "Red Rabbit" }, buttons: [ { @@ -12,16 +40,21 @@ let teamsIndex = { "url": "https://mcc.live" }, { - "label": "View source", + "label": "Use this Custom RPC", "url": "https://gitlab.com/RecapTime/mcc-discord-rpc" } ], timestamp: { - start: Date.now() + start: timestampStart() } } }, specialEvents: {} } -module.exports = teamsIndex \ No newline at end of file +let teamsWatchingIndex = {} + +module.exports = { + teamsIndex, + teamsWatchingIndex +} \ No newline at end of file diff --git a/lib/utils.js b/lib/utils.js new file mode 100644 index 0000000..54532b8 --- /dev/null +++ b/lib/utils.js @@ -0,0 +1,53 @@ +const timestampStartDefault = Date.now(); +const { client } = require("../app") +const fs = require("node:fs") +let sixHoursAgo = Date.now() + (1 * 6 * 60 * 60 * 1000) + +/** + * Get current RPC state fro rpcState.json file on the source code root. + * @returns {object} data - Parsed JSON object + */ +function getState () { + data = fs.readFileSync('rpcState.json', 'utf-8', (err, data) => { + if (err) { + return "{}"; + } + + return JSON.parse(data) + }) + return JSON.parse(data) +} + +function updateState (data) { + client.request('SET_ACTIVITY', { pid: process.pid, activity: data }) + const stringifiedJson = Buffer.from(JSON.stringify(data)) + fs.writeFile("rpcState.json", stringifiedJson, (err) => { + if (err) { + console.log("warn: State file doesn't exist yet.") + } + }) +} +function timestampStart() { + try { + if (getState() == {} || getState().timestamps.start === undefined) { + return timestampStartDefault + } else if (getState().timestamps.start !== undefined ) { + if (sixHoursAgo > getState().timestamps.start) { + return getState().timestamps.start + } else if (sixHoursAgo < getState().timestamps.start) { + return timestampStartDefault + } + } + } catch { + return timestampStartDefault + } +} + + + +module.exports = { + timestampStart, + updateState, + getState, + sixHoursAgo +} \ No newline at end of file