@discordjs/voice 0.9.0-dev.1648166871.cedd053 → 0.9.0-dev.1649030902-5748dbe

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/dist/index.js CHANGED
@@ -1,10 +1,2107 @@
1
- var ze=Object.create;var A=Object.defineProperty;var Ye=Object.getOwnPropertyDescriptor;var Xe=Object.getOwnPropertyNames;var Ze=Object.getPrototypeOf,Qe=Object.prototype.hasOwnProperty;var et=(i,e,t)=>e in i?A(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var ne=i=>A(i,"__esModule",{value:!0}),r=(i,e)=>A(i,"name",{value:e,configurable:!0});var tt=(i,e)=>()=>(e||i((e={exports:{}}).exports,e),e.exports),it=(i,e)=>{for(var t in e)A(i,t,{get:e[t],enumerable:!0})},re=(i,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Xe(e))!Qe.call(i,s)&&(t||s!=="default")&&A(i,s,{get:()=>e[s],enumerable:!(o=Ye(e,s))||o.enumerable});return i},I=(i,e)=>re(ne(A(i!=null?ze(Ze(i)):{},"default",!e&&i&&i.__esModule?{get:()=>i.default,enumerable:!0}:{value:i,enumerable:!0})),i),ot=(i=>(e,t)=>i&&i.get(e)||(t=re(ne({}),e,1),i&&i.set(e,t),t))(typeof WeakMap!="undefined"?new WeakMap:0);var a=(i,e,t)=>(et(i,typeof e!="symbol"?e+"":e,t),t);var je=tt((qi,Pt)=>{Pt.exports={name:"@discordjs/voice",version:"0.9.0-dev",description:"Implementation of the Discord Voice API for node.js",scripts:{build:"tsup && node scripts/postbuild.mjs",test:"jest --pass-with-no-tests --collect-coverage",lint:"prettier --check . && eslint src __tests__ --ext mjs,js,ts",format:"prettier --write . && eslint src __tests__ --ext mjs,js,ts --fix",docs:"typedoc --json docs/typedoc-out.json src/index.ts && node scripts/docs.mjs",prepublishOnly:"yarn build && yarn lint && yarn test",changelog:"git cliff --prepend ./CHANGELOG.md -l -c ./cliff.toml -r ../../ --include-path 'packages/voice/*'"},main:"./dist/index.js",module:"./dist/index.mjs",typings:"./dist/index.d.ts",exports:{import:"./dist/index.mjs",require:"./dist/index.js",types:"./dist/index.d.ts"},directories:{lib:"src",test:"__tests__"},files:["dist"],contributors:["Crawl <icrawltogo@gmail.com>","Amish Shah <amishshah.2k@gmail.com>","SpaceEEC <spaceeec@yahoo.com>","Vlad Frangu <kingdgrizzle@gmail.com>","Antonio Roman <kyradiscord@gmail.com>"],license:"Apache-2.0",keywords:["discord","discord.js","audio","voice","streaming"],repository:{type:"git",url:"git+https://github.com/discordjs/discord.js.git"},bugs:{url:"https://github.com/discordjs/discord.js/issues"},homepage:"https://discord.js.org",dependencies:{"@types/ws":"^8.2.2","discord-api-types":"^0.29.0","prism-media":"^1.3.2","tiny-typed-emitter":"^2.1.0",tslib:"^2.3.1",ws:"^8.5.0"},devDependencies:{"@babel/core":"^7.17.2","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@discordjs/ts-docgen":"^0.3.4","@types/jest":"^27.4.0","@types/node":"^16.11.24","@typescript-eslint/eslint-plugin":"^5.11.0","@typescript-eslint/parser":"^5.11.0",eslint:"^8.9.0","eslint-config-marine":"^9.3.2","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^4.0.0",jest:"^27.5.1","jest-websocket-mock":"^2.3.0","mock-socket":"^9.1.2",prettier:"^2.5.1",tsup:"^5.11.13",tweetnacl:"^1.0.3",typedoc:"^0.22.11",typescript:"^4.5.5"},engines:{node:">=16.9.0"},publishConfig:{access:"public"}}});var Dt={};it(Dt,{AudioPlayer:()=>N,AudioPlayerError:()=>w,AudioPlayerStatus:()=>Z,AudioReceiveStream:()=>B,AudioResource:()=>R,EndBehaviorType:()=>Ee,NoSubscriberBehavior:()=>X,PlayerSubscription:()=>x,SSRCMap:()=>M,SpeakingMap:()=>D,StreamType:()=>E,VoiceConnection:()=>W,VoiceConnectionDisconnectReason:()=>te,VoiceConnectionStatus:()=>L,VoiceReceiver:()=>U,createAudioPlayer:()=>Ve,createAudioResource:()=>Fe,createDefaultAudioReceiveStreamOptions:()=>Q,demuxProbe:()=>Vt,entersState:()=>xt,generateDependencyReport:()=>wt,getGroups:()=>ce,getVoiceConnection:()=>_,getVoiceConnections:()=>j,joinVoiceChannel:()=>yt,validateDiscordOpusHead:()=>qe});var ae=require("discord-api-types/v10");function P(i){return{op:ae.GatewayOpcodes.VoiceStateUpdate,d:{guild_id:i.guildId,channel_id:i.channelId,self_deaf:i.selfDeaf,self_mute:i.selfMute}}}r(P,"createJoinVoiceChannelPayload");var T=new Map;T.set("default",new Map);function st(i){let e=T.get(i);if(e)return e;let t=new Map;return T.set(i,t),t}r(st,"getOrCreateGroup");function ce(){return T}r(ce,"getGroups");function j(i="default"){return T.get(i)}r(j,"getVoiceConnections");function _(i,e="default"){return j(e)?.get(i)}r(_,"getVoiceConnection");function de(i){return j(i.joinConfig.group)?.delete(i.joinConfig.guildId)}r(de,"untrackVoiceConnection");function ue(i){return st(i.joinConfig.group).set(i.joinConfig.guildId,i)}r(ue,"trackVoiceConnection");var nt=20,K,v=-1,S=[];function pe(){if(v===-1)return;v+=nt;let i=S.filter(e=>e.checkPlayable());i.forEach(e=>e._stepDispatch()),le(i)}r(pe,"audioCycleStep");function le(i){let e=i.shift();if(!e){v!==-1&&(K=setTimeout(()=>pe(),v-Date.now()));return}e._stepPrepare(),setImmediate(()=>le(i))}r(le,"prepareNextAudioFrame");function rt(i){return S.includes(i)}r(rt,"hasAudioPlayer");function fe(i){return rt(i)||(S.push(i),S.length===1&&(v=Date.now(),setImmediate(()=>pe()))),i}r(fe,"addAudioPlayer");function he(i){let e=S.indexOf(i);e!==-1&&(S.splice(e,1),S.length===0&&(v=-1,typeof K!="undefined"&&clearTimeout(K)))}r(he,"deleteAudioPlayer");var h=require("discord-api-types/voice/v4");var me=require("dgram"),ge=require("net"),ye=require("tiny-typed-emitter");function at(i){let e=Buffer.from(i),t=e.slice(8,e.indexOf(0,8)).toString("utf-8");if(!(0,ge.isIPv4)(t))throw new Error("Malformed IP address");let o=e.readUInt16BE(e.length-2);return{ip:t,port:o}}r(at,"parseLocalPacket");var ct=5e3,dt=12,ut=2**32-1,G=class extends ye.TypedEmitter{constructor(e,t=!1){super();a(this,"socket");a(this,"remote");a(this,"keepAlives");a(this,"keepAliveCounter",0);a(this,"keepAliveBuffer");a(this,"keepAliveInterval");a(this,"ping");a(this,"debug");this.socket=(0,me.createSocket)("udp4"),this.socket.on("error",o=>this.emit("error",o)),this.socket.on("message",o=>this.onMessage(o)),this.socket.on("close",()=>this.emit("close")),this.remote=e,this.keepAlives=[],this.keepAliveBuffer=Buffer.alloc(8),this.keepAliveInterval=setInterval(()=>this.keepAlive(),ct),setImmediate(()=>this.keepAlive()),this.debug=t?o=>this.emit("debug",o):null}onMessage(e){if(e.length===8){let t=e.readUInt32LE(0),o=this.keepAlives.findIndex(({value:s})=>s===t);if(o===-1)return;this.ping=Date.now()-this.keepAlives[o].timestamp,this.keepAlives.splice(0,o)}this.emit("message",e)}keepAlive(){if(this.keepAlives.length>=dt){this.debug?.("UDP socket has not received enough responses from Discord - closing socket"),this.destroy();return}this.keepAliveBuffer.writeUInt32LE(this.keepAliveCounter,0),this.send(this.keepAliveBuffer),this.keepAlives.push({value:this.keepAliveCounter,timestamp:Date.now()}),this.keepAliveCounter++,this.keepAliveCounter>ut&&(this.keepAliveCounter=0)}send(e){return this.socket.send(e,this.remote.port,this.remote.ip)}destroy(){try{this.socket.close()}catch{}clearInterval(this.keepAliveInterval)}performIPDiscovery(e){return new Promise((t,o)=>{let s=r(c=>{try{if(c.readUInt16BE(0)!==2)return;let u=at(c);this.socket.off("message",s),t(u)}catch{}},"listener");this.socket.on("message",s),this.socket.once("close",()=>o(new Error("Cannot perform IP discovery - socket closed")));let n=Buffer.alloc(74);n.writeUInt16BE(1,0),n.writeUInt16BE(70,2),n.writeUInt32BE(e,4),this.send(n)})}};r(G,"VoiceUDPSocket");var z=require("discord-api-types/voice/v4"),be=I(require("ws")),Se=require("tiny-typed-emitter"),H=class extends Se.TypedEmitter{constructor(e,t){super();a(this,"heartbeatInterval");a(this,"lastHeartbeatAck");a(this,"lastHeartbeatSend");a(this,"missedHeartbeats",0);a(this,"ping");a(this,"debug");a(this,"ws");this.ws=new be.default(e),this.ws.onmessage=o=>this.onMessage(o),this.ws.onopen=o=>this.emit("open",o),this.ws.onerror=o=>this.emit("error",o instanceof Error?o:o.error),this.ws.onclose=o=>this.emit("close",o),this.lastHeartbeatAck=0,this.lastHeartbeatSend=0,this.debug=t?o=>this.emit("debug",o):null}destroy(){try{this.debug?.("destroyed"),this.setHeartbeatInterval(-1),this.ws.close(1e3)}catch(e){let t=e;this.emit("error",t)}}onMessage(e){if(typeof e.data!="string")return;this.debug?.(`<< ${e.data}`);let t;try{t=JSON.parse(e.data)}catch(o){let s=o;this.emit("error",s);return}t.op===z.VoiceOpcodes.HeartbeatAck&&(this.lastHeartbeatAck=Date.now(),this.missedHeartbeats=0,this.ping=this.lastHeartbeatAck-this.lastHeartbeatSend),this.emit("packet",t)}sendPacket(e){try{let t=JSON.stringify(e);return this.debug?.(`>> ${t}`),this.ws.send(t)}catch(t){let o=t;this.emit("error",o)}}sendHeartbeat(){this.lastHeartbeatSend=Date.now(),this.missedHeartbeats++;let e=this.lastHeartbeatSend;return this.sendPacket({op:z.VoiceOpcodes.Heartbeat,d:e})}setHeartbeatInterval(e){typeof this.heartbeatInterval!="undefined"&&clearInterval(this.heartbeatInterval),e>0&&(this.heartbeatInterval=setInterval(()=>{this.lastHeartbeatSend!==0&&this.missedHeartbeats>=3&&(this.ws.close(),this.setHeartbeatInterval(-1)),this.sendHeartbeat()},e))}};r(H,"VoiceWebSocket");var Ce={sodium:i=>({open:i.api.crypto_secretbox_open_easy,close:i.api.crypto_secretbox_easy,random:(e,t)=>(t||(t=Buffer.allocUnsafe(e)),i.api.randombytes_buf(t),t)}),"libsodium-wrappers":i=>({open:i.crypto_secretbox_open_easy,close:i.crypto_secretbox_easy,random:e=>i.randombytes_buf(e)}),tweetnacl:i=>({open:i.secretbox.open,close:i.secretbox,random:e=>i.randomBytes(e)})},Y=r(()=>{throw new Error(`Cannot play audio as no valid encryption package is installed.
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
10
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
11
+ var __commonJS = (cb, mod) => function __require() {
12
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
13
+ };
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __reExport = (target, module2, copyDefault, desc) => {
19
+ if (module2 && typeof module2 === "object" || typeof module2 === "function") {
20
+ for (let key of __getOwnPropNames(module2))
21
+ if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default"))
22
+ __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
23
+ }
24
+ return target;
25
+ };
26
+ var __toESM = (module2, isNodeMode) => {
27
+ return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", !isNodeMode && module2 && module2.__esModule ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
28
+ };
29
+ var __toCommonJS = /* @__PURE__ */ ((cache) => {
30
+ return (module2, temp) => {
31
+ return cache && cache.get(module2) || (temp = __reExport(__markAsModule({}), module2, 1), cache && cache.set(module2, temp), temp);
32
+ };
33
+ })(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0);
34
+ var __publicField = (obj, key, value) => {
35
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
36
+ return value;
37
+ };
38
+
39
+ // package.json
40
+ var require_package = __commonJS({
41
+ "package.json"(exports, module2) {
42
+ module2.exports = {
43
+ name: "@discordjs/voice",
44
+ version: "0.9.0-dev",
45
+ description: "Implementation of the Discord Voice API for node.js",
46
+ scripts: {
47
+ build: "tsup && node scripts/postbuild.mjs",
48
+ test: "jest --pass-with-no-tests --collect-coverage",
49
+ lint: "prettier --check . && eslint src __tests__ --ext mjs,js,ts",
50
+ format: "prettier --write . && eslint src __tests__ --ext mjs,js,ts --fix",
51
+ docs: "typedoc --json docs/typedoc-out.json src/index.ts && node scripts/docs.mjs",
52
+ prepublishOnly: "yarn build && yarn lint && yarn test",
53
+ changelog: "git cliff --prepend ./CHANGELOG.md -l -c ./cliff.toml -r ../../ --include-path 'packages/voice/*'"
54
+ },
55
+ main: "./dist/index.js",
56
+ module: "./dist/index.mjs",
57
+ typings: "./dist/index.d.ts",
58
+ exports: {
59
+ import: "./dist/index.mjs",
60
+ require: "./dist/index.js",
61
+ types: "./dist/index.d.ts"
62
+ },
63
+ directories: {
64
+ lib: "src",
65
+ test: "__tests__"
66
+ },
67
+ files: [
68
+ "dist"
69
+ ],
70
+ contributors: [
71
+ "Crawl <icrawltogo@gmail.com>",
72
+ "Amish Shah <amishshah.2k@gmail.com>",
73
+ "SpaceEEC <spaceeec@yahoo.com>",
74
+ "Vlad Frangu <kingdgrizzle@gmail.com>",
75
+ "Antonio Roman <kyradiscord@gmail.com>"
76
+ ],
77
+ license: "Apache-2.0",
78
+ keywords: [
79
+ "discord",
80
+ "discord.js",
81
+ "audio",
82
+ "voice",
83
+ "streaming"
84
+ ],
85
+ repository: {
86
+ type: "git",
87
+ url: "git+https://github.com/discordjs/discord.js.git"
88
+ },
89
+ bugs: {
90
+ url: "https://github.com/discordjs/discord.js/issues"
91
+ },
92
+ homepage: "https://discord.js.org",
93
+ dependencies: {
94
+ "@types/ws": "^8.2.2",
95
+ "discord-api-types": "^0.29.0",
96
+ "prism-media": "^1.3.2",
97
+ "tiny-typed-emitter": "^2.1.0",
98
+ tslib: "^2.3.1",
99
+ ws: "^8.5.0"
100
+ },
101
+ devDependencies: {
102
+ "@babel/core": "^7.17.2",
103
+ "@babel/preset-env": "^7.16.11",
104
+ "@babel/preset-typescript": "^7.16.7",
105
+ "@discordjs/ts-docgen": "^0.3.4",
106
+ "@types/jest": "^27.4.0",
107
+ "@types/node": "^16.11.24",
108
+ "@typescript-eslint/eslint-plugin": "^5.11.0",
109
+ "@typescript-eslint/parser": "^5.11.0",
110
+ eslint: "^8.9.0",
111
+ "eslint-config-marine": "^9.3.2",
112
+ "eslint-config-prettier": "^8.3.0",
113
+ "eslint-plugin-prettier": "^4.0.0",
114
+ jest: "^27.5.1",
115
+ "jest-websocket-mock": "^2.3.0",
116
+ "mock-socket": "^9.1.2",
117
+ prettier: "^2.5.1",
118
+ tsup: "^5.11.13",
119
+ tweetnacl: "^1.0.3",
120
+ typedoc: "^0.22.11",
121
+ typescript: "^4.5.5"
122
+ },
123
+ engines: {
124
+ node: ">=16.9.0"
125
+ },
126
+ publishConfig: {
127
+ access: "public"
128
+ }
129
+ };
130
+ }
131
+ });
132
+
133
+ // src/index.ts
134
+ var src_exports = {};
135
+ __export(src_exports, {
136
+ AudioPlayer: () => AudioPlayer,
137
+ AudioPlayerError: () => AudioPlayerError,
138
+ AudioPlayerStatus: () => AudioPlayerStatus,
139
+ AudioReceiveStream: () => AudioReceiveStream,
140
+ AudioResource: () => AudioResource,
141
+ EndBehaviorType: () => EndBehaviorType,
142
+ NoSubscriberBehavior: () => NoSubscriberBehavior,
143
+ PlayerSubscription: () => PlayerSubscription,
144
+ SSRCMap: () => SSRCMap,
145
+ SpeakingMap: () => SpeakingMap,
146
+ StreamType: () => StreamType,
147
+ VoiceConnection: () => VoiceConnection2,
148
+ VoiceConnectionDisconnectReason: () => VoiceConnectionDisconnectReason,
149
+ VoiceConnectionStatus: () => VoiceConnectionStatus,
150
+ VoiceReceiver: () => VoiceReceiver,
151
+ createAudioPlayer: () => createAudioPlayer,
152
+ createAudioResource: () => createAudioResource,
153
+ createDefaultAudioReceiveStreamOptions: () => createDefaultAudioReceiveStreamOptions,
154
+ demuxProbe: () => demuxProbe,
155
+ entersState: () => entersState,
156
+ generateDependencyReport: () => generateDependencyReport,
157
+ getGroups: () => getGroups,
158
+ getVoiceConnection: () => getVoiceConnection,
159
+ getVoiceConnections: () => getVoiceConnections,
160
+ joinVoiceChannel: () => joinVoiceChannel,
161
+ validateDiscordOpusHead: () => validateDiscordOpusHead
162
+ });
163
+
164
+ // src/DataStore.ts
165
+ var import_v10 = require("discord-api-types/v10");
166
+ function createJoinVoiceChannelPayload(config) {
167
+ return {
168
+ op: import_v10.GatewayOpcodes.VoiceStateUpdate,
169
+ d: {
170
+ guild_id: config.guildId,
171
+ channel_id: config.channelId,
172
+ self_deaf: config.selfDeaf,
173
+ self_mute: config.selfMute
174
+ }
175
+ };
176
+ }
177
+ __name(createJoinVoiceChannelPayload, "createJoinVoiceChannelPayload");
178
+ var groups = /* @__PURE__ */ new Map();
179
+ groups.set("default", /* @__PURE__ */ new Map());
180
+ function getOrCreateGroup(group) {
181
+ const existing = groups.get(group);
182
+ if (existing)
183
+ return existing;
184
+ const map = /* @__PURE__ */ new Map();
185
+ groups.set(group, map);
186
+ return map;
187
+ }
188
+ __name(getOrCreateGroup, "getOrCreateGroup");
189
+ function getGroups() {
190
+ return groups;
191
+ }
192
+ __name(getGroups, "getGroups");
193
+ function getVoiceConnections(group = "default") {
194
+ return groups.get(group);
195
+ }
196
+ __name(getVoiceConnections, "getVoiceConnections");
197
+ function getVoiceConnection(guildId, group = "default") {
198
+ return getVoiceConnections(group)?.get(guildId);
199
+ }
200
+ __name(getVoiceConnection, "getVoiceConnection");
201
+ function untrackVoiceConnection(voiceConnection) {
202
+ return getVoiceConnections(voiceConnection.joinConfig.group)?.delete(voiceConnection.joinConfig.guildId);
203
+ }
204
+ __name(untrackVoiceConnection, "untrackVoiceConnection");
205
+ function trackVoiceConnection(voiceConnection) {
206
+ return getOrCreateGroup(voiceConnection.joinConfig.group).set(voiceConnection.joinConfig.guildId, voiceConnection);
207
+ }
208
+ __name(trackVoiceConnection, "trackVoiceConnection");
209
+ var FRAME_LENGTH = 20;
210
+ var audioCycleInterval;
211
+ var nextTime = -1;
212
+ var audioPlayers = [];
213
+ function audioCycleStep() {
214
+ if (nextTime === -1)
215
+ return;
216
+ nextTime += FRAME_LENGTH;
217
+ const available = audioPlayers.filter((player) => player.checkPlayable());
218
+ available.forEach((player) => player["_stepDispatch"]());
219
+ prepareNextAudioFrame(available);
220
+ }
221
+ __name(audioCycleStep, "audioCycleStep");
222
+ function prepareNextAudioFrame(players) {
223
+ const nextPlayer = players.shift();
224
+ if (!nextPlayer) {
225
+ if (nextTime !== -1) {
226
+ audioCycleInterval = setTimeout(() => audioCycleStep(), nextTime - Date.now());
227
+ }
228
+ return;
229
+ }
230
+ nextPlayer["_stepPrepare"]();
231
+ setImmediate(() => prepareNextAudioFrame(players));
232
+ }
233
+ __name(prepareNextAudioFrame, "prepareNextAudioFrame");
234
+ function hasAudioPlayer(target) {
235
+ return audioPlayers.includes(target);
236
+ }
237
+ __name(hasAudioPlayer, "hasAudioPlayer");
238
+ function addAudioPlayer(player) {
239
+ if (hasAudioPlayer(player))
240
+ return player;
241
+ audioPlayers.push(player);
242
+ if (audioPlayers.length === 1) {
243
+ nextTime = Date.now();
244
+ setImmediate(() => audioCycleStep());
245
+ }
246
+ return player;
247
+ }
248
+ __name(addAudioPlayer, "addAudioPlayer");
249
+ function deleteAudioPlayer(player) {
250
+ const index = audioPlayers.indexOf(player);
251
+ if (index === -1)
252
+ return;
253
+ audioPlayers.splice(index, 1);
254
+ if (audioPlayers.length === 0) {
255
+ nextTime = -1;
256
+ if (typeof audioCycleInterval !== "undefined")
257
+ clearTimeout(audioCycleInterval);
258
+ }
259
+ }
260
+ __name(deleteAudioPlayer, "deleteAudioPlayer");
261
+
262
+ // src/networking/Networking.ts
263
+ var import_v42 = require("discord-api-types/voice/v4");
264
+
265
+ // src/networking/VoiceUDPSocket.ts
266
+ var import_node_dgram = require("dgram");
267
+ var import_node_net = require("net");
268
+ var import_tiny_typed_emitter = require("tiny-typed-emitter");
269
+ function parseLocalPacket(message) {
270
+ const packet = Buffer.from(message);
271
+ const ip = packet.slice(8, packet.indexOf(0, 8)).toString("utf-8");
272
+ if (!(0, import_node_net.isIPv4)(ip)) {
273
+ throw new Error("Malformed IP address");
274
+ }
275
+ const port = packet.readUInt16BE(packet.length - 2);
276
+ return { ip, port };
277
+ }
278
+ __name(parseLocalPacket, "parseLocalPacket");
279
+ var KEEP_ALIVE_INTERVAL = 5e3;
280
+ var KEEP_ALIVE_LIMIT = 12;
281
+ var MAX_COUNTER_VALUE = 2 ** 32 - 1;
282
+ var VoiceUDPSocket = class extends import_tiny_typed_emitter.TypedEmitter {
283
+ constructor(remote, debug = false) {
284
+ super();
285
+ __publicField(this, "socket");
286
+ __publicField(this, "remote");
287
+ __publicField(this, "keepAlives");
288
+ __publicField(this, "keepAliveCounter", 0);
289
+ __publicField(this, "keepAliveBuffer");
290
+ __publicField(this, "keepAliveInterval");
291
+ __publicField(this, "ping");
292
+ __publicField(this, "debug");
293
+ this.socket = (0, import_node_dgram.createSocket)("udp4");
294
+ this.socket.on("error", (error) => this.emit("error", error));
295
+ this.socket.on("message", (buffer) => this.onMessage(buffer));
296
+ this.socket.on("close", () => this.emit("close"));
297
+ this.remote = remote;
298
+ this.keepAlives = [];
299
+ this.keepAliveBuffer = Buffer.alloc(8);
300
+ this.keepAliveInterval = setInterval(() => this.keepAlive(), KEEP_ALIVE_INTERVAL);
301
+ setImmediate(() => this.keepAlive());
302
+ this.debug = debug ? (message) => this.emit("debug", message) : null;
303
+ }
304
+ onMessage(buffer) {
305
+ if (buffer.length === 8) {
306
+ const counter = buffer.readUInt32LE(0);
307
+ const index = this.keepAlives.findIndex(({ value }) => value === counter);
308
+ if (index === -1)
309
+ return;
310
+ this.ping = Date.now() - this.keepAlives[index].timestamp;
311
+ this.keepAlives.splice(0, index);
312
+ }
313
+ this.emit("message", buffer);
314
+ }
315
+ keepAlive() {
316
+ if (this.keepAlives.length >= KEEP_ALIVE_LIMIT) {
317
+ this.debug?.("UDP socket has not received enough responses from Discord - closing socket");
318
+ this.destroy();
319
+ return;
320
+ }
321
+ this.keepAliveBuffer.writeUInt32LE(this.keepAliveCounter, 0);
322
+ this.send(this.keepAliveBuffer);
323
+ this.keepAlives.push({
324
+ value: this.keepAliveCounter,
325
+ timestamp: Date.now()
326
+ });
327
+ this.keepAliveCounter++;
328
+ if (this.keepAliveCounter > MAX_COUNTER_VALUE) {
329
+ this.keepAliveCounter = 0;
330
+ }
331
+ }
332
+ send(buffer) {
333
+ return this.socket.send(buffer, this.remote.port, this.remote.ip);
334
+ }
335
+ destroy() {
336
+ try {
337
+ this.socket.close();
338
+ } catch {
339
+ }
340
+ clearInterval(this.keepAliveInterval);
341
+ }
342
+ performIPDiscovery(ssrc) {
343
+ return new Promise((resolve2, reject) => {
344
+ const listener = /* @__PURE__ */ __name((message) => {
345
+ try {
346
+ if (message.readUInt16BE(0) !== 2)
347
+ return;
348
+ const packet = parseLocalPacket(message);
349
+ this.socket.off("message", listener);
350
+ resolve2(packet);
351
+ } catch {
352
+ }
353
+ }, "listener");
354
+ this.socket.on("message", listener);
355
+ this.socket.once("close", () => reject(new Error("Cannot perform IP discovery - socket closed")));
356
+ const discoveryBuffer = Buffer.alloc(74);
357
+ discoveryBuffer.writeUInt16BE(1, 0);
358
+ discoveryBuffer.writeUInt16BE(70, 2);
359
+ discoveryBuffer.writeUInt32BE(ssrc, 4);
360
+ this.send(discoveryBuffer);
361
+ });
362
+ }
363
+ };
364
+ __name(VoiceUDPSocket, "VoiceUDPSocket");
365
+
366
+ // src/networking/VoiceWebSocket.ts
367
+ var import_v4 = require("discord-api-types/voice/v4");
368
+ var import_ws = __toESM(require("ws"));
369
+ var import_tiny_typed_emitter2 = require("tiny-typed-emitter");
370
+ var VoiceWebSocket = class extends import_tiny_typed_emitter2.TypedEmitter {
371
+ constructor(address, debug) {
372
+ super();
373
+ __publicField(this, "heartbeatInterval");
374
+ __publicField(this, "lastHeartbeatAck");
375
+ __publicField(this, "lastHeartbeatSend");
376
+ __publicField(this, "missedHeartbeats", 0);
377
+ __publicField(this, "ping");
378
+ __publicField(this, "debug");
379
+ __publicField(this, "ws");
380
+ this.ws = new import_ws.default(address);
381
+ this.ws.onmessage = (e) => this.onMessage(e);
382
+ this.ws.onopen = (e) => this.emit("open", e);
383
+ this.ws.onerror = (e) => this.emit("error", e instanceof Error ? e : e.error);
384
+ this.ws.onclose = (e) => this.emit("close", e);
385
+ this.lastHeartbeatAck = 0;
386
+ this.lastHeartbeatSend = 0;
387
+ this.debug = debug ? (message) => this.emit("debug", message) : null;
388
+ }
389
+ destroy() {
390
+ try {
391
+ this.debug?.("destroyed");
392
+ this.setHeartbeatInterval(-1);
393
+ this.ws.close(1e3);
394
+ } catch (error) {
395
+ const e = error;
396
+ this.emit("error", e);
397
+ }
398
+ }
399
+ onMessage(event) {
400
+ if (typeof event.data !== "string")
401
+ return;
402
+ this.debug?.(`<< ${event.data}`);
403
+ let packet;
404
+ try {
405
+ packet = JSON.parse(event.data);
406
+ } catch (error) {
407
+ const e = error;
408
+ this.emit("error", e);
409
+ return;
410
+ }
411
+ if (packet.op === import_v4.VoiceOpcodes.HeartbeatAck) {
412
+ this.lastHeartbeatAck = Date.now();
413
+ this.missedHeartbeats = 0;
414
+ this.ping = this.lastHeartbeatAck - this.lastHeartbeatSend;
415
+ }
416
+ this.emit("packet", packet);
417
+ }
418
+ sendPacket(packet) {
419
+ try {
420
+ const stringified = JSON.stringify(packet);
421
+ this.debug?.(`>> ${stringified}`);
422
+ return this.ws.send(stringified);
423
+ } catch (error) {
424
+ const e = error;
425
+ this.emit("error", e);
426
+ }
427
+ }
428
+ sendHeartbeat() {
429
+ this.lastHeartbeatSend = Date.now();
430
+ this.missedHeartbeats++;
431
+ const nonce2 = this.lastHeartbeatSend;
432
+ return this.sendPacket({
433
+ op: import_v4.VoiceOpcodes.Heartbeat,
434
+ d: nonce2
435
+ });
436
+ }
437
+ setHeartbeatInterval(ms) {
438
+ if (typeof this.heartbeatInterval !== "undefined")
439
+ clearInterval(this.heartbeatInterval);
440
+ if (ms > 0) {
441
+ this.heartbeatInterval = setInterval(() => {
442
+ if (this.lastHeartbeatSend !== 0 && this.missedHeartbeats >= 3) {
443
+ this.ws.close();
444
+ this.setHeartbeatInterval(-1);
445
+ }
446
+ this.sendHeartbeat();
447
+ }, ms);
448
+ }
449
+ }
450
+ };
451
+ __name(VoiceWebSocket, "VoiceWebSocket");
452
+
453
+ // src/util/Secretbox.ts
454
+ var libs = {
455
+ sodium: (sodium) => ({
456
+ open: sodium.api.crypto_secretbox_open_easy,
457
+ close: sodium.api.crypto_secretbox_easy,
458
+ random: (n, buffer) => {
459
+ if (!buffer)
460
+ buffer = Buffer.allocUnsafe(n);
461
+ sodium.api.randombytes_buf(buffer);
462
+ return buffer;
463
+ }
464
+ }),
465
+ "libsodium-wrappers": (sodium) => ({
466
+ open: sodium.crypto_secretbox_open_easy,
467
+ close: sodium.crypto_secretbox_easy,
468
+ random: (n) => sodium.randombytes_buf(n)
469
+ }),
470
+ tweetnacl: (tweetnacl) => ({
471
+ open: tweetnacl.secretbox.open,
472
+ close: tweetnacl.secretbox,
473
+ random: (n) => tweetnacl.randomBytes(n)
474
+ })
475
+ };
476
+ var fallbackError = /* @__PURE__ */ __name(() => {
477
+ throw new Error(`Cannot play audio as no valid encryption package is installed.
2
478
  - Install sodium, libsodium-wrappers, or tweetnacl.
3
479
  - Use the generateDependencyReport() function for more information.
4
- `)},"fallbackError"),y={open:Y,close:Y,random:Y};(async()=>{for(let i of Object.keys(Ce))try{let e=require(i);i==="libsodium-wrappers"&&e.ready&&await e.ready,Object.assign(y,Ce[i](e));break}catch{}})();var l=r(()=>{},"noop");var ke=require("tiny-typed-emitter"),lt=2,ft=48e3/100*lt,ht=2**32-1,mt=["xsalsa20_poly1305_lite","xsalsa20_poly1305_suffix","xsalsa20_poly1305"];var Ae=Buffer.alloc(24);function Pe(i){return JSON.stringify({...i,ws:Reflect.has(i,"ws"),udp:Reflect.has(i,"udp")})}r(Pe,"stringifyState");function gt(i){let e=i.find(t=>mt.includes(t));if(!e)throw new Error(`No compatible encryption modes. Available include: ${i.join(", ")}`);return e}r(gt,"chooseEncryptionMode");function ve(i){return Math.floor(Math.random()*2**i)}r(ve,"randomNBit");var J=class extends ke.TypedEmitter{constructor(e,t){super();a(this,"_state");a(this,"debug");this.onWsOpen=this.onWsOpen.bind(this),this.onChildError=this.onChildError.bind(this),this.onWsPacket=this.onWsPacket.bind(this),this.onWsClose=this.onWsClose.bind(this),this.onWsDebug=this.onWsDebug.bind(this),this.onUdpDebug=this.onUdpDebug.bind(this),this.onUdpClose=this.onUdpClose.bind(this),this.debug=t?o=>this.emit("debug",o):null,this._state={code:0,ws:this.createWebSocket(e.endpoint),connectionOptions:e}}destroy(){this.state={code:6}}get state(){return this._state}set state(e){let t=Reflect.get(this._state,"ws"),o=Reflect.get(e,"ws");t&&t!==o&&(t.off("debug",this.onWsDebug),t.on("error",l),t.off("error",this.onChildError),t.off("open",this.onWsOpen),t.off("packet",this.onWsPacket),t.off("close",this.onWsClose),t.destroy());let s=Reflect.get(this._state,"udp"),n=Reflect.get(e,"udp");s&&s!==n&&(s.on("error",l),s.off("error",this.onChildError),s.off("close",this.onUdpClose),s.off("debug",this.onUdpDebug),s.destroy());let c=this._state;this._state=e,this.emit("stateChange",c,e),this.debug?.(`state change:
5
- from ${Pe(c)}
6
- to ${Pe(e)}`)}createWebSocket(e){let t=new H(`wss://${e}?v=4`,Boolean(this.debug));return t.on("error",this.onChildError),t.once("open",this.onWsOpen),t.on("packet",this.onWsPacket),t.once("close",this.onWsClose),t.on("debug",this.onWsDebug),t}onChildError(e){this.emit("error",e)}onWsOpen(){if(this.state.code===0){let e={op:h.VoiceOpcodes.Identify,d:{server_id:this.state.connectionOptions.serverId,user_id:this.state.connectionOptions.userId,session_id:this.state.connectionOptions.sessionId,token:this.state.connectionOptions.token}};this.state.ws.sendPacket(e),this.state={...this.state,code:1}}else if(this.state.code===5){let e={op:h.VoiceOpcodes.Resume,d:{server_id:this.state.connectionOptions.serverId,session_id:this.state.connectionOptions.sessionId,token:this.state.connectionOptions.token}};this.state.ws.sendPacket(e)}}onWsClose({code:e}){(e===4015||e<4e3)&&this.state.code===4?this.state={...this.state,code:5,ws:this.createWebSocket(this.state.connectionOptions.endpoint)}:this.state.code!==6&&(this.destroy(),this.emit("close",e))}onUdpClose(){this.state.code===4&&(this.state={...this.state,code:5,ws:this.createWebSocket(this.state.connectionOptions.endpoint)})}onWsPacket(e){if(e.op===h.VoiceOpcodes.Hello&&this.state.code!==6)this.state.ws.setHeartbeatInterval(e.d.heartbeat_interval);else if(e.op===h.VoiceOpcodes.Ready&&this.state.code===1){let{ip:t,port:o,ssrc:s,modes:n}=e.d,c=new G({ip:t,port:o});c.on("error",this.onChildError),c.on("debug",this.onUdpDebug),c.once("close",this.onUdpClose),c.performIPDiscovery(s).then(u=>{this.state.code===2&&(this.state.ws.sendPacket({op:h.VoiceOpcodes.SelectProtocol,d:{protocol:"udp",data:{address:u.ip,port:u.port,mode:gt(n)}}}),this.state={...this.state,code:3})}).catch(u=>this.emit("error",u)),this.state={...this.state,code:2,udp:c,connectionData:{ssrc:s}}}else if(e.op===h.VoiceOpcodes.SessionDescription&&this.state.code===3){let{mode:t,secret_key:o}=e.d;this.state={...this.state,code:4,connectionData:{...this.state.connectionData,encryptionMode:t,secretKey:new Uint8Array(o),sequence:ve(16),timestamp:ve(32),nonce:0,nonceBuffer:Buffer.alloc(24),speaking:!1,packetsPlayed:0}}}else e.op===h.VoiceOpcodes.Resumed&&this.state.code===5&&(this.state={...this.state,code:4},this.state.connectionData.speaking=!1)}onWsDebug(e){this.debug?.(`[WS] ${e}`)}onUdpDebug(e){this.debug?.(`[UDP] ${e}`)}prepareAudioPacket(e){let t=this.state;if(t.code===4)return t.preparedPacket=this.createAudioPacket(e,t.connectionData),t.preparedPacket}dispatchAudio(){let e=this.state;return e.code!==4?!1:typeof e.preparedPacket!="undefined"?(this.playAudioPacket(e.preparedPacket),e.preparedPacket=void 0,!0):!1}playAudioPacket(e){let t=this.state;if(t.code!==4)return;let{connectionData:o}=t;o.packetsPlayed++,o.sequence++,o.timestamp+=ft,o.sequence>=2**16&&(o.sequence=0),o.timestamp>=2**32&&(o.timestamp=0),this.setSpeaking(!0),t.udp.send(e)}setSpeaking(e){let t=this.state;t.code===4&&t.connectionData.speaking!==e&&(t.connectionData.speaking=e,t.ws.sendPacket({op:h.VoiceOpcodes.Speaking,d:{speaking:e?1:0,delay:0,ssrc:t.connectionData.ssrc}}))}createAudioPacket(e,t){let o=Buffer.alloc(12);o[0]=128,o[1]=120;let{sequence:s,timestamp:n,ssrc:c}=t;return o.writeUIntBE(s,2,2),o.writeUIntBE(n,4,4),o.writeUIntBE(c,8,4),o.copy(Ae,0,0,12),Buffer.concat([o,...this.encryptOpusPacket(e,t)])}encryptOpusPacket(e,t){let{secretKey:o,encryptionMode:s}=t;if(s==="xsalsa20_poly1305_lite")return t.nonce++,t.nonce>ht&&(t.nonce=0),t.nonceBuffer.writeUInt32BE(t.nonce,0),[y.close(e,t.nonceBuffer,o),t.nonceBuffer.slice(0,4)];if(s==="xsalsa20_poly1305_suffix"){let n=y.random(24,t.nonceBuffer);return[y.close(e,n,o),n]}return[y.close(e,Ae,o)]}};r(J,"Networking");var Ie=require("tiny-typed-emitter");var $=require("discord-api-types/voice/v4");var De=require("stream");var w=class extends Error{constructor(e,t){super(e.message);a(this,"resource");this.resource=t,this.name=e.name,this.stack=e.stack}};r(w,"AudioPlayerError");var x=class{constructor(e,t){a(this,"connection");a(this,"player");this.connection=e,this.player=t}unsubscribe(){this.connection.onSubscriptionRemoved(this),this.player.unsubscribe(this)}};r(x,"PlayerSubscription");var we=require("tiny-typed-emitter"),V=Buffer.from([248,255,254]),X=(o=>(o.Pause="pause",o.Play="play",o.Stop="stop",o))(X||{}),Z=(n=>(n.Idle="idle",n.Buffering="buffering",n.Paused="paused",n.Playing="playing",n.AutoPaused="autopaused",n))(Z||{});function xe(i){return JSON.stringify({...i,resource:Reflect.has(i,"resource"),stepTimeout:Reflect.has(i,"stepTimeout")})}r(xe,"stringifyState");var N=class extends we.TypedEmitter{constructor(e={}){super();a(this,"_state");a(this,"subscribers",[]);a(this,"behaviors");a(this,"debug");this._state={status:"idle"},this.behaviors={noSubscriber:"pause",maxMissedFrames:5,...e.behaviors},this.debug=e.debug===!1?null:t=>this.emit("debug",t)}get playable(){return this.subscribers.filter(({connection:e})=>e.state.status==="ready").map(({connection:e})=>e)}subscribe(e){let t=this.subscribers.find(o=>o.connection===e);if(!t){let o=new x(e,this);return this.subscribers.push(o),setImmediate(()=>this.emit("subscribe",o)),o}return t}unsubscribe(e){let t=this.subscribers.indexOf(e),o=t!==-1;return o&&(this.subscribers.splice(t,1),e.connection.setSpeaking(!1),this.emit("unsubscribe",e)),o}get state(){return this._state}set state(e){let t=this._state,o=Reflect.get(e,"resource");t.status!=="idle"&&t.resource!==o&&(t.resource.playStream.on("error",l),t.resource.playStream.off("error",t.onStreamError),t.resource.audioPlayer=void 0,t.resource.playStream.destroy(),t.resource.playStream.read()),t.status==="buffering"&&(e.status!=="buffering"||e.resource!==t.resource)&&(t.resource.playStream.off("end",t.onFailureCallback),t.resource.playStream.off("close",t.onFailureCallback),t.resource.playStream.off("finish",t.onFailureCallback),t.resource.playStream.off("readable",t.onReadableCallback)),e.status==="idle"&&(this._signalStopSpeaking(),he(this)),o&&fe(this);let s=t.status!=="idle"&&e.status==="playing"&&t.resource!==e.resource;this._state=e,this.emit("stateChange",t,this._state),(t.status!==e.status||s)&&this.emit(e.status,t,this._state),this.debug?.(`state change:
7
- from ${xe(t)}
8
- to ${xe(e)}`)}play(e){if(e.ended)throw new Error("Cannot play a resource that has already ended.");if(e.audioPlayer){if(e.audioPlayer===this)return;throw new Error("Resource is already being played by another audio player.")}e.audioPlayer=this;let t=r(o=>{this.state.status!=="idle"&&this.emit("error",new w(o,this.state.resource)),this.state.status!=="idle"&&this.state.resource===e&&(this.state={status:"idle"})},"onStreamError");if(e.playStream.once("error",t),e.started)this.state={status:"playing",missedFrames:0,playbackDuration:0,resource:e,onStreamError:t};else{let o=r(()=>{this.state.status==="buffering"&&this.state.resource===e&&(this.state={status:"playing",missedFrames:0,playbackDuration:0,resource:e,onStreamError:t})},"onReadableCallback"),s=r(()=>{this.state.status==="buffering"&&this.state.resource===e&&(this.state={status:"idle"})},"onFailureCallback");e.playStream.once("readable",o),e.playStream.once("end",s),e.playStream.once("close",s),e.playStream.once("finish",s),this.state={status:"buffering",resource:e,onReadableCallback:o,onFailureCallback:s,onStreamError:t}}}pause(e=!0){return this.state.status!=="playing"?!1:(this.state={...this.state,status:"paused",silencePacketsRemaining:e?5:0},!0)}unpause(){return this.state.status!=="paused"?!1:(this.state={...this.state,status:"playing",missedFrames:0},!0)}stop(e=!1){return this.state.status==="idle"?!1:(e||this.state.resource.silencePaddingFrames===0?this.state={status:"idle"}:this.state.resource.silenceRemaining===-1&&(this.state.resource.silenceRemaining=this.state.resource.silencePaddingFrames),!0)}checkPlayable(){let e=this._state;return e.status==="idle"||e.status==="buffering"?!1:e.resource.readable?!0:(this.state={status:"idle"},!1)}_stepDispatch(){let e=this._state;e.status==="idle"||e.status==="buffering"||this.playable.forEach(t=>t.dispatchAudio())}_stepPrepare(){let e=this._state;if(e.status==="idle"||e.status==="buffering")return;let t=this.playable;if(e.status==="autopaused"&&t.length>0&&(this.state={...e,status:"playing",missedFrames:0}),e.status==="paused"||e.status==="autopaused"){e.silencePacketsRemaining>0&&(e.silencePacketsRemaining--,this._preparePacket(V,t,e),e.silencePacketsRemaining===0&&this._signalStopSpeaking());return}if(t.length===0)if(this.behaviors.noSubscriber==="pause"){this.state={...e,status:"autopaused",silencePacketsRemaining:5};return}else this.behaviors.noSubscriber==="stop"&&this.stop(!0);let o=e.resource.read();e.status==="playing"&&(o?(this._preparePacket(o,t,e),e.missedFrames=0):(this._preparePacket(V,t,e),e.missedFrames++,e.missedFrames>=this.behaviors.maxMissedFrames&&this.stop()))}_signalStopSpeaking(){return this.subscribers.forEach(({connection:e})=>e.setSpeaking(!1))}_preparePacket(e,t,o){o.playbackDuration+=20,t.forEach(s=>s.prepareAudioPacket(e))}};r(N,"AudioPlayer");function Ve(i){return new N(i)}r(Ve,"createAudioPlayer");var Ee=(o=>(o[o.Manual=0]="Manual",o[o.AfterSilence=1]="AfterSilence",o[o.AfterInactivity=2]="AfterInactivity",o))(Ee||{});function Q(){return{end:{behavior:0}}}r(Q,"createDefaultAudioReceiveStreamOptions");var B=class extends De.Readable{constructor({end:e,...t}){super({...t,objectMode:!0});a(this,"end");a(this,"endTimeout");this.end=e}push(e){return e&&(this.end.behavior===2||this.end.behavior===1&&(e.compare(V)!==0||typeof this.endTimeout=="undefined"))&&this.renewEndTimeout(this.end),super.push(e)}renewEndTimeout(e){this.endTimeout&&clearTimeout(this.endTimeout),this.endTimeout=setTimeout(()=>this.push(null),e.duration)}_read(){}};r(B,"AudioReceiveStream");var Re=require("tiny-typed-emitter"),ee=class extends Re.TypedEmitter{constructor(){super();a(this,"users");a(this,"speakingTimeouts");this.users=new Map,this.speakingTimeouts=new Map}onPacket(e){let t=this.speakingTimeouts.get(e);t?clearTimeout(t):(this.users.set(e,Date.now()),this.emit("start",e)),this.startTimeout(e)}startTimeout(e){this.speakingTimeouts.set(e,setTimeout(()=>{this.emit("end",e),this.speakingTimeouts.delete(e),this.users.delete(e)},ee.DELAY))}},D=ee;r(D,"SpeakingMap"),a(D,"DELAY",100);var Oe=require("tiny-typed-emitter"),M=class extends Oe.TypedEmitter{constructor(){super();a(this,"map");this.map=new Map}update(e){let t=this.map.get(e.audioSSRC),o={...this.map.get(e.audioSSRC),...e};this.map.set(e.audioSSRC,o),t||this.emit("create",o),this.emit("update",t,o)}get(e){if(typeof e=="number")return this.map.get(e);for(let t of this.map.values())if(t.userId===e)return t}delete(e){if(typeof e=="number"){let t=this.map.get(e);return t&&(this.map.delete(e),this.emit("delete",t)),t}for(let[t,o]of this.map.entries())if(o.userId===e)return this.map.delete(t),this.emit("delete",o),o}};r(M,"SSRCMap");var U=class{constructor(e){a(this,"voiceConnection");a(this,"ssrcMap");a(this,"subscriptions");a(this,"connectionData");a(this,"speaking");this.voiceConnection=e,this.ssrcMap=new M,this.speaking=new D,this.subscriptions=new Map,this.connectionData={},this.onWsPacket=this.onWsPacket.bind(this),this.onUdpMessage=this.onUdpMessage.bind(this)}onWsPacket(e){e.op===$.VoiceOpcodes.ClientDisconnect&&typeof e.d?.user_id=="string"?this.ssrcMap.delete(e.d.user_id):e.op===$.VoiceOpcodes.Speaking&&typeof e.d?.user_id=="string"&&typeof e.d?.ssrc=="number"?this.ssrcMap.update({userId:e.d.user_id,audioSSRC:e.d.ssrc}):e.op===$.VoiceOpcodes.ClientConnect&&typeof e.d?.user_id=="string"&&typeof e.d?.audio_ssrc=="number"&&this.ssrcMap.update({userId:e.d.user_id,audioSSRC:e.d.audio_ssrc,videoSSRC:e.d.video_ssrc===0?void 0:e.d.video_ssrc})}decrypt(e,t,o,s){let n;t==="xsalsa20_poly1305_lite"?(e.copy(o,0,e.length-4),n=e.length-4):t==="xsalsa20_poly1305_suffix"?(e.copy(o,0,e.length-24),n=e.length-24):e.copy(o,0,0,12);let c=y.open(e.slice(12,n),o,s);if(!!c)return Buffer.from(c)}parsePacket(e,t,o,s){let n=this.decrypt(e,t,o,s);if(!!n){if(n[0]===190&&n[1]===222&&n.length>4){let c=n.readUInt16BE(2),u=4;for(let C=0;C<c;C++){let k=n[u];u++,k!==0&&(u+=1+(k>>4))}let g=n.readUInt8(u);(g===0||g===2)&&u++,n=n.slice(u)}return n}}onUdpMessage(e){if(e.length<=8)return;let t=e.readUInt32BE(8),o=this.ssrcMap.get(t);if(!o)return;this.speaking.onPacket(o.userId);let s=this.subscriptions.get(o.userId);if(!!s&&this.connectionData.encryptionMode&&this.connectionData.nonceBuffer&&this.connectionData.secretKey){let n=this.parsePacket(e,this.connectionData.encryptionMode,this.connectionData.nonceBuffer,this.connectionData.secretKey);n?s.push(n):s.destroy(new Error("Failed to parse packet"))}}subscribe(e,t){let o=this.subscriptions.get(e);if(o)return o;let s=new B({...Q(),...t});return s.once("close",()=>this.subscriptions.delete(e)),this.subscriptions.set(e,s),s}};r(U,"VoiceReceiver");var L=(n=>(n.Signalling="signalling",n.Connecting="connecting",n.Ready="ready",n.Disconnected="disconnected",n.Destroyed="destroyed",n))(L||{}),te=(s=>(s[s.WebSocketClose=0]="WebSocketClose",s[s.AdapterUnavailable=1]="AdapterUnavailable",s[s.EndpointRemoved=2]="EndpointRemoved",s[s.Manual=3]="Manual",s))(te||{}),W=class extends Ie.TypedEmitter{constructor(e,{debug:t,adapterCreator:o}){super();a(this,"rejoinAttempts");a(this,"_state");a(this,"joinConfig");a(this,"packets");a(this,"receiver");a(this,"debug");this.debug=t?n=>this.emit("debug",n):null,this.rejoinAttempts=0,this.receiver=new U(this),this.onNetworkingClose=this.onNetworkingClose.bind(this),this.onNetworkingStateChange=this.onNetworkingStateChange.bind(this),this.onNetworkingError=this.onNetworkingError.bind(this),this.onNetworkingDebug=this.onNetworkingDebug.bind(this);let s=o({onVoiceServerUpdate:n=>this.addServerPacket(n),onVoiceStateUpdate:n=>this.addStatePacket(n),destroy:()=>this.destroy(!1)});this._state={status:"signalling",adapter:s},this.packets={server:void 0,state:void 0},this.joinConfig=e}get state(){return this._state}set state(e){let t=this._state,o=Reflect.get(t,"networking"),s=Reflect.get(e,"networking"),n=Reflect.get(t,"subscription"),c=Reflect.get(e,"subscription");if(o!==s&&(o&&(o.on("error",l),o.off("debug",this.onNetworkingDebug),o.off("error",this.onNetworkingError),o.off("close",this.onNetworkingClose),o.off("stateChange",this.onNetworkingStateChange),o.destroy()),s&&this.updateReceiveBindings(s.state,o?.state)),e.status==="ready")this.rejoinAttempts=0;else if(e.status==="destroyed")for(let u of this.receiver.subscriptions.values())u.destroyed||u.destroy();t.status!=="destroyed"&&e.status==="destroyed"&&t.adapter.destroy(),this._state=e,n&&n!==c&&n.unsubscribe(),this.emit("stateChange",t,e),t.status!==e.status&&this.emit(e.status,t,e)}addServerPacket(e){this.packets.server=e,e.endpoint?this.configureNetworking():this.state.status!=="destroyed"&&(this.state={...this.state,status:"disconnected",reason:2})}addStatePacket(e){this.packets.state=e,typeof e.self_deaf!="undefined"&&(this.joinConfig.selfDeaf=e.self_deaf),typeof e.self_mute!="undefined"&&(this.joinConfig.selfMute=e.self_mute),e.channel_id&&(this.joinConfig.channelId=e.channel_id)}updateReceiveBindings(e,t){let o=Reflect.get(t??{},"ws"),s=Reflect.get(e,"ws"),n=Reflect.get(t??{},"udp"),c=Reflect.get(e,"udp");o!==s&&(o?.off("packet",this.receiver.onWsPacket),s?.on("packet",this.receiver.onWsPacket)),n!==c&&(n?.off("message",this.receiver.onUdpMessage),c?.on("message",this.receiver.onUdpMessage)),this.receiver.connectionData=Reflect.get(e,"connectionData")??{}}configureNetworking(){let{server:e,state:t}=this.packets;if(!e||!t||this.state.status==="destroyed"||!e.endpoint)return;let o=new J({endpoint:e.endpoint,serverId:e.guild_id,token:e.token,sessionId:t.session_id,userId:t.user_id},Boolean(this.debug));o.once("close",this.onNetworkingClose),o.on("stateChange",this.onNetworkingStateChange),o.on("error",this.onNetworkingError),o.on("debug",this.onNetworkingDebug),this.state={...this.state,status:"connecting",networking:o}}onNetworkingClose(e){this.state.status!=="destroyed"&&(e===4014?this.state={...this.state,status:"disconnected",reason:0,closeCode:e}:(this.state={...this.state,status:"signalling"},this.rejoinAttempts++,this.state.adapter.sendPayload(P(this.joinConfig))||(this.state={...this.state,status:"disconnected",reason:1})))}onNetworkingStateChange(e,t){this.updateReceiveBindings(t,e),e.code!==t.code&&(this.state.status!=="connecting"&&this.state.status!=="ready"||(t.code===4?this.state={...this.state,status:"ready"}:t.code!==6&&(this.state={...this.state,status:"connecting"})))}onNetworkingError(e){this.emit("error",e)}onNetworkingDebug(e){this.debug?.(`[NW] ${e}`)}prepareAudioPacket(e){let t=this.state;if(t.status==="ready")return t.networking.prepareAudioPacket(e)}dispatchAudio(){let e=this.state;if(e.status==="ready")return e.networking.dispatchAudio()}playOpusPacket(e){let t=this.state;if(t.status==="ready")return t.networking.prepareAudioPacket(e),t.networking.dispatchAudio()}destroy(e=!0){if(this.state.status==="destroyed")throw new Error("Cannot destroy VoiceConnection - it has already been destroyed");_(this.joinConfig.guildId,this.joinConfig.group)===this&&de(this),e&&this.state.adapter.sendPayload(P({...this.joinConfig,channelId:null})),this.state={status:"destroyed"}}disconnect(){return this.state.status==="destroyed"||this.state.status==="signalling"?!1:(this.joinConfig.channelId=null,this.state.adapter.sendPayload(P(this.joinConfig))?(this.state={adapter:this.state.adapter,reason:3,status:"disconnected"},!0):(this.state={adapter:this.state.adapter,subscription:this.state.subscription,status:"disconnected",reason:1},!1))}rejoin(e){if(this.state.status==="destroyed")return!1;let t=this.state.status!=="ready";return t&&this.rejoinAttempts++,Object.assign(this.joinConfig,e),this.state.adapter.sendPayload(P(this.joinConfig))?(t&&(this.state={...this.state,status:"signalling"}),!0):(this.state={adapter:this.state.adapter,subscription:this.state.subscription,status:"disconnected",reason:1},!1)}setSpeaking(e){return this.state.status!=="ready"?!1:this.state.networking.setSpeaking(e)}subscribe(e){if(this.state.status==="destroyed")return;let t=e.subscribe(this);return this.state={...this.state,subscription:t},t}get ping(){return this.state.status==="ready"&&this.state.networking.state.code===4?{ws:this.state.networking.state.ws.ping,udp:this.state.networking.state.udp.ping}:{ws:void 0,udp:void 0}}onSubscriptionRemoved(e){this.state.status!=="destroyed"&&this.state.subscription===e&&(this.state={...this.state,subscription:void 0})}};r(W,"VoiceConnection");function Te(i,e){let t=P(i),o=_(i.guildId,i.group);if(o&&o.state.status!=="destroyed")return o.state.status==="disconnected"?o.rejoin({channelId:i.channelId,selfDeaf:i.selfDeaf,selfMute:i.selfMute}):o.state.adapter.sendPayload(t)||(o.state={...o.state,status:"disconnected",reason:1}),o;let s=new W(i,e);return ue(s),s.state.status!=="destroyed"&&(s.state.adapter.sendPayload(t)||(s.state={...s.state,status:"disconnected",reason:1})),s}r(Te,"createVoiceConnection");function yt(i){let e={selfDeaf:!0,selfMute:!1,group:"default",...i};return Te(e,{adapterCreator:i.adapterCreator,debug:i.debug})}r(yt,"joinVoiceChannel");var m=I(require("prism-media")),_e=["-analyzeduration","0","-loglevel","0","-f","s16le","-ar","48000","-ac","2"],Ne=["-analyzeduration","0","-loglevel","0","-acodec","libopus","-f","opus","-ar","48000","-ac","2"],E=(n=>(n.Arbitrary="arbitrary",n.Raw="raw",n.OggOpus="ogg/opus",n.WebmOpus="webm/opus",n.Opus="opus",n))(E||{});var ie=class{constructor(e){a(this,"edges",[]);a(this,"type");this.type=e}addEdge(e){this.edges.push({...e,from:this})}};r(ie,"Node");var Be=new Map;for(let i of Object.values(E))Be.set(i,new ie(i));function p(i){let e=Be.get(i);if(!e)throw new Error(`Node type '${i}' does not exist!`);return e}r(p,"getNode");p("raw").addEdge({type:"opus encoder",to:p("opus"),cost:1.5,transformer:()=>new m.default.opus.Encoder({rate:48e3,channels:2,frameSize:960})});p("opus").addEdge({type:"opus decoder",to:p("raw"),cost:1.5,transformer:()=>new m.default.opus.Decoder({rate:48e3,channels:2,frameSize:960})});p("ogg/opus").addEdge({type:"ogg/opus demuxer",to:p("opus"),cost:1,transformer:()=>new m.default.opus.OggDemuxer});p("webm/opus").addEdge({type:"webm/opus demuxer",to:p("opus"),cost:1,transformer:()=>new m.default.opus.WebmDemuxer});var oe={type:"ffmpeg pcm",to:p("raw"),cost:2,transformer:i=>new m.default.FFmpeg({args:typeof i=="string"?["-i",i,..._e]:_e})};p("arbitrary").addEdge(oe);p("ogg/opus").addEdge(oe);p("webm/opus").addEdge(oe);p("raw").addEdge({type:"volume transformer",to:p("raw"),cost:.5,transformer:()=>new m.default.VolumeTransformer({type:"s16le"})});function bt(){try{return m.default.FFmpeg.getInfo().output.includes("--enable-libopus")}catch{}return!1}r(bt,"canEnableFFmpegOptimizations");if(bt()){let i={type:"ffmpeg ogg",to:p("ogg/opus"),cost:2,transformer:e=>new m.default.FFmpeg({args:typeof e=="string"?["-i",e,...Ne]:Ne})};p("arbitrary").addEdge(i),p("ogg/opus").addEdge(i),p("webm/opus").addEdge(i)}function Me(i,e,t=p("opus"),o=[],s=5){if(i===t&&e(o))return{cost:0};if(s===0)return{cost:1/0};let n;for(let c of i.edges){if(n&&c.cost>n.cost)continue;let u=Me(c.to,e,t,[...o,c],s-1),g=c.cost+u.cost;(!n||g<n.cost)&&(n={cost:g,edge:c,next:u})}return n??{cost:1/0}}r(Me,"findPath");function St(i){let e=[],t=i;for(;t?.edge;)e.push(t.edge),t=t.next;return e}r(St,"constructPipeline");function Ue(i,e){return St(Me(p(i),e))}r(Ue,"findPipeline");var We=require("stream");var b=I(require("prism-media"));var R=class{constructor(e,t,o,s){a(this,"playStream");a(this,"edges");a(this,"metadata");a(this,"volume");a(this,"encoder");a(this,"audioPlayer");a(this,"playbackDuration",0);a(this,"started",!1);a(this,"silencePaddingFrames");a(this,"silenceRemaining",-1);this.edges=e,this.playStream=t.length>1?(0,We.pipeline)(t,l):t[0],this.metadata=o,this.silencePaddingFrames=s;for(let n of t)n instanceof b.default.VolumeTransformer?this.volume=n:n instanceof b.default.opus.Encoder&&(this.encoder=n);this.playStream.once("readable",()=>this.started=!0)}get readable(){if(this.silenceRemaining===0)return!1;let e=this.playStream.readable;return e||(this.silenceRemaining===-1&&(this.silenceRemaining=this.silencePaddingFrames),this.silenceRemaining!==0)}get ended(){return this.playStream.readableEnded||this.playStream.destroyed||this.silenceRemaining===0}read(){if(this.silenceRemaining===0)return null;if(this.silenceRemaining>0)return this.silenceRemaining--,V;let e=this.playStream.read();return e&&(this.playbackDuration+=20),e}};r(R,"AudioResource");var Ct=r(i=>i.some(e=>e.type==="volume transformer"),"VOLUME_CONSTRAINT"),kt=r(()=>!0,"NO_CONSTRAINT");function At(i){return i instanceof b.default.opus.Encoder?{streamType:"opus",hasVolume:!1}:i instanceof b.default.opus.Decoder?{streamType:"raw",hasVolume:!1}:i instanceof b.default.VolumeTransformer?{streamType:"raw",hasVolume:!0}:i instanceof b.default.opus.OggDemuxer?{streamType:"opus",hasVolume:!1}:i instanceof b.default.opus.WebmDemuxer?{streamType:"opus",hasVolume:!1}:{streamType:"arbitrary",hasVolume:!1}}r(At,"inferStreamType");function Fe(i,e={}){let t=e.inputType,o=Boolean(e.inlineVolume);if(typeof i=="string")t="arbitrary";else if(typeof t=="undefined"){let c=At(i);t=c.streamType,o=o&&!c.hasVolume}let s=Ue(t,o?Ct:kt);if(s.length===0){if(typeof i=="string")throw new Error(`Invalid pipeline constructed for string resource '${i}'`);return new R([],[i],e.metadata??null,e.silencePaddingFrames??5)}let n=s.map(c=>c.transformer(i));return typeof i!="string"&&n.unshift(i),new R(s,n,e.metadata??null,e.silencePaddingFrames??5)}r(Fe,"createAudioResource");var F=require("path"),Ge=I(require("prism-media"));function He(i,e,t){if(t===0)return;let o=(0,F.resolve)(i,"./package.json");try{let s=require(o);if(s.name!==e)throw new Error("package.json does not match");return s}catch{return He((0,F.resolve)(i,".."),e,t-1)}}r(He,"findPackageJSON");function vt(i){try{return(i==="@discordjs/voice"?je():He((0,F.dirname)(require.resolve(i)),i,3))?.version??"not found"}catch{return"not found"}}r(vt,"version");function wt(){let i=[],e=r(t=>i.push(`- ${t}: ${vt(t)}`),"addVersion");i.push("Core Dependencies"),e("@discordjs/voice"),e("prism-media"),i.push(""),i.push("Opus Libraries"),e("@discordjs/opus"),e("opusscript"),i.push(""),i.push("Encryption Libraries"),e("sodium"),e("libsodium-wrappers"),e("tweetnacl"),i.push(""),i.push("FFmpeg");try{let t=Ge.default.FFmpeg.getInfo();i.push(`- version: ${t.version}`),i.push(`- libopus: ${t.output.includes("--enable-libopus")?"yes":"no"}`)}catch{i.push("- not found")}return["-".repeat(50),...i,"-".repeat(50)].join(`
9
- `)}r(wt,"generateDependencyReport");function Je(i){let e=new AbortController,t=setTimeout(()=>e.abort(),i);return e.signal.addEventListener("abort",()=>clearTimeout(t)),[e,e.signal]}r(Je,"abortAfter");var Le=require("events");async function xt(i,e,t){if(i.state.status!==e){let[o,s]=typeof t=="number"?Je(t):[void 0,t];try{await(0,Le.once)(i,e,{signal:s})}finally{o?.abort()}}return i}r(xt,"entersState");var $e=require("stream"),se=I(require("prism-media"));function qe(i){let e=i.readUInt8(9),t=i.readUInt32LE(12);return e===2&&t===48e3}r(qe,"validateDiscordOpusHead");function Vt(i,e=1024,t=qe){return new Promise((o,s)=>{if(i.readableObjectMode)return s(new Error("Cannot probe a readable stream in object mode"));if(i.readableEnded)return s(new Error("Cannot probe a stream that has ended"));let n=Buffer.alloc(0),c,u=r(f=>{i.off("data",q),i.off("close",O),i.off("end",O),i.pause(),c=f,i.readableEnded?o({stream:$e.Readable.from(n),type:f}):(n.length>0&&i.push(n),o({stream:i,type:f}))},"finish"),g=r(f=>Ke=>{t(Ke)&&u(f)},"foundHead"),C=new se.default.opus.WebmDemuxer;C.once("error",l),C.on("head",g("webm/opus"));let k=new se.default.opus.OggDemuxer;k.once("error",l),k.on("head",g("ogg/opus"));let O=r(()=>{c||u("arbitrary")},"onClose"),q=r(f=>{n=Buffer.concat([n,f]),C.write(f),k.write(f),n.length>=e&&(i.off("data",q),i.pause(),process.nextTick(O))},"onData");i.once("error",s),i.on("data",q),i.once("close",O),i.once("end",O)})}r(Vt,"demuxProbe");module.exports=ot(Dt);0&&(module.exports={AudioPlayer,AudioPlayerError,AudioPlayerStatus,AudioReceiveStream,AudioResource,EndBehaviorType,NoSubscriberBehavior,PlayerSubscription,SSRCMap,SpeakingMap,StreamType,VoiceConnection,VoiceConnectionDisconnectReason,VoiceConnectionStatus,VoiceReceiver,createAudioPlayer,createAudioResource,createDefaultAudioReceiveStreamOptions,demuxProbe,entersState,generateDependencyReport,getGroups,getVoiceConnection,getVoiceConnections,joinVoiceChannel,validateDiscordOpusHead});
480
+ `);
481
+ }, "fallbackError");
482
+ var methods = {
483
+ open: fallbackError,
484
+ close: fallbackError,
485
+ random: fallbackError
486
+ };
487
+ void (async () => {
488
+ for (const libName of Object.keys(libs)) {
489
+ try {
490
+ const lib = require(libName);
491
+ if (libName === "libsodium-wrappers" && lib.ready)
492
+ await lib.ready;
493
+ Object.assign(methods, libs[libName](lib));
494
+ break;
495
+ } catch {
496
+ }
497
+ }
498
+ })();
499
+
500
+ // src/util/util.ts
501
+ var noop = /* @__PURE__ */ __name(() => {
502
+ }, "noop");
503
+
504
+ // src/networking/Networking.ts
505
+ var import_tiny_typed_emitter3 = require("tiny-typed-emitter");
506
+ var CHANNELS = 2;
507
+ var TIMESTAMP_INC = 48e3 / 100 * CHANNELS;
508
+ var MAX_NONCE_SIZE = 2 ** 32 - 1;
509
+ var SUPPORTED_ENCRYPTION_MODES = ["xsalsa20_poly1305_lite", "xsalsa20_poly1305_suffix", "xsalsa20_poly1305"];
510
+ var nonce = Buffer.alloc(24);
511
+ function stringifyState(state) {
512
+ return JSON.stringify({
513
+ ...state,
514
+ ws: Reflect.has(state, "ws"),
515
+ udp: Reflect.has(state, "udp")
516
+ });
517
+ }
518
+ __name(stringifyState, "stringifyState");
519
+ function chooseEncryptionMode(options) {
520
+ const option = options.find((option2) => SUPPORTED_ENCRYPTION_MODES.includes(option2));
521
+ if (!option) {
522
+ throw new Error(`No compatible encryption modes. Available include: ${options.join(", ")}`);
523
+ }
524
+ return option;
525
+ }
526
+ __name(chooseEncryptionMode, "chooseEncryptionMode");
527
+ function randomNBit(n) {
528
+ return Math.floor(Math.random() * 2 ** n);
529
+ }
530
+ __name(randomNBit, "randomNBit");
531
+ var Networking = class extends import_tiny_typed_emitter3.TypedEmitter {
532
+ constructor(options, debug) {
533
+ super();
534
+ __publicField(this, "_state");
535
+ __publicField(this, "debug");
536
+ this.onWsOpen = this.onWsOpen.bind(this);
537
+ this.onChildError = this.onChildError.bind(this);
538
+ this.onWsPacket = this.onWsPacket.bind(this);
539
+ this.onWsClose = this.onWsClose.bind(this);
540
+ this.onWsDebug = this.onWsDebug.bind(this);
541
+ this.onUdpDebug = this.onUdpDebug.bind(this);
542
+ this.onUdpClose = this.onUdpClose.bind(this);
543
+ this.debug = debug ? (message) => this.emit("debug", message) : null;
544
+ this._state = {
545
+ code: 0 /* OpeningWs */,
546
+ ws: this.createWebSocket(options.endpoint),
547
+ connectionOptions: options
548
+ };
549
+ }
550
+ destroy() {
551
+ this.state = {
552
+ code: 6 /* Closed */
553
+ };
554
+ }
555
+ get state() {
556
+ return this._state;
557
+ }
558
+ set state(newState) {
559
+ const oldWs = Reflect.get(this._state, "ws");
560
+ const newWs = Reflect.get(newState, "ws");
561
+ if (oldWs && oldWs !== newWs) {
562
+ oldWs.off("debug", this.onWsDebug);
563
+ oldWs.on("error", noop);
564
+ oldWs.off("error", this.onChildError);
565
+ oldWs.off("open", this.onWsOpen);
566
+ oldWs.off("packet", this.onWsPacket);
567
+ oldWs.off("close", this.onWsClose);
568
+ oldWs.destroy();
569
+ }
570
+ const oldUdp = Reflect.get(this._state, "udp");
571
+ const newUdp = Reflect.get(newState, "udp");
572
+ if (oldUdp && oldUdp !== newUdp) {
573
+ oldUdp.on("error", noop);
574
+ oldUdp.off("error", this.onChildError);
575
+ oldUdp.off("close", this.onUdpClose);
576
+ oldUdp.off("debug", this.onUdpDebug);
577
+ oldUdp.destroy();
578
+ }
579
+ const oldState = this._state;
580
+ this._state = newState;
581
+ this.emit("stateChange", oldState, newState);
582
+ this.debug?.(`state change:
583
+ from ${stringifyState(oldState)}
584
+ to ${stringifyState(newState)}`);
585
+ }
586
+ createWebSocket(endpoint) {
587
+ const ws = new VoiceWebSocket(`wss://${endpoint}?v=4`, Boolean(this.debug));
588
+ ws.on("error", this.onChildError);
589
+ ws.once("open", this.onWsOpen);
590
+ ws.on("packet", this.onWsPacket);
591
+ ws.once("close", this.onWsClose);
592
+ ws.on("debug", this.onWsDebug);
593
+ return ws;
594
+ }
595
+ onChildError(error) {
596
+ this.emit("error", error);
597
+ }
598
+ onWsOpen() {
599
+ if (this.state.code === 0 /* OpeningWs */) {
600
+ const packet = {
601
+ op: import_v42.VoiceOpcodes.Identify,
602
+ d: {
603
+ server_id: this.state.connectionOptions.serverId,
604
+ user_id: this.state.connectionOptions.userId,
605
+ session_id: this.state.connectionOptions.sessionId,
606
+ token: this.state.connectionOptions.token
607
+ }
608
+ };
609
+ this.state.ws.sendPacket(packet);
610
+ this.state = {
611
+ ...this.state,
612
+ code: 1 /* Identifying */
613
+ };
614
+ } else if (this.state.code === 5 /* Resuming */) {
615
+ const packet = {
616
+ op: import_v42.VoiceOpcodes.Resume,
617
+ d: {
618
+ server_id: this.state.connectionOptions.serverId,
619
+ session_id: this.state.connectionOptions.sessionId,
620
+ token: this.state.connectionOptions.token
621
+ }
622
+ };
623
+ this.state.ws.sendPacket(packet);
624
+ }
625
+ }
626
+ onWsClose({ code }) {
627
+ const canResume = code === 4015 || code < 4e3;
628
+ if (canResume && this.state.code === 4 /* Ready */) {
629
+ this.state = {
630
+ ...this.state,
631
+ code: 5 /* Resuming */,
632
+ ws: this.createWebSocket(this.state.connectionOptions.endpoint)
633
+ };
634
+ } else if (this.state.code !== 6 /* Closed */) {
635
+ this.destroy();
636
+ this.emit("close", code);
637
+ }
638
+ }
639
+ onUdpClose() {
640
+ if (this.state.code === 4 /* Ready */) {
641
+ this.state = {
642
+ ...this.state,
643
+ code: 5 /* Resuming */,
644
+ ws: this.createWebSocket(this.state.connectionOptions.endpoint)
645
+ };
646
+ }
647
+ }
648
+ onWsPacket(packet) {
649
+ if (packet.op === import_v42.VoiceOpcodes.Hello && this.state.code !== 6 /* Closed */) {
650
+ this.state.ws.setHeartbeatInterval(packet.d.heartbeat_interval);
651
+ } else if (packet.op === import_v42.VoiceOpcodes.Ready && this.state.code === 1 /* Identifying */) {
652
+ const { ip, port, ssrc, modes } = packet.d;
653
+ const udp = new VoiceUDPSocket({ ip, port });
654
+ udp.on("error", this.onChildError);
655
+ udp.on("debug", this.onUdpDebug);
656
+ udp.once("close", this.onUdpClose);
657
+ udp.performIPDiscovery(ssrc).then((localConfig) => {
658
+ if (this.state.code !== 2 /* UdpHandshaking */)
659
+ return;
660
+ this.state.ws.sendPacket({
661
+ op: import_v42.VoiceOpcodes.SelectProtocol,
662
+ d: {
663
+ protocol: "udp",
664
+ data: {
665
+ address: localConfig.ip,
666
+ port: localConfig.port,
667
+ mode: chooseEncryptionMode(modes)
668
+ }
669
+ }
670
+ });
671
+ this.state = {
672
+ ...this.state,
673
+ code: 3 /* SelectingProtocol */
674
+ };
675
+ }).catch((error) => this.emit("error", error));
676
+ this.state = {
677
+ ...this.state,
678
+ code: 2 /* UdpHandshaking */,
679
+ udp,
680
+ connectionData: {
681
+ ssrc
682
+ }
683
+ };
684
+ } else if (packet.op === import_v42.VoiceOpcodes.SessionDescription && this.state.code === 3 /* SelectingProtocol */) {
685
+ const { mode: encryptionMode, secret_key: secretKey } = packet.d;
686
+ this.state = {
687
+ ...this.state,
688
+ code: 4 /* Ready */,
689
+ connectionData: {
690
+ ...this.state.connectionData,
691
+ encryptionMode,
692
+ secretKey: new Uint8Array(secretKey),
693
+ sequence: randomNBit(16),
694
+ timestamp: randomNBit(32),
695
+ nonce: 0,
696
+ nonceBuffer: Buffer.alloc(24),
697
+ speaking: false,
698
+ packetsPlayed: 0
699
+ }
700
+ };
701
+ } else if (packet.op === import_v42.VoiceOpcodes.Resumed && this.state.code === 5 /* Resuming */) {
702
+ this.state = {
703
+ ...this.state,
704
+ code: 4 /* Ready */
705
+ };
706
+ this.state.connectionData.speaking = false;
707
+ }
708
+ }
709
+ onWsDebug(message) {
710
+ this.debug?.(`[WS] ${message}`);
711
+ }
712
+ onUdpDebug(message) {
713
+ this.debug?.(`[UDP] ${message}`);
714
+ }
715
+ prepareAudioPacket(opusPacket) {
716
+ const state = this.state;
717
+ if (state.code !== 4 /* Ready */)
718
+ return;
719
+ state.preparedPacket = this.createAudioPacket(opusPacket, state.connectionData);
720
+ return state.preparedPacket;
721
+ }
722
+ dispatchAudio() {
723
+ const state = this.state;
724
+ if (state.code !== 4 /* Ready */)
725
+ return false;
726
+ if (typeof state.preparedPacket !== "undefined") {
727
+ this.playAudioPacket(state.preparedPacket);
728
+ state.preparedPacket = void 0;
729
+ return true;
730
+ }
731
+ return false;
732
+ }
733
+ playAudioPacket(audioPacket) {
734
+ const state = this.state;
735
+ if (state.code !== 4 /* Ready */)
736
+ return;
737
+ const { connectionData } = state;
738
+ connectionData.packetsPlayed++;
739
+ connectionData.sequence++;
740
+ connectionData.timestamp += TIMESTAMP_INC;
741
+ if (connectionData.sequence >= 2 ** 16)
742
+ connectionData.sequence = 0;
743
+ if (connectionData.timestamp >= 2 ** 32)
744
+ connectionData.timestamp = 0;
745
+ this.setSpeaking(true);
746
+ state.udp.send(audioPacket);
747
+ }
748
+ setSpeaking(speaking) {
749
+ const state = this.state;
750
+ if (state.code !== 4 /* Ready */)
751
+ return;
752
+ if (state.connectionData.speaking === speaking)
753
+ return;
754
+ state.connectionData.speaking = speaking;
755
+ state.ws.sendPacket({
756
+ op: import_v42.VoiceOpcodes.Speaking,
757
+ d: {
758
+ speaking: speaking ? 1 : 0,
759
+ delay: 0,
760
+ ssrc: state.connectionData.ssrc
761
+ }
762
+ });
763
+ }
764
+ createAudioPacket(opusPacket, connectionData) {
765
+ const packetBuffer = Buffer.alloc(12);
766
+ packetBuffer[0] = 128;
767
+ packetBuffer[1] = 120;
768
+ const { sequence, timestamp, ssrc } = connectionData;
769
+ packetBuffer.writeUIntBE(sequence, 2, 2);
770
+ packetBuffer.writeUIntBE(timestamp, 4, 4);
771
+ packetBuffer.writeUIntBE(ssrc, 8, 4);
772
+ packetBuffer.copy(nonce, 0, 0, 12);
773
+ return Buffer.concat([packetBuffer, ...this.encryptOpusPacket(opusPacket, connectionData)]);
774
+ }
775
+ encryptOpusPacket(opusPacket, connectionData) {
776
+ const { secretKey, encryptionMode } = connectionData;
777
+ if (encryptionMode === "xsalsa20_poly1305_lite") {
778
+ connectionData.nonce++;
779
+ if (connectionData.nonce > MAX_NONCE_SIZE)
780
+ connectionData.nonce = 0;
781
+ connectionData.nonceBuffer.writeUInt32BE(connectionData.nonce, 0);
782
+ return [
783
+ methods.close(opusPacket, connectionData.nonceBuffer, secretKey),
784
+ connectionData.nonceBuffer.slice(0, 4)
785
+ ];
786
+ } else if (encryptionMode === "xsalsa20_poly1305_suffix") {
787
+ const random = methods.random(24, connectionData.nonceBuffer);
788
+ return [methods.close(opusPacket, random, secretKey), random];
789
+ }
790
+ return [methods.close(opusPacket, nonce, secretKey)];
791
+ }
792
+ };
793
+ __name(Networking, "Networking");
794
+
795
+ // src/VoiceConnection.ts
796
+ var import_tiny_typed_emitter7 = require("tiny-typed-emitter");
797
+
798
+ // src/receive/VoiceReceiver.ts
799
+ var import_v43 = require("discord-api-types/voice/v4");
800
+
801
+ // src/receive/AudioReceiveStream.ts
802
+ var import_node_stream = require("stream");
803
+
804
+ // src/audio/AudioPlayerError.ts
805
+ var AudioPlayerError = class extends Error {
806
+ constructor(error, resource) {
807
+ super(error.message);
808
+ __publicField(this, "resource");
809
+ this.resource = resource;
810
+ this.name = error.name;
811
+ this.stack = error.stack;
812
+ }
813
+ };
814
+ __name(AudioPlayerError, "AudioPlayerError");
815
+
816
+ // src/audio/PlayerSubscription.ts
817
+ var PlayerSubscription = class {
818
+ constructor(connection, player) {
819
+ __publicField(this, "connection");
820
+ __publicField(this, "player");
821
+ this.connection = connection;
822
+ this.player = player;
823
+ }
824
+ unsubscribe() {
825
+ this.connection["onSubscriptionRemoved"](this);
826
+ this.player["unsubscribe"](this);
827
+ }
828
+ };
829
+ __name(PlayerSubscription, "PlayerSubscription");
830
+
831
+ // src/audio/AudioPlayer.ts
832
+ var import_tiny_typed_emitter4 = require("tiny-typed-emitter");
833
+ var SILENCE_FRAME = Buffer.from([248, 255, 254]);
834
+ var NoSubscriberBehavior = /* @__PURE__ */ ((NoSubscriberBehavior2) => {
835
+ NoSubscriberBehavior2["Pause"] = "pause";
836
+ NoSubscriberBehavior2["Play"] = "play";
837
+ NoSubscriberBehavior2["Stop"] = "stop";
838
+ return NoSubscriberBehavior2;
839
+ })(NoSubscriberBehavior || {});
840
+ var AudioPlayerStatus = /* @__PURE__ */ ((AudioPlayerStatus2) => {
841
+ AudioPlayerStatus2["Idle"] = "idle";
842
+ AudioPlayerStatus2["Buffering"] = "buffering";
843
+ AudioPlayerStatus2["Paused"] = "paused";
844
+ AudioPlayerStatus2["Playing"] = "playing";
845
+ AudioPlayerStatus2["AutoPaused"] = "autopaused";
846
+ return AudioPlayerStatus2;
847
+ })(AudioPlayerStatus || {});
848
+ function stringifyState2(state) {
849
+ return JSON.stringify({
850
+ ...state,
851
+ resource: Reflect.has(state, "resource"),
852
+ stepTimeout: Reflect.has(state, "stepTimeout")
853
+ });
854
+ }
855
+ __name(stringifyState2, "stringifyState");
856
+ var AudioPlayer = class extends import_tiny_typed_emitter4.TypedEmitter {
857
+ constructor(options = {}) {
858
+ super();
859
+ __publicField(this, "_state");
860
+ __publicField(this, "subscribers", []);
861
+ __publicField(this, "behaviors");
862
+ __publicField(this, "debug");
863
+ this._state = { status: "idle" /* Idle */ };
864
+ this.behaviors = {
865
+ noSubscriber: "pause" /* Pause */,
866
+ maxMissedFrames: 5,
867
+ ...options.behaviors
868
+ };
869
+ this.debug = options.debug === false ? null : (message) => this.emit("debug", message);
870
+ }
871
+ get playable() {
872
+ return this.subscribers.filter(({ connection }) => connection.state.status === "ready" /* Ready */).map(({ connection }) => connection);
873
+ }
874
+ subscribe(connection) {
875
+ const existingSubscription = this.subscribers.find((subscription) => subscription.connection === connection);
876
+ if (!existingSubscription) {
877
+ const subscription = new PlayerSubscription(connection, this);
878
+ this.subscribers.push(subscription);
879
+ setImmediate(() => this.emit("subscribe", subscription));
880
+ return subscription;
881
+ }
882
+ return existingSubscription;
883
+ }
884
+ unsubscribe(subscription) {
885
+ const index = this.subscribers.indexOf(subscription);
886
+ const exists = index !== -1;
887
+ if (exists) {
888
+ this.subscribers.splice(index, 1);
889
+ subscription.connection.setSpeaking(false);
890
+ this.emit("unsubscribe", subscription);
891
+ }
892
+ return exists;
893
+ }
894
+ get state() {
895
+ return this._state;
896
+ }
897
+ set state(newState) {
898
+ const oldState = this._state;
899
+ const newResource = Reflect.get(newState, "resource");
900
+ if (oldState.status !== "idle" /* Idle */ && oldState.resource !== newResource) {
901
+ oldState.resource.playStream.on("error", noop);
902
+ oldState.resource.playStream.off("error", oldState.onStreamError);
903
+ oldState.resource.audioPlayer = void 0;
904
+ oldState.resource.playStream.destroy();
905
+ oldState.resource.playStream.read();
906
+ }
907
+ if (oldState.status === "buffering" /* Buffering */ && (newState.status !== "buffering" /* Buffering */ || newState.resource !== oldState.resource)) {
908
+ oldState.resource.playStream.off("end", oldState.onFailureCallback);
909
+ oldState.resource.playStream.off("close", oldState.onFailureCallback);
910
+ oldState.resource.playStream.off("finish", oldState.onFailureCallback);
911
+ oldState.resource.playStream.off("readable", oldState.onReadableCallback);
912
+ }
913
+ if (newState.status === "idle" /* Idle */) {
914
+ this._signalStopSpeaking();
915
+ deleteAudioPlayer(this);
916
+ }
917
+ if (newResource) {
918
+ addAudioPlayer(this);
919
+ }
920
+ const didChangeResources = oldState.status !== "idle" /* Idle */ && newState.status === "playing" /* Playing */ && oldState.resource !== newState.resource;
921
+ this._state = newState;
922
+ this.emit("stateChange", oldState, this._state);
923
+ if (oldState.status !== newState.status || didChangeResources) {
924
+ this.emit(newState.status, oldState, this._state);
925
+ }
926
+ this.debug?.(`state change:
927
+ from ${stringifyState2(oldState)}
928
+ to ${stringifyState2(newState)}`);
929
+ }
930
+ play(resource) {
931
+ if (resource.ended) {
932
+ throw new Error("Cannot play a resource that has already ended.");
933
+ }
934
+ if (resource.audioPlayer) {
935
+ if (resource.audioPlayer === this) {
936
+ return;
937
+ }
938
+ throw new Error("Resource is already being played by another audio player.");
939
+ }
940
+ resource.audioPlayer = this;
941
+ const onStreamError = /* @__PURE__ */ __name((error) => {
942
+ if (this.state.status !== "idle" /* Idle */) {
943
+ this.emit("error", new AudioPlayerError(error, this.state.resource));
944
+ }
945
+ if (this.state.status !== "idle" /* Idle */ && this.state.resource === resource) {
946
+ this.state = {
947
+ status: "idle" /* Idle */
948
+ };
949
+ }
950
+ }, "onStreamError");
951
+ resource.playStream.once("error", onStreamError);
952
+ if (resource.started) {
953
+ this.state = {
954
+ status: "playing" /* Playing */,
955
+ missedFrames: 0,
956
+ playbackDuration: 0,
957
+ resource,
958
+ onStreamError
959
+ };
960
+ } else {
961
+ const onReadableCallback = /* @__PURE__ */ __name(() => {
962
+ if (this.state.status === "buffering" /* Buffering */ && this.state.resource === resource) {
963
+ this.state = {
964
+ status: "playing" /* Playing */,
965
+ missedFrames: 0,
966
+ playbackDuration: 0,
967
+ resource,
968
+ onStreamError
969
+ };
970
+ }
971
+ }, "onReadableCallback");
972
+ const onFailureCallback = /* @__PURE__ */ __name(() => {
973
+ if (this.state.status === "buffering" /* Buffering */ && this.state.resource === resource) {
974
+ this.state = {
975
+ status: "idle" /* Idle */
976
+ };
977
+ }
978
+ }, "onFailureCallback");
979
+ resource.playStream.once("readable", onReadableCallback);
980
+ resource.playStream.once("end", onFailureCallback);
981
+ resource.playStream.once("close", onFailureCallback);
982
+ resource.playStream.once("finish", onFailureCallback);
983
+ this.state = {
984
+ status: "buffering" /* Buffering */,
985
+ resource,
986
+ onReadableCallback,
987
+ onFailureCallback,
988
+ onStreamError
989
+ };
990
+ }
991
+ }
992
+ pause(interpolateSilence = true) {
993
+ if (this.state.status !== "playing" /* Playing */)
994
+ return false;
995
+ this.state = {
996
+ ...this.state,
997
+ status: "paused" /* Paused */,
998
+ silencePacketsRemaining: interpolateSilence ? 5 : 0
999
+ };
1000
+ return true;
1001
+ }
1002
+ unpause() {
1003
+ if (this.state.status !== "paused" /* Paused */)
1004
+ return false;
1005
+ this.state = {
1006
+ ...this.state,
1007
+ status: "playing" /* Playing */,
1008
+ missedFrames: 0
1009
+ };
1010
+ return true;
1011
+ }
1012
+ stop(force = false) {
1013
+ if (this.state.status === "idle" /* Idle */)
1014
+ return false;
1015
+ if (force || this.state.resource.silencePaddingFrames === 0) {
1016
+ this.state = {
1017
+ status: "idle" /* Idle */
1018
+ };
1019
+ } else if (this.state.resource.silenceRemaining === -1) {
1020
+ this.state.resource.silenceRemaining = this.state.resource.silencePaddingFrames;
1021
+ }
1022
+ return true;
1023
+ }
1024
+ checkPlayable() {
1025
+ const state = this._state;
1026
+ if (state.status === "idle" /* Idle */ || state.status === "buffering" /* Buffering */)
1027
+ return false;
1028
+ if (!state.resource.readable) {
1029
+ this.state = {
1030
+ status: "idle" /* Idle */
1031
+ };
1032
+ return false;
1033
+ }
1034
+ return true;
1035
+ }
1036
+ _stepDispatch() {
1037
+ const state = this._state;
1038
+ if (state.status === "idle" /* Idle */ || state.status === "buffering" /* Buffering */)
1039
+ return;
1040
+ this.playable.forEach((connection) => connection.dispatchAudio());
1041
+ }
1042
+ _stepPrepare() {
1043
+ const state = this._state;
1044
+ if (state.status === "idle" /* Idle */ || state.status === "buffering" /* Buffering */)
1045
+ return;
1046
+ const playable = this.playable;
1047
+ if (state.status === "autopaused" /* AutoPaused */ && playable.length > 0) {
1048
+ this.state = {
1049
+ ...state,
1050
+ status: "playing" /* Playing */,
1051
+ missedFrames: 0
1052
+ };
1053
+ }
1054
+ if (state.status === "paused" /* Paused */ || state.status === "autopaused" /* AutoPaused */) {
1055
+ if (state.silencePacketsRemaining > 0) {
1056
+ state.silencePacketsRemaining--;
1057
+ this._preparePacket(SILENCE_FRAME, playable, state);
1058
+ if (state.silencePacketsRemaining === 0) {
1059
+ this._signalStopSpeaking();
1060
+ }
1061
+ }
1062
+ return;
1063
+ }
1064
+ if (playable.length === 0) {
1065
+ if (this.behaviors.noSubscriber === "pause" /* Pause */) {
1066
+ this.state = {
1067
+ ...state,
1068
+ status: "autopaused" /* AutoPaused */,
1069
+ silencePacketsRemaining: 5
1070
+ };
1071
+ return;
1072
+ } else if (this.behaviors.noSubscriber === "stop" /* Stop */) {
1073
+ this.stop(true);
1074
+ }
1075
+ }
1076
+ const packet = state.resource.read();
1077
+ if (state.status === "playing" /* Playing */) {
1078
+ if (packet) {
1079
+ this._preparePacket(packet, playable, state);
1080
+ state.missedFrames = 0;
1081
+ } else {
1082
+ this._preparePacket(SILENCE_FRAME, playable, state);
1083
+ state.missedFrames++;
1084
+ if (state.missedFrames >= this.behaviors.maxMissedFrames) {
1085
+ this.stop();
1086
+ }
1087
+ }
1088
+ }
1089
+ }
1090
+ _signalStopSpeaking() {
1091
+ return this.subscribers.forEach(({ connection }) => connection.setSpeaking(false));
1092
+ }
1093
+ _preparePacket(packet, receivers, state) {
1094
+ state.playbackDuration += 20;
1095
+ receivers.forEach((connection) => connection.prepareAudioPacket(packet));
1096
+ }
1097
+ };
1098
+ __name(AudioPlayer, "AudioPlayer");
1099
+ function createAudioPlayer(options) {
1100
+ return new AudioPlayer(options);
1101
+ }
1102
+ __name(createAudioPlayer, "createAudioPlayer");
1103
+
1104
+ // src/receive/AudioReceiveStream.ts
1105
+ var EndBehaviorType = /* @__PURE__ */ ((EndBehaviorType2) => {
1106
+ EndBehaviorType2[EndBehaviorType2["Manual"] = 0] = "Manual";
1107
+ EndBehaviorType2[EndBehaviorType2["AfterSilence"] = 1] = "AfterSilence";
1108
+ EndBehaviorType2[EndBehaviorType2["AfterInactivity"] = 2] = "AfterInactivity";
1109
+ return EndBehaviorType2;
1110
+ })(EndBehaviorType || {});
1111
+ function createDefaultAudioReceiveStreamOptions() {
1112
+ return {
1113
+ end: {
1114
+ behavior: 0 /* Manual */
1115
+ }
1116
+ };
1117
+ }
1118
+ __name(createDefaultAudioReceiveStreamOptions, "createDefaultAudioReceiveStreamOptions");
1119
+ var AudioReceiveStream = class extends import_node_stream.Readable {
1120
+ constructor({ end, ...options }) {
1121
+ super({
1122
+ ...options,
1123
+ objectMode: true
1124
+ });
1125
+ __publicField(this, "end");
1126
+ __publicField(this, "endTimeout");
1127
+ this.end = end;
1128
+ }
1129
+ push(buffer) {
1130
+ if (buffer) {
1131
+ if (this.end.behavior === 2 /* AfterInactivity */ || this.end.behavior === 1 /* AfterSilence */ && (buffer.compare(SILENCE_FRAME) !== 0 || typeof this.endTimeout === "undefined")) {
1132
+ this.renewEndTimeout(this.end);
1133
+ }
1134
+ }
1135
+ return super.push(buffer);
1136
+ }
1137
+ renewEndTimeout(end) {
1138
+ if (this.endTimeout) {
1139
+ clearTimeout(this.endTimeout);
1140
+ }
1141
+ this.endTimeout = setTimeout(() => this.push(null), end.duration);
1142
+ }
1143
+ _read() {
1144
+ }
1145
+ };
1146
+ __name(AudioReceiveStream, "AudioReceiveStream");
1147
+
1148
+ // src/receive/SpeakingMap.ts
1149
+ var import_tiny_typed_emitter5 = require("tiny-typed-emitter");
1150
+ var _SpeakingMap = class extends import_tiny_typed_emitter5.TypedEmitter {
1151
+ constructor() {
1152
+ super();
1153
+ __publicField(this, "users");
1154
+ __publicField(this, "speakingTimeouts");
1155
+ this.users = /* @__PURE__ */ new Map();
1156
+ this.speakingTimeouts = /* @__PURE__ */ new Map();
1157
+ }
1158
+ onPacket(userId) {
1159
+ const timeout = this.speakingTimeouts.get(userId);
1160
+ if (timeout) {
1161
+ clearTimeout(timeout);
1162
+ } else {
1163
+ this.users.set(userId, Date.now());
1164
+ this.emit("start", userId);
1165
+ }
1166
+ this.startTimeout(userId);
1167
+ }
1168
+ startTimeout(userId) {
1169
+ this.speakingTimeouts.set(userId, setTimeout(() => {
1170
+ this.emit("end", userId);
1171
+ this.speakingTimeouts.delete(userId);
1172
+ this.users.delete(userId);
1173
+ }, _SpeakingMap.DELAY));
1174
+ }
1175
+ };
1176
+ var SpeakingMap = _SpeakingMap;
1177
+ __name(SpeakingMap, "SpeakingMap");
1178
+ __publicField(SpeakingMap, "DELAY", 100);
1179
+
1180
+ // src/receive/SSRCMap.ts
1181
+ var import_tiny_typed_emitter6 = require("tiny-typed-emitter");
1182
+ var SSRCMap = class extends import_tiny_typed_emitter6.TypedEmitter {
1183
+ constructor() {
1184
+ super();
1185
+ __publicField(this, "map");
1186
+ this.map = /* @__PURE__ */ new Map();
1187
+ }
1188
+ update(data) {
1189
+ const existing = this.map.get(data.audioSSRC);
1190
+ const newValue = {
1191
+ ...this.map.get(data.audioSSRC),
1192
+ ...data
1193
+ };
1194
+ this.map.set(data.audioSSRC, newValue);
1195
+ if (!existing)
1196
+ this.emit("create", newValue);
1197
+ this.emit("update", existing, newValue);
1198
+ }
1199
+ get(target) {
1200
+ if (typeof target === "number") {
1201
+ return this.map.get(target);
1202
+ }
1203
+ for (const data of this.map.values()) {
1204
+ if (data.userId === target) {
1205
+ return data;
1206
+ }
1207
+ }
1208
+ return void 0;
1209
+ }
1210
+ delete(target) {
1211
+ if (typeof target === "number") {
1212
+ const existing = this.map.get(target);
1213
+ if (existing) {
1214
+ this.map.delete(target);
1215
+ this.emit("delete", existing);
1216
+ }
1217
+ return existing;
1218
+ }
1219
+ for (const [audioSSRC, data] of this.map.entries()) {
1220
+ if (data.userId === target) {
1221
+ this.map.delete(audioSSRC);
1222
+ this.emit("delete", data);
1223
+ return data;
1224
+ }
1225
+ }
1226
+ return void 0;
1227
+ }
1228
+ };
1229
+ __name(SSRCMap, "SSRCMap");
1230
+
1231
+ // src/receive/VoiceReceiver.ts
1232
+ var VoiceReceiver = class {
1233
+ constructor(voiceConnection) {
1234
+ __publicField(this, "voiceConnection");
1235
+ __publicField(this, "ssrcMap");
1236
+ __publicField(this, "subscriptions");
1237
+ __publicField(this, "connectionData");
1238
+ __publicField(this, "speaking");
1239
+ this.voiceConnection = voiceConnection;
1240
+ this.ssrcMap = new SSRCMap();
1241
+ this.speaking = new SpeakingMap();
1242
+ this.subscriptions = /* @__PURE__ */ new Map();
1243
+ this.connectionData = {};
1244
+ this.onWsPacket = this.onWsPacket.bind(this);
1245
+ this.onUdpMessage = this.onUdpMessage.bind(this);
1246
+ }
1247
+ onWsPacket(packet) {
1248
+ if (packet.op === import_v43.VoiceOpcodes.ClientDisconnect && typeof packet.d?.user_id === "string") {
1249
+ this.ssrcMap.delete(packet.d.user_id);
1250
+ } else if (packet.op === import_v43.VoiceOpcodes.Speaking && typeof packet.d?.user_id === "string" && typeof packet.d?.ssrc === "number") {
1251
+ this.ssrcMap.update({ userId: packet.d.user_id, audioSSRC: packet.d.ssrc });
1252
+ } else if (packet.op === import_v43.VoiceOpcodes.ClientConnect && typeof packet.d?.user_id === "string" && typeof packet.d?.audio_ssrc === "number") {
1253
+ this.ssrcMap.update({
1254
+ userId: packet.d.user_id,
1255
+ audioSSRC: packet.d.audio_ssrc,
1256
+ videoSSRC: packet.d.video_ssrc === 0 ? void 0 : packet.d.video_ssrc
1257
+ });
1258
+ }
1259
+ }
1260
+ decrypt(buffer, mode, nonce2, secretKey) {
1261
+ let end;
1262
+ if (mode === "xsalsa20_poly1305_lite") {
1263
+ buffer.copy(nonce2, 0, buffer.length - 4);
1264
+ end = buffer.length - 4;
1265
+ } else if (mode === "xsalsa20_poly1305_suffix") {
1266
+ buffer.copy(nonce2, 0, buffer.length - 24);
1267
+ end = buffer.length - 24;
1268
+ } else {
1269
+ buffer.copy(nonce2, 0, 0, 12);
1270
+ }
1271
+ const decrypted = methods.open(buffer.slice(12, end), nonce2, secretKey);
1272
+ if (!decrypted)
1273
+ return;
1274
+ return Buffer.from(decrypted);
1275
+ }
1276
+ parsePacket(buffer, mode, nonce2, secretKey) {
1277
+ let packet = this.decrypt(buffer, mode, nonce2, secretKey);
1278
+ if (!packet)
1279
+ return;
1280
+ if (packet[0] === 190 && packet[1] === 222 && packet.length > 4) {
1281
+ const headerExtensionLength = packet.readUInt16BE(2);
1282
+ let offset = 4;
1283
+ for (let i = 0; i < headerExtensionLength; i++) {
1284
+ const byte2 = packet[offset];
1285
+ offset++;
1286
+ if (byte2 === 0)
1287
+ continue;
1288
+ offset += 1 + (byte2 >> 4);
1289
+ }
1290
+ const byte = packet.readUInt8(offset);
1291
+ if (byte === 0 || byte === 2)
1292
+ offset++;
1293
+ packet = packet.slice(offset);
1294
+ }
1295
+ return packet;
1296
+ }
1297
+ onUdpMessage(msg) {
1298
+ if (msg.length <= 8)
1299
+ return;
1300
+ const ssrc = msg.readUInt32BE(8);
1301
+ const userData = this.ssrcMap.get(ssrc);
1302
+ if (!userData)
1303
+ return;
1304
+ this.speaking.onPacket(userData.userId);
1305
+ const stream = this.subscriptions.get(userData.userId);
1306
+ if (!stream)
1307
+ return;
1308
+ if (this.connectionData.encryptionMode && this.connectionData.nonceBuffer && this.connectionData.secretKey) {
1309
+ const packet = this.parsePacket(msg, this.connectionData.encryptionMode, this.connectionData.nonceBuffer, this.connectionData.secretKey);
1310
+ if (packet) {
1311
+ stream.push(packet);
1312
+ } else {
1313
+ stream.destroy(new Error("Failed to parse packet"));
1314
+ }
1315
+ }
1316
+ }
1317
+ subscribe(userId, options) {
1318
+ const existing = this.subscriptions.get(userId);
1319
+ if (existing)
1320
+ return existing;
1321
+ const stream = new AudioReceiveStream({
1322
+ ...createDefaultAudioReceiveStreamOptions(),
1323
+ ...options
1324
+ });
1325
+ stream.once("close", () => this.subscriptions.delete(userId));
1326
+ this.subscriptions.set(userId, stream);
1327
+ return stream;
1328
+ }
1329
+ };
1330
+ __name(VoiceReceiver, "VoiceReceiver");
1331
+
1332
+ // src/VoiceConnection.ts
1333
+ var VoiceConnectionStatus = /* @__PURE__ */ ((VoiceConnectionStatus2) => {
1334
+ VoiceConnectionStatus2["Signalling"] = "signalling";
1335
+ VoiceConnectionStatus2["Connecting"] = "connecting";
1336
+ VoiceConnectionStatus2["Ready"] = "ready";
1337
+ VoiceConnectionStatus2["Disconnected"] = "disconnected";
1338
+ VoiceConnectionStatus2["Destroyed"] = "destroyed";
1339
+ return VoiceConnectionStatus2;
1340
+ })(VoiceConnectionStatus || {});
1341
+ var VoiceConnectionDisconnectReason = /* @__PURE__ */ ((VoiceConnectionDisconnectReason2) => {
1342
+ VoiceConnectionDisconnectReason2[VoiceConnectionDisconnectReason2["WebSocketClose"] = 0] = "WebSocketClose";
1343
+ VoiceConnectionDisconnectReason2[VoiceConnectionDisconnectReason2["AdapterUnavailable"] = 1] = "AdapterUnavailable";
1344
+ VoiceConnectionDisconnectReason2[VoiceConnectionDisconnectReason2["EndpointRemoved"] = 2] = "EndpointRemoved";
1345
+ VoiceConnectionDisconnectReason2[VoiceConnectionDisconnectReason2["Manual"] = 3] = "Manual";
1346
+ return VoiceConnectionDisconnectReason2;
1347
+ })(VoiceConnectionDisconnectReason || {});
1348
+ var VoiceConnection2 = class extends import_tiny_typed_emitter7.TypedEmitter {
1349
+ constructor(joinConfig, { debug, adapterCreator }) {
1350
+ super();
1351
+ __publicField(this, "rejoinAttempts");
1352
+ __publicField(this, "_state");
1353
+ __publicField(this, "joinConfig");
1354
+ __publicField(this, "packets");
1355
+ __publicField(this, "receiver");
1356
+ __publicField(this, "debug");
1357
+ this.debug = debug ? (message) => this.emit("debug", message) : null;
1358
+ this.rejoinAttempts = 0;
1359
+ this.receiver = new VoiceReceiver(this);
1360
+ this.onNetworkingClose = this.onNetworkingClose.bind(this);
1361
+ this.onNetworkingStateChange = this.onNetworkingStateChange.bind(this);
1362
+ this.onNetworkingError = this.onNetworkingError.bind(this);
1363
+ this.onNetworkingDebug = this.onNetworkingDebug.bind(this);
1364
+ const adapter = adapterCreator({
1365
+ onVoiceServerUpdate: (data) => this.addServerPacket(data),
1366
+ onVoiceStateUpdate: (data) => this.addStatePacket(data),
1367
+ destroy: () => this.destroy(false)
1368
+ });
1369
+ this._state = { status: "signalling" /* Signalling */, adapter };
1370
+ this.packets = {
1371
+ server: void 0,
1372
+ state: void 0
1373
+ };
1374
+ this.joinConfig = joinConfig;
1375
+ }
1376
+ get state() {
1377
+ return this._state;
1378
+ }
1379
+ set state(newState) {
1380
+ const oldState = this._state;
1381
+ const oldNetworking = Reflect.get(oldState, "networking");
1382
+ const newNetworking = Reflect.get(newState, "networking");
1383
+ const oldSubscription = Reflect.get(oldState, "subscription");
1384
+ const newSubscription = Reflect.get(newState, "subscription");
1385
+ if (oldNetworking !== newNetworking) {
1386
+ if (oldNetworking) {
1387
+ oldNetworking.on("error", noop);
1388
+ oldNetworking.off("debug", this.onNetworkingDebug);
1389
+ oldNetworking.off("error", this.onNetworkingError);
1390
+ oldNetworking.off("close", this.onNetworkingClose);
1391
+ oldNetworking.off("stateChange", this.onNetworkingStateChange);
1392
+ oldNetworking.destroy();
1393
+ }
1394
+ if (newNetworking)
1395
+ this.updateReceiveBindings(newNetworking.state, oldNetworking?.state);
1396
+ }
1397
+ if (newState.status === "ready" /* Ready */) {
1398
+ this.rejoinAttempts = 0;
1399
+ } else if (newState.status === "destroyed" /* Destroyed */) {
1400
+ for (const stream of this.receiver.subscriptions.values()) {
1401
+ if (!stream.destroyed)
1402
+ stream.destroy();
1403
+ }
1404
+ }
1405
+ if (oldState.status !== "destroyed" /* Destroyed */ && newState.status === "destroyed" /* Destroyed */) {
1406
+ oldState.adapter.destroy();
1407
+ }
1408
+ this._state = newState;
1409
+ if (oldSubscription && oldSubscription !== newSubscription) {
1410
+ oldSubscription.unsubscribe();
1411
+ }
1412
+ this.emit("stateChange", oldState, newState);
1413
+ if (oldState.status !== newState.status) {
1414
+ this.emit(newState.status, oldState, newState);
1415
+ }
1416
+ }
1417
+ addServerPacket(packet) {
1418
+ this.packets.server = packet;
1419
+ if (packet.endpoint) {
1420
+ this.configureNetworking();
1421
+ } else if (this.state.status !== "destroyed" /* Destroyed */) {
1422
+ this.state = {
1423
+ ...this.state,
1424
+ status: "disconnected" /* Disconnected */,
1425
+ reason: 2 /* EndpointRemoved */
1426
+ };
1427
+ }
1428
+ }
1429
+ addStatePacket(packet) {
1430
+ this.packets.state = packet;
1431
+ if (typeof packet.self_deaf !== "undefined")
1432
+ this.joinConfig.selfDeaf = packet.self_deaf;
1433
+ if (typeof packet.self_mute !== "undefined")
1434
+ this.joinConfig.selfMute = packet.self_mute;
1435
+ if (packet.channel_id)
1436
+ this.joinConfig.channelId = packet.channel_id;
1437
+ }
1438
+ updateReceiveBindings(newState, oldState) {
1439
+ const oldWs = Reflect.get(oldState ?? {}, "ws");
1440
+ const newWs = Reflect.get(newState, "ws");
1441
+ const oldUdp = Reflect.get(oldState ?? {}, "udp");
1442
+ const newUdp = Reflect.get(newState, "udp");
1443
+ if (oldWs !== newWs) {
1444
+ oldWs?.off("packet", this.receiver.onWsPacket);
1445
+ newWs?.on("packet", this.receiver.onWsPacket);
1446
+ }
1447
+ if (oldUdp !== newUdp) {
1448
+ oldUdp?.off("message", this.receiver.onUdpMessage);
1449
+ newUdp?.on("message", this.receiver.onUdpMessage);
1450
+ }
1451
+ this.receiver.connectionData = Reflect.get(newState, "connectionData") ?? {};
1452
+ }
1453
+ configureNetworking() {
1454
+ const { server, state } = this.packets;
1455
+ if (!server || !state || this.state.status === "destroyed" /* Destroyed */ || !server.endpoint)
1456
+ return;
1457
+ const networking = new Networking({
1458
+ endpoint: server.endpoint,
1459
+ serverId: server.guild_id,
1460
+ token: server.token,
1461
+ sessionId: state.session_id,
1462
+ userId: state.user_id
1463
+ }, Boolean(this.debug));
1464
+ networking.once("close", this.onNetworkingClose);
1465
+ networking.on("stateChange", this.onNetworkingStateChange);
1466
+ networking.on("error", this.onNetworkingError);
1467
+ networking.on("debug", this.onNetworkingDebug);
1468
+ this.state = {
1469
+ ...this.state,
1470
+ status: "connecting" /* Connecting */,
1471
+ networking
1472
+ };
1473
+ }
1474
+ onNetworkingClose(code) {
1475
+ if (this.state.status === "destroyed" /* Destroyed */)
1476
+ return;
1477
+ if (code === 4014) {
1478
+ this.state = {
1479
+ ...this.state,
1480
+ status: "disconnected" /* Disconnected */,
1481
+ reason: 0 /* WebSocketClose */,
1482
+ closeCode: code
1483
+ };
1484
+ } else {
1485
+ this.state = {
1486
+ ...this.state,
1487
+ status: "signalling" /* Signalling */
1488
+ };
1489
+ this.rejoinAttempts++;
1490
+ if (!this.state.adapter.sendPayload(createJoinVoiceChannelPayload(this.joinConfig))) {
1491
+ this.state = {
1492
+ ...this.state,
1493
+ status: "disconnected" /* Disconnected */,
1494
+ reason: 1 /* AdapterUnavailable */
1495
+ };
1496
+ }
1497
+ }
1498
+ }
1499
+ onNetworkingStateChange(oldState, newState) {
1500
+ this.updateReceiveBindings(newState, oldState);
1501
+ if (oldState.code === newState.code)
1502
+ return;
1503
+ if (this.state.status !== "connecting" /* Connecting */ && this.state.status !== "ready" /* Ready */)
1504
+ return;
1505
+ if (newState.code === 4 /* Ready */) {
1506
+ this.state = {
1507
+ ...this.state,
1508
+ status: "ready" /* Ready */
1509
+ };
1510
+ } else if (newState.code !== 6 /* Closed */) {
1511
+ this.state = {
1512
+ ...this.state,
1513
+ status: "connecting" /* Connecting */
1514
+ };
1515
+ }
1516
+ }
1517
+ onNetworkingError(error) {
1518
+ this.emit("error", error);
1519
+ }
1520
+ onNetworkingDebug(message) {
1521
+ this.debug?.(`[NW] ${message}`);
1522
+ }
1523
+ prepareAudioPacket(buffer) {
1524
+ const state = this.state;
1525
+ if (state.status !== "ready" /* Ready */)
1526
+ return;
1527
+ return state.networking.prepareAudioPacket(buffer);
1528
+ }
1529
+ dispatchAudio() {
1530
+ const state = this.state;
1531
+ if (state.status !== "ready" /* Ready */)
1532
+ return;
1533
+ return state.networking.dispatchAudio();
1534
+ }
1535
+ playOpusPacket(buffer) {
1536
+ const state = this.state;
1537
+ if (state.status !== "ready" /* Ready */)
1538
+ return;
1539
+ state.networking.prepareAudioPacket(buffer);
1540
+ return state.networking.dispatchAudio();
1541
+ }
1542
+ destroy(adapterAvailable = true) {
1543
+ if (this.state.status === "destroyed" /* Destroyed */) {
1544
+ throw new Error("Cannot destroy VoiceConnection - it has already been destroyed");
1545
+ }
1546
+ if (getVoiceConnection(this.joinConfig.guildId, this.joinConfig.group) === this) {
1547
+ untrackVoiceConnection(this);
1548
+ }
1549
+ if (adapterAvailable) {
1550
+ this.state.adapter.sendPayload(createJoinVoiceChannelPayload({ ...this.joinConfig, channelId: null }));
1551
+ }
1552
+ this.state = {
1553
+ status: "destroyed" /* Destroyed */
1554
+ };
1555
+ }
1556
+ disconnect() {
1557
+ if (this.state.status === "destroyed" /* Destroyed */ || this.state.status === "signalling" /* Signalling */) {
1558
+ return false;
1559
+ }
1560
+ this.joinConfig.channelId = null;
1561
+ if (!this.state.adapter.sendPayload(createJoinVoiceChannelPayload(this.joinConfig))) {
1562
+ this.state = {
1563
+ adapter: this.state.adapter,
1564
+ subscription: this.state.subscription,
1565
+ status: "disconnected" /* Disconnected */,
1566
+ reason: 1 /* AdapterUnavailable */
1567
+ };
1568
+ return false;
1569
+ }
1570
+ this.state = {
1571
+ adapter: this.state.adapter,
1572
+ reason: 3 /* Manual */,
1573
+ status: "disconnected" /* Disconnected */
1574
+ };
1575
+ return true;
1576
+ }
1577
+ rejoin(joinConfig) {
1578
+ if (this.state.status === "destroyed" /* Destroyed */) {
1579
+ return false;
1580
+ }
1581
+ const notReady = this.state.status !== "ready" /* Ready */;
1582
+ if (notReady)
1583
+ this.rejoinAttempts++;
1584
+ Object.assign(this.joinConfig, joinConfig);
1585
+ if (this.state.adapter.sendPayload(createJoinVoiceChannelPayload(this.joinConfig))) {
1586
+ if (notReady) {
1587
+ this.state = {
1588
+ ...this.state,
1589
+ status: "signalling" /* Signalling */
1590
+ };
1591
+ }
1592
+ return true;
1593
+ }
1594
+ this.state = {
1595
+ adapter: this.state.adapter,
1596
+ subscription: this.state.subscription,
1597
+ status: "disconnected" /* Disconnected */,
1598
+ reason: 1 /* AdapterUnavailable */
1599
+ };
1600
+ return false;
1601
+ }
1602
+ setSpeaking(enabled) {
1603
+ if (this.state.status !== "ready" /* Ready */)
1604
+ return false;
1605
+ return this.state.networking.setSpeaking(enabled);
1606
+ }
1607
+ subscribe(player) {
1608
+ if (this.state.status === "destroyed" /* Destroyed */)
1609
+ return;
1610
+ const subscription = player["subscribe"](this);
1611
+ this.state = {
1612
+ ...this.state,
1613
+ subscription
1614
+ };
1615
+ return subscription;
1616
+ }
1617
+ get ping() {
1618
+ if (this.state.status === "ready" /* Ready */ && this.state.networking.state.code === 4 /* Ready */) {
1619
+ return {
1620
+ ws: this.state.networking.state.ws.ping,
1621
+ udp: this.state.networking.state.udp.ping
1622
+ };
1623
+ }
1624
+ return {
1625
+ ws: void 0,
1626
+ udp: void 0
1627
+ };
1628
+ }
1629
+ onSubscriptionRemoved(subscription) {
1630
+ if (this.state.status !== "destroyed" /* Destroyed */ && this.state.subscription === subscription) {
1631
+ this.state = {
1632
+ ...this.state,
1633
+ subscription: void 0
1634
+ };
1635
+ }
1636
+ }
1637
+ };
1638
+ __name(VoiceConnection2, "VoiceConnection");
1639
+ function createVoiceConnection(joinConfig, options) {
1640
+ const payload = createJoinVoiceChannelPayload(joinConfig);
1641
+ const existing = getVoiceConnection(joinConfig.guildId, joinConfig.group);
1642
+ if (existing && existing.state.status !== "destroyed" /* Destroyed */) {
1643
+ if (existing.state.status === "disconnected" /* Disconnected */) {
1644
+ existing.rejoin({
1645
+ channelId: joinConfig.channelId,
1646
+ selfDeaf: joinConfig.selfDeaf,
1647
+ selfMute: joinConfig.selfMute
1648
+ });
1649
+ } else if (!existing.state.adapter.sendPayload(payload)) {
1650
+ existing.state = {
1651
+ ...existing.state,
1652
+ status: "disconnected" /* Disconnected */,
1653
+ reason: 1 /* AdapterUnavailable */
1654
+ };
1655
+ }
1656
+ return existing;
1657
+ }
1658
+ const voiceConnection = new VoiceConnection2(joinConfig, options);
1659
+ trackVoiceConnection(voiceConnection);
1660
+ if (voiceConnection.state.status !== "destroyed" /* Destroyed */) {
1661
+ if (!voiceConnection.state.adapter.sendPayload(payload)) {
1662
+ voiceConnection.state = {
1663
+ ...voiceConnection.state,
1664
+ status: "disconnected" /* Disconnected */,
1665
+ reason: 1 /* AdapterUnavailable */
1666
+ };
1667
+ }
1668
+ }
1669
+ return voiceConnection;
1670
+ }
1671
+ __name(createVoiceConnection, "createVoiceConnection");
1672
+
1673
+ // src/joinVoiceChannel.ts
1674
+ function joinVoiceChannel(options) {
1675
+ const joinConfig = {
1676
+ selfDeaf: true,
1677
+ selfMute: false,
1678
+ group: "default",
1679
+ ...options
1680
+ };
1681
+ return createVoiceConnection(joinConfig, {
1682
+ adapterCreator: options.adapterCreator,
1683
+ debug: options.debug
1684
+ });
1685
+ }
1686
+ __name(joinVoiceChannel, "joinVoiceChannel");
1687
+
1688
+ // src/audio/TransformerGraph.ts
1689
+ var import_prism_media = __toESM(require("prism-media"));
1690
+ var FFMPEG_PCM_ARGUMENTS = ["-analyzeduration", "0", "-loglevel", "0", "-f", "s16le", "-ar", "48000", "-ac", "2"];
1691
+ var FFMPEG_OPUS_ARGUMENTS = [
1692
+ "-analyzeduration",
1693
+ "0",
1694
+ "-loglevel",
1695
+ "0",
1696
+ "-acodec",
1697
+ "libopus",
1698
+ "-f",
1699
+ "opus",
1700
+ "-ar",
1701
+ "48000",
1702
+ "-ac",
1703
+ "2"
1704
+ ];
1705
+ var StreamType = /* @__PURE__ */ ((StreamType2) => {
1706
+ StreamType2["Arbitrary"] = "arbitrary";
1707
+ StreamType2["Raw"] = "raw";
1708
+ StreamType2["OggOpus"] = "ogg/opus";
1709
+ StreamType2["WebmOpus"] = "webm/opus";
1710
+ StreamType2["Opus"] = "opus";
1711
+ return StreamType2;
1712
+ })(StreamType || {});
1713
+ var Node = class {
1714
+ constructor(type) {
1715
+ __publicField(this, "edges", []);
1716
+ __publicField(this, "type");
1717
+ this.type = type;
1718
+ }
1719
+ addEdge(edge) {
1720
+ this.edges.push({ ...edge, from: this });
1721
+ }
1722
+ };
1723
+ __name(Node, "Node");
1724
+ var NODES = /* @__PURE__ */ new Map();
1725
+ for (const streamType of Object.values(StreamType)) {
1726
+ NODES.set(streamType, new Node(streamType));
1727
+ }
1728
+ function getNode(type) {
1729
+ const node = NODES.get(type);
1730
+ if (!node)
1731
+ throw new Error(`Node type '${type}' does not exist!`);
1732
+ return node;
1733
+ }
1734
+ __name(getNode, "getNode");
1735
+ getNode("raw" /* Raw */).addEdge({
1736
+ type: "opus encoder" /* OpusEncoder */,
1737
+ to: getNode("opus" /* Opus */),
1738
+ cost: 1.5,
1739
+ transformer: () => new import_prism_media.default.opus.Encoder({ rate: 48e3, channels: 2, frameSize: 960 })
1740
+ });
1741
+ getNode("opus" /* Opus */).addEdge({
1742
+ type: "opus decoder" /* OpusDecoder */,
1743
+ to: getNode("raw" /* Raw */),
1744
+ cost: 1.5,
1745
+ transformer: () => new import_prism_media.default.opus.Decoder({ rate: 48e3, channels: 2, frameSize: 960 })
1746
+ });
1747
+ getNode("ogg/opus" /* OggOpus */).addEdge({
1748
+ type: "ogg/opus demuxer" /* OggOpusDemuxer */,
1749
+ to: getNode("opus" /* Opus */),
1750
+ cost: 1,
1751
+ transformer: () => new import_prism_media.default.opus.OggDemuxer()
1752
+ });
1753
+ getNode("webm/opus" /* WebmOpus */).addEdge({
1754
+ type: "webm/opus demuxer" /* WebmOpusDemuxer */,
1755
+ to: getNode("opus" /* Opus */),
1756
+ cost: 1,
1757
+ transformer: () => new import_prism_media.default.opus.WebmDemuxer()
1758
+ });
1759
+ var FFMPEG_PCM_EDGE = {
1760
+ type: "ffmpeg pcm" /* FFmpegPCM */,
1761
+ to: getNode("raw" /* Raw */),
1762
+ cost: 2,
1763
+ transformer: (input) => new import_prism_media.default.FFmpeg({
1764
+ args: typeof input === "string" ? ["-i", input, ...FFMPEG_PCM_ARGUMENTS] : FFMPEG_PCM_ARGUMENTS
1765
+ })
1766
+ };
1767
+ getNode("arbitrary" /* Arbitrary */).addEdge(FFMPEG_PCM_EDGE);
1768
+ getNode("ogg/opus" /* OggOpus */).addEdge(FFMPEG_PCM_EDGE);
1769
+ getNode("webm/opus" /* WebmOpus */).addEdge(FFMPEG_PCM_EDGE);
1770
+ getNode("raw" /* Raw */).addEdge({
1771
+ type: "volume transformer" /* InlineVolume */,
1772
+ to: getNode("raw" /* Raw */),
1773
+ cost: 0.5,
1774
+ transformer: () => new import_prism_media.default.VolumeTransformer({ type: "s16le" })
1775
+ });
1776
+ function canEnableFFmpegOptimizations() {
1777
+ try {
1778
+ return import_prism_media.default.FFmpeg.getInfo().output.includes("--enable-libopus");
1779
+ } catch {
1780
+ }
1781
+ return false;
1782
+ }
1783
+ __name(canEnableFFmpegOptimizations, "canEnableFFmpegOptimizations");
1784
+ if (canEnableFFmpegOptimizations()) {
1785
+ const FFMPEG_OGG_EDGE = {
1786
+ type: "ffmpeg ogg" /* FFmpegOgg */,
1787
+ to: getNode("ogg/opus" /* OggOpus */),
1788
+ cost: 2,
1789
+ transformer: (input) => new import_prism_media.default.FFmpeg({
1790
+ args: typeof input === "string" ? ["-i", input, ...FFMPEG_OPUS_ARGUMENTS] : FFMPEG_OPUS_ARGUMENTS
1791
+ })
1792
+ };
1793
+ getNode("arbitrary" /* Arbitrary */).addEdge(FFMPEG_OGG_EDGE);
1794
+ getNode("ogg/opus" /* OggOpus */).addEdge(FFMPEG_OGG_EDGE);
1795
+ getNode("webm/opus" /* WebmOpus */).addEdge(FFMPEG_OGG_EDGE);
1796
+ }
1797
+ function findPath(from, constraints, goal = getNode("opus" /* Opus */), path = [], depth = 5) {
1798
+ if (from === goal && constraints(path)) {
1799
+ return { cost: 0 };
1800
+ } else if (depth === 0) {
1801
+ return { cost: Infinity };
1802
+ }
1803
+ let currentBest = void 0;
1804
+ for (const edge of from.edges) {
1805
+ if (currentBest && edge.cost > currentBest.cost)
1806
+ continue;
1807
+ const next = findPath(edge.to, constraints, goal, [...path, edge], depth - 1);
1808
+ const cost = edge.cost + next.cost;
1809
+ if (!currentBest || cost < currentBest.cost) {
1810
+ currentBest = { cost, edge, next };
1811
+ }
1812
+ }
1813
+ return currentBest ?? { cost: Infinity };
1814
+ }
1815
+ __name(findPath, "findPath");
1816
+ function constructPipeline(step) {
1817
+ const edges = [];
1818
+ let current = step;
1819
+ while (current?.edge) {
1820
+ edges.push(current.edge);
1821
+ current = current.next;
1822
+ }
1823
+ return edges;
1824
+ }
1825
+ __name(constructPipeline, "constructPipeline");
1826
+ function findPipeline(from, constraint) {
1827
+ return constructPipeline(findPath(getNode(from), constraint));
1828
+ }
1829
+ __name(findPipeline, "findPipeline");
1830
+
1831
+ // src/audio/AudioResource.ts
1832
+ var import_node_stream2 = require("stream");
1833
+ var import_prism_media2 = __toESM(require("prism-media"));
1834
+ var AudioResource = class {
1835
+ constructor(edges, streams, metadata, silencePaddingFrames) {
1836
+ __publicField(this, "playStream");
1837
+ __publicField(this, "edges");
1838
+ __publicField(this, "metadata");
1839
+ __publicField(this, "volume");
1840
+ __publicField(this, "encoder");
1841
+ __publicField(this, "audioPlayer");
1842
+ __publicField(this, "playbackDuration", 0);
1843
+ __publicField(this, "started", false);
1844
+ __publicField(this, "silencePaddingFrames");
1845
+ __publicField(this, "silenceRemaining", -1);
1846
+ this.edges = edges;
1847
+ this.playStream = streams.length > 1 ? (0, import_node_stream2.pipeline)(streams, noop) : streams[0];
1848
+ this.metadata = metadata;
1849
+ this.silencePaddingFrames = silencePaddingFrames;
1850
+ for (const stream of streams) {
1851
+ if (stream instanceof import_prism_media2.default.VolumeTransformer) {
1852
+ this.volume = stream;
1853
+ } else if (stream instanceof import_prism_media2.default.opus.Encoder) {
1854
+ this.encoder = stream;
1855
+ }
1856
+ }
1857
+ this.playStream.once("readable", () => this.started = true);
1858
+ }
1859
+ get readable() {
1860
+ if (this.silenceRemaining === 0)
1861
+ return false;
1862
+ const real = this.playStream.readable;
1863
+ if (!real) {
1864
+ if (this.silenceRemaining === -1)
1865
+ this.silenceRemaining = this.silencePaddingFrames;
1866
+ return this.silenceRemaining !== 0;
1867
+ }
1868
+ return real;
1869
+ }
1870
+ get ended() {
1871
+ return this.playStream.readableEnded || this.playStream.destroyed || this.silenceRemaining === 0;
1872
+ }
1873
+ read() {
1874
+ if (this.silenceRemaining === 0) {
1875
+ return null;
1876
+ } else if (this.silenceRemaining > 0) {
1877
+ this.silenceRemaining--;
1878
+ return SILENCE_FRAME;
1879
+ }
1880
+ const packet = this.playStream.read();
1881
+ if (packet) {
1882
+ this.playbackDuration += 20;
1883
+ }
1884
+ return packet;
1885
+ }
1886
+ };
1887
+ __name(AudioResource, "AudioResource");
1888
+ var VOLUME_CONSTRAINT = /* @__PURE__ */ __name((path) => path.some((edge) => edge.type === "volume transformer" /* InlineVolume */), "VOLUME_CONSTRAINT");
1889
+ var NO_CONSTRAINT = /* @__PURE__ */ __name(() => true, "NO_CONSTRAINT");
1890
+ function inferStreamType(stream) {
1891
+ if (stream instanceof import_prism_media2.default.opus.Encoder) {
1892
+ return { streamType: "opus" /* Opus */, hasVolume: false };
1893
+ } else if (stream instanceof import_prism_media2.default.opus.Decoder) {
1894
+ return { streamType: "raw" /* Raw */, hasVolume: false };
1895
+ } else if (stream instanceof import_prism_media2.default.VolumeTransformer) {
1896
+ return { streamType: "raw" /* Raw */, hasVolume: true };
1897
+ } else if (stream instanceof import_prism_media2.default.opus.OggDemuxer) {
1898
+ return { streamType: "opus" /* Opus */, hasVolume: false };
1899
+ } else if (stream instanceof import_prism_media2.default.opus.WebmDemuxer) {
1900
+ return { streamType: "opus" /* Opus */, hasVolume: false };
1901
+ }
1902
+ return { streamType: "arbitrary" /* Arbitrary */, hasVolume: false };
1903
+ }
1904
+ __name(inferStreamType, "inferStreamType");
1905
+ function createAudioResource(input, options = {}) {
1906
+ let inputType = options.inputType;
1907
+ let needsInlineVolume = Boolean(options.inlineVolume);
1908
+ if (typeof input === "string") {
1909
+ inputType = "arbitrary" /* Arbitrary */;
1910
+ } else if (typeof inputType === "undefined") {
1911
+ const analysis = inferStreamType(input);
1912
+ inputType = analysis.streamType;
1913
+ needsInlineVolume = needsInlineVolume && !analysis.hasVolume;
1914
+ }
1915
+ const transformerPipeline = findPipeline(inputType, needsInlineVolume ? VOLUME_CONSTRAINT : NO_CONSTRAINT);
1916
+ if (transformerPipeline.length === 0) {
1917
+ if (typeof input === "string")
1918
+ throw new Error(`Invalid pipeline constructed for string resource '${input}'`);
1919
+ return new AudioResource([], [input], options.metadata ?? null, options.silencePaddingFrames ?? 5);
1920
+ }
1921
+ const streams = transformerPipeline.map((edge) => edge.transformer(input));
1922
+ if (typeof input !== "string")
1923
+ streams.unshift(input);
1924
+ return new AudioResource(transformerPipeline, streams, options.metadata ?? null, options.silencePaddingFrames ?? 5);
1925
+ }
1926
+ __name(createAudioResource, "createAudioResource");
1927
+
1928
+ // src/util/generateDependencyReport.ts
1929
+ var import_node_path = require("path");
1930
+ var import_prism_media3 = __toESM(require("prism-media"));
1931
+ function findPackageJSON(dir, packageName, depth) {
1932
+ if (depth === 0)
1933
+ return void 0;
1934
+ const attemptedPath = (0, import_node_path.resolve)(dir, "./package.json");
1935
+ try {
1936
+ const pkg = require(attemptedPath);
1937
+ if (pkg.name !== packageName)
1938
+ throw new Error("package.json does not match");
1939
+ return pkg;
1940
+ } catch (err) {
1941
+ return findPackageJSON((0, import_node_path.resolve)(dir, ".."), packageName, depth - 1);
1942
+ }
1943
+ }
1944
+ __name(findPackageJSON, "findPackageJSON");
1945
+ function version(name) {
1946
+ try {
1947
+ const pkg = name === "@discordjs/voice" ? require_package() : findPackageJSON((0, import_node_path.dirname)(require.resolve(name)), name, 3);
1948
+ return pkg?.version ?? "not found";
1949
+ } catch (err) {
1950
+ return "not found";
1951
+ }
1952
+ }
1953
+ __name(version, "version");
1954
+ function generateDependencyReport() {
1955
+ const report = [];
1956
+ const addVersion = /* @__PURE__ */ __name((name) => report.push(`- ${name}: ${version(name)}`), "addVersion");
1957
+ report.push("Core Dependencies");
1958
+ addVersion("@discordjs/voice");
1959
+ addVersion("prism-media");
1960
+ report.push("");
1961
+ report.push("Opus Libraries");
1962
+ addVersion("@discordjs/opus");
1963
+ addVersion("opusscript");
1964
+ report.push("");
1965
+ report.push("Encryption Libraries");
1966
+ addVersion("sodium");
1967
+ addVersion("libsodium-wrappers");
1968
+ addVersion("tweetnacl");
1969
+ report.push("");
1970
+ report.push("FFmpeg");
1971
+ try {
1972
+ const info = import_prism_media3.default.FFmpeg.getInfo();
1973
+ report.push(`- version: ${info.version}`);
1974
+ report.push(`- libopus: ${info.output.includes("--enable-libopus") ? "yes" : "no"}`);
1975
+ } catch (err) {
1976
+ report.push("- not found");
1977
+ }
1978
+ return ["-".repeat(50), ...report, "-".repeat(50)].join("\n");
1979
+ }
1980
+ __name(generateDependencyReport, "generateDependencyReport");
1981
+
1982
+ // src/util/abortAfter.ts
1983
+ function abortAfter(delay) {
1984
+ const ac = new AbortController();
1985
+ const timeout = setTimeout(() => ac.abort(), delay);
1986
+ ac.signal.addEventListener("abort", () => clearTimeout(timeout));
1987
+ return [ac, ac.signal];
1988
+ }
1989
+ __name(abortAfter, "abortAfter");
1990
+
1991
+ // src/util/entersState.ts
1992
+ var import_node_events = require("events");
1993
+ async function entersState(target, status, timeoutOrSignal) {
1994
+ if (target.state.status !== status) {
1995
+ const [ac, signal] = typeof timeoutOrSignal === "number" ? abortAfter(timeoutOrSignal) : [void 0, timeoutOrSignal];
1996
+ try {
1997
+ await (0, import_node_events.once)(target, status, { signal });
1998
+ } finally {
1999
+ ac?.abort();
2000
+ }
2001
+ }
2002
+ return target;
2003
+ }
2004
+ __name(entersState, "entersState");
2005
+
2006
+ // src/util/demuxProbe.ts
2007
+ var import_node_stream3 = require("stream");
2008
+ var import_prism_media4 = __toESM(require("prism-media"));
2009
+ function validateDiscordOpusHead(opusHead) {
2010
+ const channels = opusHead.readUInt8(9);
2011
+ const sampleRate = opusHead.readUInt32LE(12);
2012
+ return channels === 2 && sampleRate === 48e3;
2013
+ }
2014
+ __name(validateDiscordOpusHead, "validateDiscordOpusHead");
2015
+ function demuxProbe(stream, probeSize = 1024, validator = validateDiscordOpusHead) {
2016
+ return new Promise((resolve2, reject) => {
2017
+ if (stream.readableObjectMode)
2018
+ return reject(new Error("Cannot probe a readable stream in object mode"));
2019
+ if (stream.readableEnded)
2020
+ return reject(new Error("Cannot probe a stream that has ended"));
2021
+ let readBuffer = Buffer.alloc(0);
2022
+ let resolved = void 0;
2023
+ const finish = /* @__PURE__ */ __name((type) => {
2024
+ stream.off("data", onData);
2025
+ stream.off("close", onClose);
2026
+ stream.off("end", onClose);
2027
+ stream.pause();
2028
+ resolved = type;
2029
+ if (stream.readableEnded) {
2030
+ resolve2({
2031
+ stream: import_node_stream3.Readable.from(readBuffer),
2032
+ type
2033
+ });
2034
+ } else {
2035
+ if (readBuffer.length > 0) {
2036
+ stream.push(readBuffer);
2037
+ }
2038
+ resolve2({
2039
+ stream,
2040
+ type
2041
+ });
2042
+ }
2043
+ }, "finish");
2044
+ const foundHead = /* @__PURE__ */ __name((type) => (head) => {
2045
+ if (validator(head)) {
2046
+ finish(type);
2047
+ }
2048
+ }, "foundHead");
2049
+ const webm = new import_prism_media4.default.opus.WebmDemuxer();
2050
+ webm.once("error", noop);
2051
+ webm.on("head", foundHead("webm/opus" /* WebmOpus */));
2052
+ const ogg = new import_prism_media4.default.opus.OggDemuxer();
2053
+ ogg.once("error", noop);
2054
+ ogg.on("head", foundHead("ogg/opus" /* OggOpus */));
2055
+ const onClose = /* @__PURE__ */ __name(() => {
2056
+ if (!resolved) {
2057
+ finish("arbitrary" /* Arbitrary */);
2058
+ }
2059
+ }, "onClose");
2060
+ const onData = /* @__PURE__ */ __name((buffer) => {
2061
+ readBuffer = Buffer.concat([readBuffer, buffer]);
2062
+ webm.write(buffer);
2063
+ ogg.write(buffer);
2064
+ if (readBuffer.length >= probeSize) {
2065
+ stream.off("data", onData);
2066
+ stream.pause();
2067
+ process.nextTick(onClose);
2068
+ }
2069
+ }, "onData");
2070
+ stream.once("error", reject);
2071
+ stream.on("data", onData);
2072
+ stream.once("close", onClose);
2073
+ stream.once("end", onClose);
2074
+ });
2075
+ }
2076
+ __name(demuxProbe, "demuxProbe");
2077
+ module.exports = __toCommonJS(src_exports);
2078
+ // Annotate the CommonJS export names for ESM import in node:
2079
+ 0 && (module.exports = {
2080
+ AudioPlayer,
2081
+ AudioPlayerError,
2082
+ AudioPlayerStatus,
2083
+ AudioReceiveStream,
2084
+ AudioResource,
2085
+ EndBehaviorType,
2086
+ NoSubscriberBehavior,
2087
+ PlayerSubscription,
2088
+ SSRCMap,
2089
+ SpeakingMap,
2090
+ StreamType,
2091
+ VoiceConnection,
2092
+ VoiceConnectionDisconnectReason,
2093
+ VoiceConnectionStatus,
2094
+ VoiceReceiver,
2095
+ createAudioPlayer,
2096
+ createAudioResource,
2097
+ createDefaultAudioReceiveStreamOptions,
2098
+ demuxProbe,
2099
+ entersState,
2100
+ generateDependencyReport,
2101
+ getGroups,
2102
+ getVoiceConnection,
2103
+ getVoiceConnections,
2104
+ joinVoiceChannel,
2105
+ validateDiscordOpusHead
2106
+ });
10
2107
  //# sourceMappingURL=index.js.map