aboutsummaryrefslogtreecommitdiff
path: root/priv/static/discordActivity.js
blob: ad7a6c30c2c6ee1d2efaeea309047602d4a3c4d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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.textContent = "none yet";
  if (!contentEl.hasChildNodes()) {
    contentEl.replaceChildren(defaultContents);
  }

  fetch(roomsForInstanceUrl(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.textContent = roomInfo["host_username"] + " — ";
          const filename = item.appendChild(document.createElement("code"));
          filename.textContent = roomInfo["filename"] + " ";
          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 = QUERY_PARAM_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) {
    updateInstanceRoomInfo();
    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.");
  });