summaryrefslogtreecommitdiff
path: root/priv/static/discordActivity.js
diff options
context:
space:
mode:
Diffstat (limited to 'priv/static/discordActivity.js')
-rw-r--r--priv/static/discordActivity.js113
1 files changed, 113 insertions, 0 deletions
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.");
+ });