From 407862a4e0e10ce2a035e4e5e76e26dde849aac1 Mon Sep 17 00:00:00 2001 From: Arjun Satarkar Date: Sat, 27 Jul 2024 21:04:28 +0530 Subject: Finish Discord activity implementation --- priv/discord_activity.html.eex | 44 +++++++++++++-- priv/static/discordActivity.js | 113 +++++++++++++++++++++++++++++++++++++++ priv/static/discord_activity.js | 20 ------- priv/static/room/displayState.js | 5 +- 4 files changed, 155 insertions(+), 27 deletions(-) create mode 100644 priv/static/discordActivity.js delete mode 100644 priv/static/discord_activity.js (limited to 'priv') diff --git a/priv/discord_activity.html.eex b/priv/discord_activity.html.eex index 83bda0d..5278400 100644 --- a/priv/discord_activity.html.eex +++ b/priv/discord_activity.html.eex @@ -1,3 +1,4 @@ +<% home_url = "/.proxy/?#{Mediasync.Constants.query_param_discord_activity_inner()}" %> @@ -6,25 +7,58 @@ discord activity | mediasync - - + +
+ currently hosting: +
+
+ + - + diff --git a/priv/static/discordActivity.js b/priv/static/discordActivity.js new file mode 100644 index 0000000..7ec4872 --- /dev/null +++ b/priv/static/discordActivity.js @@ -0,0 +1,113 @@ +import { DiscordSDK } from "/static/discord-embedded-app-sdk/Discord.js"; + +const discordSdk = new DiscordSDK(DISCORD_CLIENT_ID); + +const updateInstanceRoomInfo = () => { + const contentEl = document.getElementById("instance-room-info-content"); + + const defaultContents = document.createElement("i"); + defaultContents.innerText = "none yet"; + if (!contentEl.hasChildNodes()) { + contentEl.replaceChildren(defaultContents); + } + + fetch( + `/.proxy/discord_activity/rooms_for_instance?discord_activity_inner&instance_id=${discordSdk.instanceId}`, + ) + .then((response) => { + if (!response.ok) { + throw new Error(`Fetching instance room info failed with status code ${response.status}`); + } + return response.json(); + }) + .then((json) => { + let docFragment = new DocumentFragment(); + if (json.length === 0) { + docFragment.appendChild(defaultContents); + } else { + const listEl = docFragment.appendChild(document.createElement("ul")); + for (const roomInfo of json) { + const item = listEl.appendChild(document.createElement("li")); + item.innerText = roomInfo["host_username"] + " "; + const form = item.appendChild(document.createElement("form")); + form.action = roomUrl(roomInfo["room_id"]); + form.target = "activity-inner-iframe"; + form.style.display = "inline"; + const hiddenInput = form.appendChild(document.createElement("input")); + hiddenInput.type = "hidden"; + hiddenInput.name = "discord_activity_inner"; + const submitInput = form.appendChild(document.createElement("input")); + submitInput.type = "submit"; + submitInput.value = "join"; + } + } + contentEl.replaceChildren(docFragment); + }) + .catch((error) => { + console.error(error); + }); +}; + +updateInstanceRoomInfo(); +const INSTANCE_ROOM_INFO_INTERVAL = 3000; +let instanceRoomInfoIntervalId = setInterval(updateInstanceRoomInfo, INSTANCE_ROOM_INFO_INTERVAL); + +const iframe = document.querySelector("iframe"); +// It doesn't matter if the iframe's initial loading finishes before this is added +iframe.addEventListener("load", (_) => { + clearInterval(instanceRoomInfoIntervalId); + + const locationURL = new URL(iframe.contentWindow.location); + const locationPath = locationURL.pathname + locationURL.search; + if (locationPath === HOME_URL) { + instanceRoomInfoIntervalId = setInterval(updateInstanceRoomInfo, INSTANCE_ROOM_INFO_INTERVAL); + iframe.className = "at-home"; + } else { + iframe.className = ""; + } +}); + +discordSdk + .ready() + .then(() => { + return discordSdk.commands.authorize({ + client_id: DISCORD_CLIENT_ID, + response_type: "code", + state: "", + prompt: "none", + scope: ["identify"], + }); + }) + .then((result) => { + const { code } = result; + + return fetch(ACCESS_TOKEN_URL, { + body: new URLSearchParams([["code", code]]), + headers: { + "content-type": "application/x-www-form-urlencoded", + "x-csrf-token": document.body.dataset.csrfToken, + }, + method: "POST", + }); + }) + .then((response) => { + if (!response.ok) { + throw new Error(`Getting access token failed with status code ${response.status}`); + } + // Note: the access token should now be in the session cookie as well + return response.text(); + }) + .then((accessToken) => { + return discordSdk.commands.authenticate({ access_token: accessToken }); + }) + .then((authenticationResult) => { + if (authenticationResult === null) { + throw new Error("Authenticating with Discord client failed"); + } + iframe.style.display = null; + }) + .catch((error) => { + console.error(error); + const CLOSE_ABNORMAL = 1006; + discordSdk.close(CLOSE_ABNORMAL, "Could not obtain authorizations required to run this app."); + }); diff --git a/priv/static/discord_activity.js b/priv/static/discord_activity.js deleted file mode 100644 index 344c30d..0000000 --- a/priv/static/discord_activity.js +++ /dev/null @@ -1,20 +0,0 @@ -import { DiscordSDK } from "/static/discord-embedded-app-sdk/Discord.js"; - -const discordSdk = new DiscordSDK(DISCORD_CLIENT_ID); - -discordSdk - .ready() - .then(() => { - console.log("Mediasync: Discord SDK ready."); - return discordSdk.commands.authorize({ - client_id: DISCORD_CLIENT_ID, - response_type: "code", - state: "", - prompt: "none", - scope: ["identify"], - }); - }) - .then((result) => { - const { code } = result; - console.log(code); - }); diff --git a/priv/static/room/displayState.js b/priv/static/room/displayState.js index 3a5e923..a2da229 100644 --- a/priv/static/room/displayState.js +++ b/priv/static/room/displayState.js @@ -9,7 +9,7 @@ fetch(STATE_URL) .then((response) => { if (!response.ok) { - throw new Error(`Error: fetching state returned ${response.status}`); + throw new Error(`Fetching room state failed with status code ${response.status}`); } return response.json(); }) @@ -17,7 +17,8 @@ const viewersConnected = json.viewersConnected; stateElement.dataset.text = `total viewers: ${viewersConnected}`; }) - .catch((_) => { + .catch((error) => { + console.error(error); stateElement.dataset.text = STATE_ELEMENT_INITIAL_TEXT; }); } -- cgit v1.2.3-57-g22cb