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