summaryrefslogtreecommitdiff
path: root/adapter.js
blob: 5eecb4e9472dc31b68daa68e633ecaf68cb90149 (plain) (blame)
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
const { DiscordGatewayAdapterCreator, DiscordGatewayAdapterLibraryMethods } = require('@discordjs/voice');
const { VoiceChannel, Snowflake, Client, Constants, Guild } = require('discord.js');
const { GatewayVoiceServerUpdateDispatchData, GatewayVoiceStateUpdateDispatchData } = require('discord-api-types/v9');

const adapters = new Map();
const trackedClients = new Set();

/**
 * Tracks a Discord.js client, listening to VOICE_SERVER_UPDATE and VOICE_STATE_UPDATE events.
 * @param client - The Discord.js Client to track
 */
function trackClient(client) {
  if (trackedClients.has(client)) return;
  trackedClients.add(client);
  client.ws.on(Constants.WSEvents.VOICE_SERVER_UPDATE, (payload) => {
    adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload);
  });
  client.ws.on(Constants.WSEvents.VOICE_STATE_UPDATE, (payload) => {
    if (payload.guild_id && payload.session_id && payload.user_id === client.user?.id) {
      adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);
    }
  });
  client.on(Constants.Events.SHARD_DISCONNECT, (_, shardID) => {
    const guilds = trackedShards.get(shardID);
    if (guilds) {
      for (const guildID of guilds.values()) {
        adapters.get(guildID)?.destroy();
      }
    }
    trackedShards.delete(shardID);
  });
}

const trackedShards = new Map();

function trackGuild(guild) {
  let guilds = trackedShards.get(guild.shardID);
  if (!guilds) {
    guilds = new Set();
    trackedShards.set(guild.shardID, guilds);
  }
  guilds.add(guild.id);
}

/**
 * Creates an adapter for a Voice Channel
 * @param channel - The channel to create the adapter for
 */
function createDiscordJSAdapter(channel) {
  return (methods) => {
    adapters.set(channel.guild.id, methods);
    trackClient(channel.client);
    trackGuild(channel.guild);
    return {
      sendPayload(data) {
        if (channel.guild.shard.status === Constants.Status.READY) {
          channel.guild.shard.send(data);
          return true;
        }
        return false;
      },
      destroy() {
        return adapters.delete(channel.guild.id);
      },
    };
  };
}

module.exports = { createDiscordJSAdapter }