disgroove 2.2.1-dev.efad41d → 2.2.2-dev.23938d8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/lib/Client.d.ts +2 -0
- package/dist/lib/Client.js +17 -20
- package/dist/lib/gateway/Shard.d.ts +3 -1
- package/dist/lib/gateway/Shard.js +25 -5
- package/dist/lib/gateway/ShardManager.d.ts +6 -1
- package/dist/lib/gateway/ShardManager.js +6 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +1 -0
- package/dist/lib/types/gateway-events.d.ts +14 -1
- package/dist/lib/types/poll.d.ts +4 -4
- package/dist/lib/types/voice-connections.d.ts +64 -0
- package/dist/lib/types/voice-connections.js +2 -0
- package/dist/lib/voice/VoiceConnection.d.ts +57 -0
- package/dist/lib/voice/VoiceConnection.js +150 -0
- package/dist/lib/voice/VoiceConnectionManager.d.ts +19 -0
- package/dist/lib/voice/VoiceConnectionManager.js +66 -0
- package/dist/lib/voice/index.d.ts +2 -0
- package/dist/lib/voice/index.js +18 -0
- package/dist/package.json +3 -3
- package/package.json +3 -3
package/README.md
CHANGED
@@ -3,11 +3,13 @@
|
|
3
3
|
A module to interface with Discord
|
4
4
|
|
5
5
|
- Fast
|
6
|
+
- Lightweight
|
7
|
+
- Flexible
|
6
8
|
- 100% coverage of the [Official Discord API Documentation](https://discord.com/developers/docs/intro)
|
7
9
|
|
8
10
|
## Installation
|
9
11
|
|
10
|
-
[**
|
12
|
+
[**NodeJS v18**](https://nodejs.org) or newer required
|
11
13
|
|
12
14
|
```
|
13
15
|
npm install disgroove
|
package/dist/lib/Client.d.ts
CHANGED
@@ -28,6 +28,7 @@ import type { Sticker, StickerPack } from "./types/sticker";
|
|
28
28
|
import type { User, ApplicationRoleConnection, Connection } from "./types/user";
|
29
29
|
import type { VoiceRegion, VoiceState } from "./types/voice";
|
30
30
|
import type { Webhook } from "./types/webhook";
|
31
|
+
import { VoiceConnectionManager } from "./voice";
|
31
32
|
export interface ClientOptions {
|
32
33
|
intents?: number | Array<number>;
|
33
34
|
shardsCount?: number | "auto";
|
@@ -45,6 +46,7 @@ export declare class Client extends EventEmitter {
|
|
45
46
|
user: User;
|
46
47
|
guilds: Map<string, Guild>;
|
47
48
|
application: Pick<Application, "id" | "flags">;
|
49
|
+
voiceConnections: VoiceConnectionManager;
|
48
50
|
constructor(token: string, options?: ClientOptions);
|
49
51
|
/** https://discord.com/developers/docs/resources/channel#group-dm-add-recipient */
|
50
52
|
addGroupRecipient(channelID: snowflake, userID: snowflake, options: {
|
package/dist/lib/Client.js
CHANGED
@@ -9,6 +9,7 @@ const utils_1 = require("./utils");
|
|
9
9
|
const rest_1 = require("./rest");
|
10
10
|
const node_events_1 = __importDefault(require("node:events"));
|
11
11
|
const gateway_1 = require("./gateway");
|
12
|
+
const voice_1 = require("./voice");
|
12
13
|
class Client extends node_events_1.default {
|
13
14
|
token;
|
14
15
|
intents;
|
@@ -21,6 +22,7 @@ class Client extends node_events_1.default {
|
|
21
22
|
user;
|
22
23
|
guilds;
|
23
24
|
application;
|
25
|
+
voiceConnections;
|
24
26
|
constructor(token, options) {
|
25
27
|
super();
|
26
28
|
this.token = token;
|
@@ -37,6 +39,7 @@ class Client extends node_events_1.default {
|
|
37
39
|
this.util = new utils_1.Util();
|
38
40
|
this.guildShardMap = {};
|
39
41
|
this.guilds = new Map();
|
42
|
+
this.voiceConnections = new voice_1.VoiceConnectionManager();
|
40
43
|
}
|
41
44
|
/** https://discord.com/developers/docs/resources/channel#group-dm-add-recipient */
|
42
45
|
addGroupRecipient(channelID, userID, options) {
|
@@ -1987,15 +1990,12 @@ class Client extends node_events_1.default {
|
|
1987
1990
|
}
|
1988
1991
|
/** https://discord.com/developers/docs/topics/gateway-events#update-voice-state */
|
1989
1992
|
joinVoiceChannel(guildID, channelID, options) {
|
1990
|
-
this.shards.get(this.guildShardMap[guildID])?.
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
1996
|
-
self_deaf: !!options?.selfDeaf,
|
1997
|
-
},
|
1998
|
-
}));
|
1993
|
+
this.shards.get(this.guildShardMap[guildID])?.updateVoiceState({
|
1994
|
+
guildID: guildID,
|
1995
|
+
channelID: channelID,
|
1996
|
+
selfMute: !!options?.selfMute,
|
1997
|
+
selfDeaf: !!options?.selfDeaf,
|
1998
|
+
});
|
1999
1999
|
}
|
2000
2000
|
/** https://discord.com/developers/docs/resources/user#leave-guild */
|
2001
2001
|
leaveGuild(guildID) {
|
@@ -2007,15 +2007,13 @@ class Client extends node_events_1.default {
|
|
2007
2007
|
}
|
2008
2008
|
/** https://discord.com/developers/docs/topics/gateway-events#update-voice-state */
|
2009
2009
|
leaveVoiceChannel(guildID) {
|
2010
|
-
this.
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
2016
|
-
|
2017
|
-
},
|
2018
|
-
}));
|
2010
|
+
this.voiceConnections.disconnect(guildID);
|
2011
|
+
this.shards.get(this.guildShardMap[guildID])?.updateVoiceState({
|
2012
|
+
guildID: guildID,
|
2013
|
+
channelID: null,
|
2014
|
+
selfMute: false,
|
2015
|
+
selfDeaf: false,
|
2016
|
+
});
|
2019
2017
|
}
|
2020
2018
|
/** https://discord.com/developers/docs/resources/channel#pin-message */
|
2021
2019
|
pinMessage(channelID, messageID, reason) {
|
@@ -2061,8 +2059,7 @@ class Client extends node_events_1.default {
|
|
2061
2059
|
}
|
2062
2060
|
/** https://discord.com/developers/docs/topics/gateway-events#update-presence */
|
2063
2061
|
setPresence(options) {
|
2064
|
-
|
2065
|
-
shard.updatePresence(options);
|
2062
|
+
this.shards.updatePresence(options);
|
2066
2063
|
}
|
2067
2064
|
/** https://discord.com/developers/docs/resources/guild-template#sync-guild-template */
|
2068
2065
|
async syncGuildTemplate(guildID, code) {
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import WebSocket from "ws";
|
2
2
|
import { Client } from "../Client";
|
3
|
-
import type { GatewayPresenceUpdate, Identify, RequestGuildMembers, Resume } from "../types/gateway-events";
|
3
|
+
import type { GatewayPresenceUpdate, GatewayVoiceStateUpdate, Identify, RequestGuildMembers, Resume } from "../types/gateway-events";
|
4
4
|
export declare class Shard {
|
5
5
|
id: number;
|
6
6
|
private heartbeatInterval;
|
@@ -27,4 +27,6 @@ export declare class Shard {
|
|
27
27
|
resume(options: Resume): void;
|
28
28
|
/** https://discord.com/developers/docs/topics/gateway-events#update-presence */
|
29
29
|
updatePresence(options: Partial<Pick<GatewayPresenceUpdate, "activities" | "status" | "afk">>): void;
|
30
|
+
/** https://discord.com/developers/docs/topics/gateway-events#update-voice-state */
|
31
|
+
updateVoiceState(options: GatewayVoiceStateUpdate): void;
|
30
32
|
}
|
@@ -462,11 +462,19 @@ class Shard {
|
|
462
462
|
this.client.emit(constants_1.GatewayEvents.VoiceStateUpdate, this.client.util.voiceStateFromRaw(packet.d));
|
463
463
|
break;
|
464
464
|
case "VOICE_SERVER_UPDATE":
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
465
|
+
{
|
466
|
+
this.client.voiceConnections.connect(packet.d.endpoint, {
|
467
|
+
serverID: packet.d.guild_id,
|
468
|
+
userID: this.client.user.id,
|
469
|
+
sessionID: this.sessionID,
|
470
|
+
token: packet.d.token,
|
471
|
+
});
|
472
|
+
this.client.emit(constants_1.GatewayEvents.VoiceServerUpdate, {
|
473
|
+
token: packet.d.token,
|
474
|
+
guildID: packet.d.guild_id,
|
475
|
+
endpoint: packet.d.endpoint,
|
476
|
+
});
|
477
|
+
}
|
470
478
|
break;
|
471
479
|
case "WEBHOOKS_UPDATE":
|
472
480
|
this.client.emit(constants_1.GatewayEvents.WebhooksUpdate, packet.d.channel_id, packet.d.guild_id);
|
@@ -568,5 +576,17 @@ class Shard {
|
|
568
576
|
},
|
569
577
|
}));
|
570
578
|
}
|
579
|
+
/** https://discord.com/developers/docs/topics/gateway-events#update-voice-state */
|
580
|
+
updateVoiceState(options) {
|
581
|
+
this.ws.send(JSON.stringify({
|
582
|
+
op: constants_1.GatewayOPCodes.VoiceStateUpdate,
|
583
|
+
d: {
|
584
|
+
guild_id: options.guildID,
|
585
|
+
channel_id: options.channelID,
|
586
|
+
self_mute: options.selfMute,
|
587
|
+
self_deaf: options.selfDeaf,
|
588
|
+
},
|
589
|
+
}));
|
590
|
+
}
|
571
591
|
}
|
572
592
|
exports.Shard = Shard;
|
@@ -1,5 +1,10 @@
|
|
1
|
-
import { Shard } from ".";
|
1
|
+
import type { Shard } from ".";
|
2
|
+
import type { GatewayPresenceUpdate } from "../types/gateway-events";
|
2
3
|
export declare class ShardManager extends Map<number, Shard> {
|
4
|
+
/** https://discord.com/developers/docs/topics/gateway#connections */
|
3
5
|
connect(): void;
|
6
|
+
/** https://discord.com/developers/docs/topics/gateway#connections */
|
4
7
|
disconnect(): void;
|
8
|
+
/** https://discord.com/developers/docs/topics/gateway-events#update-presence */
|
9
|
+
updatePresence(options: Partial<Pick<GatewayPresenceUpdate, "activities" | "status" | "afk">>): void;
|
5
10
|
}
|
@@ -2,11 +2,17 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.ShardManager = void 0;
|
4
4
|
class ShardManager extends Map {
|
5
|
+
/** https://discord.com/developers/docs/topics/gateway#connections */
|
5
6
|
connect() {
|
6
7
|
this.forEach((shard) => shard.connect());
|
7
8
|
}
|
9
|
+
/** https://discord.com/developers/docs/topics/gateway#connections */
|
8
10
|
disconnect() {
|
9
11
|
this.forEach((shard) => shard.disconnect());
|
10
12
|
}
|
13
|
+
/** https://discord.com/developers/docs/topics/gateway-events#update-presence */
|
14
|
+
updatePresence(options) {
|
15
|
+
this.forEach((shard) => shard.updatePresence(options));
|
16
|
+
}
|
11
17
|
}
|
12
18
|
exports.ShardManager = ShardManager;
|
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.js
CHANGED
@@ -42,5 +42,6 @@ __exportStar(require("./types/user"), exports);
|
|
42
42
|
__exportStar(require("./types/voice"), exports);
|
43
43
|
__exportStar(require("./types/webhook"), exports);
|
44
44
|
__exportStar(require("./utils"), exports);
|
45
|
+
__exportStar(require("./voice"), exports);
|
45
46
|
__exportStar(require("./Client"), exports);
|
46
47
|
__exportStar(require("./constants"), exports);
|
@@ -11,7 +11,7 @@ import type { RawUser, RawAvatarDecorationData, User, AvatarDecorationData } fro
|
|
11
11
|
import type { RawVoiceState, VoiceState } from "./voice";
|
12
12
|
/** https://discord.com/developers/docs/topics/gateway-events#payload-structure */
|
13
13
|
export interface RawPayload {
|
14
|
-
op:
|
14
|
+
op: number;
|
15
15
|
d: any | null;
|
16
16
|
s: number | null;
|
17
17
|
t: string | null;
|
@@ -54,6 +54,13 @@ export interface RawGatewayPresenceUpdate {
|
|
54
54
|
status: StatusTypes;
|
55
55
|
afk: boolean;
|
56
56
|
}
|
57
|
+
/** https://discord.com/developers/docs/topics/gateway-events#update-voice-state-gateway-voice-state-update-structure */
|
58
|
+
export interface RawGatewayVoiceStateUpdate {
|
59
|
+
guild_id: snowflake;
|
60
|
+
channel_id: snowflake | null;
|
61
|
+
self_mute: boolean;
|
62
|
+
self_deaf: boolean;
|
63
|
+
}
|
57
64
|
/** https://discord.com/developers/docs/topics/gateway-events#auto-moderation-action-execution-auto-moderation-action-execution-event-fields */
|
58
65
|
export interface RawAutoModerationActionExecutionEventFields {
|
59
66
|
guild_id: snowflake;
|
@@ -377,6 +384,12 @@ export interface GatewayPresenceUpdate {
|
|
377
384
|
status: StatusTypes;
|
378
385
|
afk: boolean;
|
379
386
|
}
|
387
|
+
export interface GatewayVoiceStateUpdate {
|
388
|
+
guildID: snowflake;
|
389
|
+
channelID: snowflake | null;
|
390
|
+
selfMute: boolean;
|
391
|
+
selfDeaf: boolean;
|
392
|
+
}
|
380
393
|
export interface AutoModerationActionExecutionEventFields {
|
381
394
|
guildID: snowflake;
|
382
395
|
action: AutoModerationAction;
|
package/dist/lib/types/poll.d.ts
CHANGED
@@ -13,8 +13,8 @@ export interface RawPoll {
|
|
13
13
|
export interface RawPollCreateParams {
|
14
14
|
question: RawPollMedia;
|
15
15
|
answers: Array<RawPollAnswer>;
|
16
|
-
duration
|
17
|
-
allow_multiselect
|
16
|
+
duration?: number;
|
17
|
+
allow_multiselect?: boolean;
|
18
18
|
layout_type?: LayoutType;
|
19
19
|
}
|
20
20
|
/** https://discord.com/developers/docs/resources/poll#poll-media-object-poll-media-object-structure */
|
@@ -49,8 +49,8 @@ export interface Poll {
|
|
49
49
|
export interface PollCreateParams {
|
50
50
|
question: PollMedia;
|
51
51
|
answers: Array<PollAnswer>;
|
52
|
-
duration
|
53
|
-
allowMultiselect
|
52
|
+
duration?: number;
|
53
|
+
allowMultiselect?: boolean;
|
54
54
|
layoutType?: LayoutType;
|
55
55
|
}
|
56
56
|
export interface PollMedia {
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import type { snowflake } from "./common";
|
2
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload */
|
3
|
+
export interface RawVoiceIdentifyPayload {
|
4
|
+
server_id: snowflake;
|
5
|
+
user_id: snowflake;
|
6
|
+
session_id: string;
|
7
|
+
token: string;
|
8
|
+
}
|
9
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-ready-payload */
|
10
|
+
export interface RawVoiceReadyPayload {
|
11
|
+
ssrc: number;
|
12
|
+
ip: string;
|
13
|
+
port: number;
|
14
|
+
modes: Array<string>;
|
15
|
+
}
|
16
|
+
/** https://discord.com/developers/docs/topics/voice-connections#resuming-voice-connection-example-resume-connection-payload */
|
17
|
+
export interface RawResumeConnectionPayload {
|
18
|
+
server_id: snowflake;
|
19
|
+
session_id: string;
|
20
|
+
token: string;
|
21
|
+
}
|
22
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-select-protocol-payload */
|
23
|
+
export interface RawSelectProtocolPayload {
|
24
|
+
protocol: string;
|
25
|
+
data: {
|
26
|
+
address: string;
|
27
|
+
port: number;
|
28
|
+
mode: string;
|
29
|
+
};
|
30
|
+
}
|
31
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-session-description-payload */
|
32
|
+
export interface RawSessionDescriptionPayload {
|
33
|
+
mode: string;
|
34
|
+
secret_key: Array<number>;
|
35
|
+
}
|
36
|
+
export interface VoiceIdentifyPayload {
|
37
|
+
serverID: snowflake;
|
38
|
+
userID: snowflake;
|
39
|
+
sessionID: string;
|
40
|
+
token: string;
|
41
|
+
}
|
42
|
+
export interface VoiceReadyPayload {
|
43
|
+
ssrc: number;
|
44
|
+
ip: string;
|
45
|
+
port: number;
|
46
|
+
modes: Array<string>;
|
47
|
+
}
|
48
|
+
export interface ResumeConnectionPayload {
|
49
|
+
serverID: snowflake;
|
50
|
+
sessionID: string;
|
51
|
+
token: string;
|
52
|
+
}
|
53
|
+
export interface SelectProtocolPayload {
|
54
|
+
protocol: string;
|
55
|
+
data: {
|
56
|
+
address: string;
|
57
|
+
port: number;
|
58
|
+
mode: string;
|
59
|
+
};
|
60
|
+
}
|
61
|
+
export interface SessionDescriptionPayload {
|
62
|
+
mode: string;
|
63
|
+
secretKey: Array<number>;
|
64
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
import WebSocket from "ws";
|
3
|
+
import type { snowflake } from "../types/common";
|
4
|
+
import EventEmitter from "node:events";
|
5
|
+
import type { ResumeConnectionPayload, SelectProtocolPayload, SessionDescriptionPayload, VoiceIdentifyPayload, VoiceReadyPayload } from "../types/voice-connections";
|
6
|
+
export declare class VoiceConnection extends EventEmitter {
|
7
|
+
ws: WebSocket;
|
8
|
+
endpoint: string;
|
9
|
+
serverID: snowflake;
|
10
|
+
userID: snowflake;
|
11
|
+
sessionID: string;
|
12
|
+
token: string;
|
13
|
+
private heartbeatInterval;
|
14
|
+
ssrc: number;
|
15
|
+
constructor(endpoint: string, options: VoiceIdentifyPayload);
|
16
|
+
/** https://discord.com/developers/docs/topics/voice-connections#connecting-to-voice */
|
17
|
+
connect(): void;
|
18
|
+
/** https://discord.com/developers/docs/topics/gateway#connections */
|
19
|
+
disconnect(): void;
|
20
|
+
/** https://discord.com/developers/docs/topics/voice-connections#heartbeating */
|
21
|
+
heartbeat(): void;
|
22
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload */
|
23
|
+
identify(options: VoiceIdentifyPayload): void;
|
24
|
+
private onWebSocketOpen;
|
25
|
+
private onWebSocketMessage;
|
26
|
+
private onWebSocketError;
|
27
|
+
private onWebSocketClose;
|
28
|
+
/** https://discord.com/developers/docs/topics/voice-connections#resuming-voice-connection */
|
29
|
+
resume(options: ResumeConnectionPayload): void;
|
30
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection */
|
31
|
+
selectProtocol(options: SelectProtocolPayload): void;
|
32
|
+
/** https://discord.com/developers/docs/topics/voice-connections#speaking */
|
33
|
+
speaking(speaking: number): void;
|
34
|
+
}
|
35
|
+
export declare interface VoiceConnection extends EventEmitter {
|
36
|
+
addListener<K extends keyof VoiceConnectionEvents>(eventName: K, listener: (...args: VoiceConnectionEvents[K]) => void): this;
|
37
|
+
emit<K extends keyof VoiceConnectionEvents>(eventName: K, ...args: VoiceConnectionEvents[K]): boolean;
|
38
|
+
listenerCount(eventName: keyof VoiceConnectionEvents): number;
|
39
|
+
listeners(eventName: keyof VoiceConnectionEvents): Array<Function>;
|
40
|
+
off<K extends keyof VoiceConnectionEvents>(eventName: K, listener: (...args: VoiceConnectionEvents[K]) => void): this;
|
41
|
+
on<K extends keyof VoiceConnectionEvents>(eventName: K, listener: (...args: VoiceConnectionEvents[K]) => void): this;
|
42
|
+
once<K extends keyof VoiceConnectionEvents>(eventName: K, listener: (...args: VoiceConnectionEvents[K]) => void): this;
|
43
|
+
prependListener<K extends keyof VoiceConnectionEvents>(eventName: K, listener: (...args: VoiceConnectionEvents[K]) => void): this;
|
44
|
+
prependOnceListener<K extends keyof VoiceConnectionEvents>(eventName: K, listener: (...args: VoiceConnectionEvents[K]) => void): this;
|
45
|
+
rawListeners(eventName: keyof VoiceConnectionEvents): Array<Function>;
|
46
|
+
removeAllListeners(event?: keyof VoiceConnectionEvents): this;
|
47
|
+
removeListener<K extends keyof VoiceConnectionEvents>(eventName: K, listener: (...args: VoiceConnectionEvents[K]) => void): this;
|
48
|
+
}
|
49
|
+
export interface VoiceConnectionEvents {
|
50
|
+
ready: [voiceServer: VoiceReadyPayload];
|
51
|
+
sessionDescription: [session: SessionDescriptionPayload];
|
52
|
+
speaking: [speaking: number];
|
53
|
+
heartbeatACK: [heartbeat: number];
|
54
|
+
hello: [];
|
55
|
+
resumed: [];
|
56
|
+
clientDisconnect: [];
|
57
|
+
}
|
@@ -0,0 +1,150 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.VoiceConnection = void 0;
|
7
|
+
const ws_1 = __importDefault(require("ws"));
|
8
|
+
const constants_1 = require("../constants");
|
9
|
+
const utils_1 = require("../utils");
|
10
|
+
const node_events_1 = __importDefault(require("node:events"));
|
11
|
+
class VoiceConnection extends node_events_1.default {
|
12
|
+
ws;
|
13
|
+
endpoint;
|
14
|
+
serverID;
|
15
|
+
userID;
|
16
|
+
sessionID;
|
17
|
+
token;
|
18
|
+
heartbeatInterval;
|
19
|
+
ssrc;
|
20
|
+
constructor(endpoint, options) {
|
21
|
+
super();
|
22
|
+
this.ws = new ws_1.default(`wss://${endpoint}?v=4`);
|
23
|
+
this.endpoint = endpoint;
|
24
|
+
this.serverID = options.serverID;
|
25
|
+
this.userID = options.userID;
|
26
|
+
this.sessionID = options.sessionID;
|
27
|
+
this.token = options.token;
|
28
|
+
}
|
29
|
+
/** https://discord.com/developers/docs/topics/voice-connections#connecting-to-voice */
|
30
|
+
connect() {
|
31
|
+
this.ws.on("open", () => this.onWebSocketOpen());
|
32
|
+
this.ws.on("message", (data) => this.onWebSocketMessage(data));
|
33
|
+
this.ws.on("error", (err) => this.onWebSocketError(err));
|
34
|
+
this.ws.on("close", (code, reason) => this.onWebSocketClose(code, reason));
|
35
|
+
}
|
36
|
+
/** https://discord.com/developers/docs/topics/gateway#connections */
|
37
|
+
disconnect() {
|
38
|
+
if (this.heartbeatInterval) {
|
39
|
+
clearInterval(this.heartbeatInterval);
|
40
|
+
this.heartbeatInterval = null;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
/** https://discord.com/developers/docs/topics/voice-connections#heartbeating */
|
44
|
+
heartbeat() {
|
45
|
+
this.ws.send(JSON.stringify({
|
46
|
+
op: constants_1.VoiceOPCodes.Heartbeat,
|
47
|
+
d: Date.now(),
|
48
|
+
}));
|
49
|
+
}
|
50
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload */
|
51
|
+
identify(options) {
|
52
|
+
this.ws.send(JSON.stringify({
|
53
|
+
op: constants_1.VoiceOPCodes.Identify,
|
54
|
+
d: {
|
55
|
+
server_id: options.serverID,
|
56
|
+
user_id: options.userID,
|
57
|
+
session_id: options.sessionID,
|
58
|
+
token: options.token,
|
59
|
+
},
|
60
|
+
}));
|
61
|
+
}
|
62
|
+
onWebSocketOpen() {
|
63
|
+
this.identify({
|
64
|
+
serverID: this.serverID,
|
65
|
+
userID: this.userID,
|
66
|
+
sessionID: this.sessionID,
|
67
|
+
token: this.token,
|
68
|
+
});
|
69
|
+
}
|
70
|
+
onWebSocketMessage(data) {
|
71
|
+
const packet = JSON.parse(data.toString());
|
72
|
+
switch (packet.op) {
|
73
|
+
case constants_1.VoiceOPCodes.Ready:
|
74
|
+
{
|
75
|
+
this.ssrc = packet.d.ssrc;
|
76
|
+
this.emit("ready", {
|
77
|
+
ssrc: packet.d.ssrc,
|
78
|
+
ip: packet.d.ip,
|
79
|
+
port: packet.d.port,
|
80
|
+
modes: packet.d.modes,
|
81
|
+
});
|
82
|
+
}
|
83
|
+
break;
|
84
|
+
case constants_1.VoiceOPCodes.SessionDescription:
|
85
|
+
this.emit("sessionDescription", {
|
86
|
+
mode: packet.d.mode,
|
87
|
+
secretKey: packet.d.secret_key,
|
88
|
+
});
|
89
|
+
break;
|
90
|
+
case constants_1.VoiceOPCodes.Speaking:
|
91
|
+
this.emit("speaking", packet.d.speaking);
|
92
|
+
break;
|
93
|
+
case constants_1.VoiceOPCodes.HeartbeatACK:
|
94
|
+
this.emit("heartbeatACK", packet.d);
|
95
|
+
break;
|
96
|
+
case constants_1.VoiceOPCodes.Hello:
|
97
|
+
{
|
98
|
+
this.heartbeatInterval = setInterval(() => this.heartbeat(), packet.d.heartbeat_interval);
|
99
|
+
this.emit("hello");
|
100
|
+
}
|
101
|
+
break;
|
102
|
+
case constants_1.VoiceOPCodes.Resumed:
|
103
|
+
this.emit("resumed");
|
104
|
+
break;
|
105
|
+
case constants_1.VoiceOPCodes.ClientDisconnect:
|
106
|
+
this.emit("clientDisconnect");
|
107
|
+
break;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
onWebSocketError(err) {
|
111
|
+
throw err;
|
112
|
+
}
|
113
|
+
onWebSocketClose(code, reason) {
|
114
|
+
if (code === 1000)
|
115
|
+
return;
|
116
|
+
if (code === constants_1.VoiceCloseEventCodes.Disconnect)
|
117
|
+
return this.disconnect();
|
118
|
+
throw new utils_1.GatewayError(`[${code}] ${reason}`);
|
119
|
+
}
|
120
|
+
/** https://discord.com/developers/docs/topics/voice-connections#resuming-voice-connection */
|
121
|
+
resume(options) {
|
122
|
+
this.ws.send(JSON.stringify({
|
123
|
+
op: constants_1.VoiceOPCodes.Resume,
|
124
|
+
d: {
|
125
|
+
server_id: options.serverID,
|
126
|
+
session_id: options.sessionID,
|
127
|
+
token: options.token,
|
128
|
+
},
|
129
|
+
}));
|
130
|
+
}
|
131
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection */
|
132
|
+
selectProtocol(options) {
|
133
|
+
this.ws.send(JSON.stringify({
|
134
|
+
op: constants_1.VoiceOPCodes.SelectProtocol,
|
135
|
+
d: options,
|
136
|
+
}));
|
137
|
+
}
|
138
|
+
/** https://discord.com/developers/docs/topics/voice-connections#speaking */
|
139
|
+
speaking(speaking) {
|
140
|
+
this.ws.send(JSON.stringify({
|
141
|
+
op: constants_1.VoiceOPCodes.Speaking,
|
142
|
+
d: {
|
143
|
+
speaking,
|
144
|
+
delay: 0,
|
145
|
+
ssrc: this.ssrc,
|
146
|
+
},
|
147
|
+
}));
|
148
|
+
}
|
149
|
+
}
|
150
|
+
exports.VoiceConnection = VoiceConnection;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import type { snowflake } from "../types/common";
|
2
|
+
import type { ResumeConnectionPayload, SelectProtocolPayload, VoiceIdentifyPayload } from "../types/voice-connections";
|
3
|
+
import { VoiceConnection } from ".";
|
4
|
+
export declare class VoiceConnectionManager extends Map<snowflake, VoiceConnection> {
|
5
|
+
/** https://discord.com/developers/docs/topics/voice-connections#connecting-to-voice */
|
6
|
+
connect(endpoint: string, options: VoiceIdentifyPayload): VoiceConnection;
|
7
|
+
/** https://discord.com/developers/docs/topics/gateway#connections */
|
8
|
+
disconnect(guildID: snowflake): void;
|
9
|
+
/** https://discord.com/developers/docs/topics/voice-connections#heartbeating */
|
10
|
+
heartbeat(guildID: snowflake): void;
|
11
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload */
|
12
|
+
identify(guildID: snowflake, options: VoiceIdentifyPayload): void;
|
13
|
+
/** https://discord.com/developers/docs/topics/voice-connections#resuming-voice-connection */
|
14
|
+
resume(guildID: snowflake, options: ResumeConnectionPayload): void;
|
15
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection */
|
16
|
+
selectProtocol(guildID: snowflake, options: SelectProtocolPayload): void;
|
17
|
+
/** https://discord.com/developers/docs/topics/voice-connections#speaking */
|
18
|
+
speaking(guildID: snowflake, speaking: number): void;
|
19
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.VoiceConnectionManager = void 0;
|
4
|
+
const _1 = require(".");
|
5
|
+
class VoiceConnectionManager extends Map {
|
6
|
+
/** https://discord.com/developers/docs/topics/voice-connections#connecting-to-voice */
|
7
|
+
connect(endpoint, options) {
|
8
|
+
let voiceConnection = new _1.VoiceConnection(endpoint, options);
|
9
|
+
if (!this.has(options.serverID)) {
|
10
|
+
this.set(options.serverID, voiceConnection);
|
11
|
+
voiceConnection.connect();
|
12
|
+
}
|
13
|
+
else {
|
14
|
+
this.disconnect(options.serverID);
|
15
|
+
this.set(options.serverID, voiceConnection);
|
16
|
+
}
|
17
|
+
return voiceConnection;
|
18
|
+
}
|
19
|
+
/** https://discord.com/developers/docs/topics/gateway#connections */
|
20
|
+
disconnect(guildID) {
|
21
|
+
if (this.has(guildID)) {
|
22
|
+
this.get(guildID).disconnect();
|
23
|
+
this.delete(guildID);
|
24
|
+
}
|
25
|
+
}
|
26
|
+
/** https://discord.com/developers/docs/topics/voice-connections#heartbeating */
|
27
|
+
heartbeat(guildID) {
|
28
|
+
if (this.has(guildID)) {
|
29
|
+
this.get(guildID).heartbeat();
|
30
|
+
}
|
31
|
+
}
|
32
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload */
|
33
|
+
identify(guildID, options) {
|
34
|
+
if (this.has(guildID)) {
|
35
|
+
this.get(guildID).identify({
|
36
|
+
serverID: options.serverID,
|
37
|
+
userID: options.userID,
|
38
|
+
sessionID: options.sessionID,
|
39
|
+
token: options.token,
|
40
|
+
});
|
41
|
+
}
|
42
|
+
}
|
43
|
+
/** https://discord.com/developers/docs/topics/voice-connections#resuming-voice-connection */
|
44
|
+
resume(guildID, options) {
|
45
|
+
if (this.has(guildID)) {
|
46
|
+
this.get(guildID).resume({
|
47
|
+
serverID: options.serverID,
|
48
|
+
sessionID: options.sessionID,
|
49
|
+
token: options.token,
|
50
|
+
});
|
51
|
+
}
|
52
|
+
}
|
53
|
+
/** https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection */
|
54
|
+
selectProtocol(guildID, options) {
|
55
|
+
if (this.has(guildID)) {
|
56
|
+
this.get(guildID).selectProtocol(options);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
/** https://discord.com/developers/docs/topics/voice-connections#speaking */
|
60
|
+
speaking(guildID, speaking) {
|
61
|
+
if (this.has(guildID)) {
|
62
|
+
this.get(guildID).speaking(speaking);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
exports.VoiceConnectionManager = VoiceConnectionManager;
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
|
+
};
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
17
|
+
__exportStar(require("./VoiceConnection"), exports);
|
18
|
+
__exportStar(require("./VoiceConnectionManager"), exports);
|
package/dist/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "disgroove",
|
3
|
-
"version": "2.2.
|
3
|
+
"version": "2.2.2-dev.23938d8",
|
4
4
|
"description": "A module to interface with Discord",
|
5
5
|
"main": "./dist/lib/index.js",
|
6
6
|
"types": "./dist/lib/index.d.ts",
|
@@ -25,9 +25,9 @@
|
|
25
25
|
},
|
26
26
|
"homepage": "https://github.com/XenKys/disgroove#readme",
|
27
27
|
"devDependencies": {
|
28
|
-
"@types/node": "^20.14.
|
28
|
+
"@types/node": "^20.14.9",
|
29
29
|
"@types/ws": "^8.5.10",
|
30
|
-
"typescript": "^5.5.
|
30
|
+
"typescript": "^5.5.3"
|
31
31
|
},
|
32
32
|
"dependencies": {
|
33
33
|
"ws": "^8.17.1"
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "disgroove",
|
3
|
-
"version": "2.2.
|
3
|
+
"version": "2.2.2-dev.23938d8",
|
4
4
|
"description": "A module to interface with Discord",
|
5
5
|
"main": "./dist/lib/index.js",
|
6
6
|
"types": "./dist/lib/index.d.ts",
|
@@ -25,9 +25,9 @@
|
|
25
25
|
},
|
26
26
|
"homepage": "https://github.com/XenKys/disgroove#readme",
|
27
27
|
"devDependencies": {
|
28
|
-
"@types/node": "^20.14.
|
28
|
+
"@types/node": "^20.14.9",
|
29
29
|
"@types/ws": "^8.5.10",
|
30
|
-
"typescript": "^5.5.
|
30
|
+
"typescript": "^5.5.3"
|
31
31
|
},
|
32
32
|
"dependencies": {
|
33
33
|
"ws": "^8.17.1"
|