linkdave 0.1.6 → 0.2.0-dev.db8ab4a

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/client.d.ts CHANGED
@@ -24,7 +24,10 @@ export declare class LinkDaveClient extends EventEmitter {
24
24
  connectAll(): Promise<void>;
25
25
  disconnectAll(): void;
26
26
  getBestNode(): Node | undefined;
27
- getPlayer(guildId: string, options?: Omit<PlayerOptions, "guildId">): Player;
27
+ private getPreferredNode;
28
+ getPlayer(guildId: string, options?: Omit<PlayerOptions, "guildId"> & {
29
+ nodeId?: string;
30
+ }): Player;
28
31
  removePlayer(guildId: string): boolean;
29
32
  get players(): ReadonlyMap<string, Player>;
30
33
  get clientId(): string;
@@ -33,4 +36,3 @@ export declare class LinkDaveClient extends EventEmitter {
33
36
  _onPlayerDestroy(guildId: string): void;
34
37
  _updatePlayerNode(guildId: string, oldNode: Node, newNode: Node): void;
35
38
  }
36
- //# sourceMappingURL=client.d.ts.map
package/dist/client.js CHANGED
@@ -2,7 +2,7 @@ import { GatewayDispatchEvents } from "discord-api-types/v10";
2
2
  import { EventEmitter } from "node:events";
3
3
  import { Node } from "./node.js";
4
4
  import { Player } from "./player.js";
5
- import { EventName, ManagerEventName } from "./types.js";
5
+ import { DisconnectReason, EventName, ManagerEventName } from "./types.js";
6
6
  const CLIENT_ID_REGEX = /^\d{15,21}$/;
7
7
  // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
8
8
  export class LinkDaveClient extends EventEmitter {
@@ -63,20 +63,32 @@ export class LinkDaveClient extends EventEmitter {
63
63
  if (!node.connected || node.draining) {
64
64
  continue;
65
65
  }
66
- if (node.playerCount < lowestCount) {
67
- lowestCount = node.playerCount;
66
+ if (node.stats.players < lowestCount) {
67
+ lowestCount = node.stats.players;
68
68
  bestNode = node;
69
69
  }
70
70
  }
71
71
  return bestNode;
72
72
  }
73
+ getPreferredNode(nodeId) {
74
+ if (!nodeId) {
75
+ return this.getBestNode();
76
+ }
77
+ const node = this.#nodes.get(nodeId);
78
+ if (!node || !node.connected || node.draining) {
79
+ return undefined;
80
+ }
81
+ return node;
82
+ }
73
83
  getPlayer(guildId, options) {
74
84
  let player = this.#players.get(guildId);
75
85
  if (player)
76
86
  return player;
77
- const node = this.getBestNode();
87
+ const node = this.getPreferredNode(options?.nodeId);
78
88
  if (!node) {
79
- throw new Error("No available nodes to create player");
89
+ throw new Error(options?.nodeId
90
+ ? `Node "${options.nodeId}" is not available to create player`
91
+ : "No available nodes to create player");
80
92
  }
81
93
  player = new Player(this, guildId, node, options);
82
94
  this.#players.set(guildId, player);
@@ -104,7 +116,6 @@ export class LinkDaveClient extends EventEmitter {
104
116
  handleRaw({ t: event, d: data }) {
105
117
  switch (event) {
106
118
  case GatewayDispatchEvents.VoiceStateUpdate: {
107
- // https://discord.com/developers/docs/resources/voice#voice-state-object
108
119
  if (!data.guild_id)
109
120
  return;
110
121
  if (data.user_id !== this.#clientId)
@@ -134,9 +145,8 @@ export class LinkDaveClient extends EventEmitter {
134
145
  node.on(EventName.TrackEnd, (data) => this.#handleTrackEnd(node, data));
135
146
  node.on(EventName.TrackError, (data) => this.#forwardPlayerEvent(node, data.guild_id, EventName.TrackError, data));
136
147
  node.on(EventName.QueueError, (data) => this.#forwardPlayerEvent(node, data.guild_id, EventName.QueueError, data));
137
- node.on(EventName.VoiceConnect, (data) => this.#forwardPlayerEvent(node, data.guild_id, EventName.VoiceConnect, data));
148
+ node.on(EventName.VoiceConnect, (data) => this.#handleVoiceConnect(node, data));
138
149
  node.on(EventName.VoiceDisconnect, (data) => this.#handleVoiceDisconnect(node, data));
139
- node.on(EventName.Pong, () => this.emit(EventName.Pong, undefined));
140
150
  node.on(EventName.Stats, (data) => this.emit(EventName.Stats, data));
141
151
  node.on(EventName.NodeDraining, (data) => this.#handleNodeDraining(node, data));
142
152
  node.on(EventName.MigrateReady, (data) => this.#handleMigrateReady(node, data));
@@ -153,7 +163,7 @@ export class LinkDaveClient extends EventEmitter {
153
163
  const player = this.#players.get(data.guild_id);
154
164
  if (player?.node !== node)
155
165
  return;
156
- player._updateState(data);
166
+ player._onPlayerUpdate(data);
157
167
  this.emit(EventName.PlayerUpdate, data);
158
168
  }
159
169
  #handleTrackStart(node, data) {
@@ -170,14 +180,37 @@ export class LinkDaveClient extends EventEmitter {
170
180
  player._onTrackEnd(data);
171
181
  this.emit(EventName.TrackEnd, data);
172
182
  }
183
+ #handleVoiceConnect(node, data) {
184
+ const player = this.#players.get(data.guild_id);
185
+ if (player?.node !== node)
186
+ return;
187
+ player._onVoiceConnect();
188
+ this.emit(EventName.VoiceConnect, data);
189
+ }
173
190
  #handleVoiceDisconnect(node, data) {
174
191
  const player = this.#players.get(data.guild_id);
175
192
  if (player?.node !== node)
176
193
  return;
194
+ if (data.reason === DisconnectReason.ConnectionLost) {
195
+ this.#handleConnectionLost(player);
196
+ return;
197
+ }
177
198
  player._onVoiceDisconnect();
178
- this.emit(EventName.VoiceDisconnect, data);
179
199
  player.node.decrementPlayerCount();
180
200
  this.#players.delete(data.guild_id);
201
+ this.emit(EventName.VoiceDisconnect, data);
202
+ }
203
+ #handleConnectionLost(player) {
204
+ if (player.voiceChannelId)
205
+ player.disconnect();
206
+ else
207
+ player._onVoiceDisconnect();
208
+ player.node.decrementPlayerCount();
209
+ this.#players.delete(player.guildId);
210
+ this.emit(EventName.VoiceDisconnect, {
211
+ guild_id: player.guildId,
212
+ reason: DisconnectReason.ConnectionLost
213
+ });
181
214
  }
182
215
  _onPlayerDestroy(guildId) {
183
216
  const player = this.#players.get(guildId);
@@ -226,4 +259,3 @@ export class LinkDaveClient extends EventEmitter {
226
259
  newNode.incrementPlayerCount();
227
260
  }
228
261
  }
229
- //# sourceMappingURL=client.js.map
@@ -0,0 +1,61 @@
1
+ import type { Filter, FiltersPayload } from "./types.js";
2
+ export declare class PlayerFilters {
3
+ #private;
4
+ /**
5
+ * Pitch multiplier applied on top of any preset pitch.
6
+ *
7
+ * - **Default:** `0` (no override — preset value is used as-is)
8
+ * - **Normal playback:** `1.0`
9
+ * - **Recommended range:** `0.5` – `2.0`
10
+ * - Values below `0` are clamped to `0`. Values above `2.0` will work
11
+ * but progressively degrade audio quality due to resampling artifacts.
12
+ *
13
+ * When a preset like {@link Filter.Nightcore} is active (which sets pitch
14
+ * to `1.3×`), this value is **multiplied** on top: e.g. `pitch = 0.5`
15
+ * with Nightcore → effective pitch = `1.3 × 0.5 = 0.65`.
16
+ */
17
+ get pitch(): number;
18
+ set pitch(value: number);
19
+ /**
20
+ * Speed multiplier applied on top of any preset speed.
21
+ *
22
+ * - **Default:** `0` (no override — preset value is used as-is)
23
+ * - **Normal playback:** `1.0`
24
+ * - **Recommended range:** `0.25` – `3.0`
25
+ * - Values below `0` are clamped to `0`. Extreme values (e.g. `>5.0`)
26
+ * will work but may cause audible quality loss since more source
27
+ * samples are consumed per output frame.
28
+ *
29
+ * When a preset like {@link Filter.Vaporwave} is active (which sets speed
30
+ * to `0.8×`), this value is **multiplied** on top: e.g. `speed = 1.25`
31
+ * with Vaporwave → effective speed = `0.8 × 1.25 = 1.0`.
32
+ */
33
+ get speed(): number;
34
+ set speed(value: number);
35
+ /**
36
+ * Toggle a filter on or off. If `enabled` is omitted the filter is
37
+ * flipped from its current state.
38
+ *
39
+ * **Preset filters** ({@link Filter.Nightcore}, {@link Filter.Vaporwave})
40
+ * adjust both speed and pitch by fixed amounts (1.3× and 0.8×
41
+ * respectively). Enabling both simultaneously multiplies their effects
42
+ * together (effective speed = `1.3 × 0.8 = 1.04`).
43
+ *
44
+ * **DSP filters** ({@link Filter.Tremolo}, {@link Filter.Vibrato},
45
+ * {@link Filter.Rotation}, {@link Filter.LowPass}) modify the audio
46
+ * signal in-place and can all be enabled simultaneously — they are
47
+ * applied in sequence (tremolo → vibrato → rotation → lowpass).
48
+ */
49
+ toggle(filter: Filter, enabled?: boolean): this;
50
+ /**
51
+ * @returns `true` if any filter is active or if pitch or speed are non-zero.
52
+ */
53
+ get active(): boolean;
54
+ /**
55
+ * @returns an array of all active filters.
56
+ */
57
+ get activeFilters(): Filter[];
58
+ get(filter: Filter): boolean | undefined;
59
+ clear(): void;
60
+ toPayload(): FiltersPayload | undefined;
61
+ }
@@ -0,0 +1,108 @@
1
+ export class PlayerFilters {
2
+ #state = new Map();
3
+ #pitch = 0;
4
+ #speed = 0;
5
+ /**
6
+ * Pitch multiplier applied on top of any preset pitch.
7
+ *
8
+ * - **Default:** `0` (no override — preset value is used as-is)
9
+ * - **Normal playback:** `1.0`
10
+ * - **Recommended range:** `0.5` – `2.0`
11
+ * - Values below `0` are clamped to `0`. Values above `2.0` will work
12
+ * but progressively degrade audio quality due to resampling artifacts.
13
+ *
14
+ * When a preset like {@link Filter.Nightcore} is active (which sets pitch
15
+ * to `1.3×`), this value is **multiplied** on top: e.g. `pitch = 0.5`
16
+ * with Nightcore → effective pitch = `1.3 × 0.5 = 0.65`.
17
+ */
18
+ get pitch() {
19
+ return this.#pitch;
20
+ }
21
+ set pitch(value) {
22
+ this.#pitch = Math.max(0, value);
23
+ }
24
+ /**
25
+ * Speed multiplier applied on top of any preset speed.
26
+ *
27
+ * - **Default:** `0` (no override — preset value is used as-is)
28
+ * - **Normal playback:** `1.0`
29
+ * - **Recommended range:** `0.25` – `3.0`
30
+ * - Values below `0` are clamped to `0`. Extreme values (e.g. `>5.0`)
31
+ * will work but may cause audible quality loss since more source
32
+ * samples are consumed per output frame.
33
+ *
34
+ * When a preset like {@link Filter.Vaporwave} is active (which sets speed
35
+ * to `0.8×`), this value is **multiplied** on top: e.g. `speed = 1.25`
36
+ * with Vaporwave → effective speed = `0.8 × 1.25 = 1.0`.
37
+ */
38
+ get speed() {
39
+ return this.#speed;
40
+ }
41
+ set speed(value) {
42
+ this.#speed = Math.max(0, value);
43
+ }
44
+ /**
45
+ * Toggle a filter on or off. If `enabled` is omitted the filter is
46
+ * flipped from its current state.
47
+ *
48
+ * **Preset filters** ({@link Filter.Nightcore}, {@link Filter.Vaporwave})
49
+ * adjust both speed and pitch by fixed amounts (1.3× and 0.8×
50
+ * respectively). Enabling both simultaneously multiplies their effects
51
+ * together (effective speed = `1.3 × 0.8 = 1.04`).
52
+ *
53
+ * **DSP filters** ({@link Filter.Tremolo}, {@link Filter.Vibrato},
54
+ * {@link Filter.Rotation}, {@link Filter.LowPass}) modify the audio
55
+ * signal in-place and can all be enabled simultaneously — they are
56
+ * applied in sequence (tremolo → vibrato → rotation → lowpass).
57
+ */
58
+ toggle(filter, enabled) {
59
+ const next = enabled ?? !this.#state.get(filter);
60
+ this.#state.set(filter, next);
61
+ return this;
62
+ }
63
+ /**
64
+ * @returns `true` if any filter is active or if pitch or speed are non-zero.
65
+ */
66
+ get active() {
67
+ for (const v of this.#state.values()) {
68
+ if (v)
69
+ return true;
70
+ }
71
+ return this.#pitch > 0 || this.#speed > 0;
72
+ }
73
+ /**
74
+ * @returns an array of all active filters.
75
+ */
76
+ get activeFilters() {
77
+ const result = [];
78
+ for (const [k, v] of this.#state)
79
+ if (v)
80
+ result.push(k);
81
+ return result;
82
+ }
83
+ get(filter) {
84
+ return this.#state.get(filter);
85
+ }
86
+ clear() {
87
+ this.#state.clear();
88
+ this.#pitch = 0;
89
+ this.#speed = 0;
90
+ }
91
+ toPayload() {
92
+ if (!this.active)
93
+ return undefined;
94
+ const enabled = [];
95
+ for (const [k, v] of this.#state) {
96
+ if (v)
97
+ enabled.push(k);
98
+ }
99
+ const payload = {};
100
+ if (enabled.length > 0)
101
+ payload.enabled = enabled;
102
+ if (this.#pitch > 0)
103
+ payload.pitch = this.#pitch;
104
+ if (this.#speed > 0)
105
+ payload.speed = this.#speed;
106
+ return payload;
107
+ }
108
+ }
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  export * from "./client.js";
2
+ export * from "./filters.js";
2
3
  export * from "./node.js";
3
4
  export * from "./player.js";
4
5
  export * from "./queue.js";
5
6
  export * from "./rest.js";
6
7
  export * from "./types.js";
7
8
  export * from "./utils.js";
8
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  export * from "./client.js";
2
+ export * from "./filters.js";
2
3
  export * from "./node.js";
3
4
  export * from "./player.js";
4
5
  export * from "./queue.js";
5
6
  export * from "./rest.js";
6
7
  export * from "./types.js";
7
8
  export * from "./utils.js";
8
- //# sourceMappingURL=index.js.map
package/dist/node.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { EventEmitter } from "node:events";
2
2
  import { RESTClient } from "./rest.js";
3
- import type { Events, PlayPayload, SeekPayload, VoiceUpdatePayload, VolumePayload } from "./types.js";
3
+ import type { Events, PlayPayload, SeekPayload, StatsPayload, VoiceUpdatePayload } from "./types.js";
4
4
  export interface NodeOptions {
5
5
  name: string;
6
6
  url: string;
@@ -23,7 +23,6 @@ export interface Node {
23
23
  }
24
24
  export declare class Node extends EventEmitter {
25
25
  #private;
26
- private static readonly NODE_PING_INTERVAL;
27
26
  readonly name: string;
28
27
  readonly url: string;
29
28
  readonly rest: RESTClient;
@@ -32,7 +31,7 @@ export declare class Node extends EventEmitter {
32
31
  disconnect(): void;
33
32
  get state(): NodeState;
34
33
  get sessionId(): string | null;
35
- get playerCount(): number;
34
+ get stats(): StatsPayload;
36
35
  get draining(): boolean;
37
36
  get connected(): boolean;
38
37
  incrementPlayerCount(): void;
@@ -44,7 +43,5 @@ export declare class Node extends EventEmitter {
44
43
  sendResume(guildId: string): Promise<void>;
45
44
  sendStop(guildId: string): Promise<void>;
46
45
  sendSeek(guildId: string, data: SeekPayload): Promise<void>;
47
- sendVolume(guildId: string, data: VolumePayload): Promise<void>;
48
46
  sendDisconnect(guildId: string): Promise<void>;
49
47
  }
50
- //# sourceMappingURL=node.d.ts.map
package/dist/node.js CHANGED
@@ -11,7 +11,6 @@ export var NodeState;
11
11
  })(NodeState || (NodeState = {}));
12
12
  // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
13
13
  export class Node extends EventEmitter {
14
- static NODE_PING_INTERVAL = 30_000;
15
14
  name;
16
15
  url;
17
16
  rest;
@@ -20,9 +19,8 @@ export class Node extends EventEmitter {
20
19
  #sessionId = null;
21
20
  #reconnectAttempts = 0;
22
21
  #reconnectTimeout = null;
23
- #pingInterval = null;
24
22
  #state = NodeState.Disconnected;
25
- #playerCount = 0;
23
+ #stats = { players: 0, playing_tracks: 0, uptime: 0, memory: 0 };
26
24
  constructor(options) {
27
25
  super();
28
26
  this.name = options.name;
@@ -53,7 +51,6 @@ export class Node extends EventEmitter {
53
51
  const onOpen = () => {
54
52
  this.#state = NodeState.Connected;
55
53
  this.#reconnectAttempts = 0;
56
- this.#startPingInterval();
57
54
  resolve(null);
58
55
  };
59
56
  const onError = (event) => {
@@ -70,7 +67,6 @@ export class Node extends EventEmitter {
70
67
  }
71
68
  disconnect() {
72
69
  this.#state = NodeState.Disconnected;
73
- this.#stopPingInterval();
74
70
  this.#stopReconnect();
75
71
  if (this.#ws) {
76
72
  this.#ws.close(1_000, "Client disconnect");
@@ -84,8 +80,8 @@ export class Node extends EventEmitter {
84
80
  get sessionId() {
85
81
  return this.#sessionId;
86
82
  }
87
- get playerCount() {
88
- return this.#playerCount;
83
+ get stats() {
84
+ return this.#stats;
89
85
  }
90
86
  get draining() {
91
87
  return this.state === NodeState.Draining;
@@ -94,12 +90,12 @@ export class Node extends EventEmitter {
94
90
  return this.#state === NodeState.Connected || this.#state === NodeState.Draining;
95
91
  }
96
92
  incrementPlayerCount() {
97
- this.#playerCount++;
93
+ this.#stats.players++;
98
94
  }
99
95
  decrementPlayerCount() {
100
- if (this.#playerCount > 0) {
101
- this.#playerCount--;
102
- }
96
+ if (this.#stats.players <= 0)
97
+ return;
98
+ this.#stats.players--;
103
99
  }
104
100
  #onMessage(event) {
105
101
  try {
@@ -134,12 +130,8 @@ export class Node extends EventEmitter {
134
130
  case ServerOpCodes.VoiceDisconnect:
135
131
  this.emit(EventName.VoiceDisconnect, message.d);
136
132
  break;
137
- case ServerOpCodes.Pong:
138
- this.emit(EventName.Pong, undefined);
139
- break;
140
133
  case ServerOpCodes.Stats:
141
- this.#playerCount = message.d.players;
142
- this.#state = message.d.draining ? NodeState.Draining : NodeState.Connected;
134
+ this.#stats = message.d;
143
135
  this.emit(EventName.Stats, message.d);
144
136
  break;
145
137
  case ServerOpCodes.NodeDraining:
@@ -153,7 +145,6 @@ export class Node extends EventEmitter {
153
145
  }
154
146
  #onClose(event) {
155
147
  this.#state = NodeState.Disconnected;
156
- this.#stopPingInterval();
157
148
  this.emit(EventName.Close, { code: event.code, reason: event.reason });
158
149
  if (event.code !== 1_000 && this.#options.autoReconnect && !this.draining && this.#reconnectAttempts < this.#options.maxReconnectAttempts) {
159
150
  this.#scheduleReconnect();
@@ -176,15 +167,6 @@ export class Node extends EventEmitter {
176
167
  }
177
168
  this.#reconnectAttempts = 0;
178
169
  }
179
- #startPingInterval() {
180
- this.#pingInterval = setInterval(() => this.#send(ClientOpCodes.Ping, undefined), Node.NODE_PING_INTERVAL);
181
- }
182
- #stopPingInterval() {
183
- if (!this.#pingInterval)
184
- return;
185
- clearInterval(this.#pingInterval);
186
- this.#pingInterval = null;
187
- }
188
170
  sendVoiceUpdate(data) {
189
171
  this.#send(ClientOpCodes.VoiceUpdate, data);
190
172
  }
@@ -206,9 +188,6 @@ export class Node extends EventEmitter {
206
188
  async sendSeek(guildId, data) {
207
189
  await this.rest.post(Routes.seek(this.#requireSession(), guildId), data);
208
190
  }
209
- async sendVolume(guildId, data) {
210
- await this.rest.patch(Routes.volume(this.#requireSession(), guildId), data);
211
- }
212
191
  async sendDisconnect(guildId) {
213
192
  await this.rest.delete(Routes.disconnect(this.#requireSession(), guildId));
214
193
  }
@@ -226,4 +205,3 @@ export class Node extends EventEmitter {
226
205
  this.#ws.send(JSON.stringify(message));
227
206
  }
228
207
  }
229
- //# sourceMappingURL=node.js.map
package/dist/player.d.ts CHANGED
@@ -1,17 +1,20 @@
1
1
  import { type GatewayVoiceServerUpdateDispatchData, type GatewayVoiceStateUpdateDispatchData } from "discord-api-types/v10";
2
2
  import type { LinkDaveClient } from "./client.js";
3
+ import { PlayerFilters } from "./filters.js";
3
4
  import type { Node } from "./node.js";
4
5
  import { Queue } from "./queue.js";
5
- import type { MigrateReadyPayload, PlayerUpdatePayload, TrackEndPayload, TrackInfo, TrackStartPayload, VoiceConnectPayload } from "./types.js";
6
+ import type { FiltersPayload, MigrateReadyPayload, PlayerUpdatePayload, TrackEndPayload, TrackInfo, TrackStartPayload, VoiceConnectPayload } from "./types.js";
6
7
  import { PlayerState } from "./types.js";
7
8
  export interface PlayOptions {
8
9
  startTime?: number;
9
- volume?: number;
10
+ requesterId?: string;
11
+ filters?: FiltersPayload;
10
12
  }
11
13
  export interface PlayerOptions {
12
14
  voiceChannelId?: string;
13
15
  selfMute?: boolean;
14
16
  selfDeaf?: boolean;
17
+ inactivityTimeout?: number;
15
18
  }
16
19
  export type RawVoiceStateUpdate = Pick<GatewayVoiceStateUpdateDispatchData, "user_id" | "channel_id" | "session_id">;
17
20
  export type RawVoiceServerUpdate = Pick<GatewayVoiceServerUpdateDispatchData, "token" | "guild_id" | "endpoint">;
@@ -22,14 +25,13 @@ export declare class Player {
22
25
  get guildId(): string;
23
26
  get voiceChannelId(): string | null;
24
27
  get state(): PlayerState;
25
- get position(): number;
26
- get volume(): number;
27
28
  get current(): TrackInfo | null;
28
29
  get node(): Node;
29
30
  get queue(): Queue;
30
31
  get playing(): boolean;
31
32
  get paused(): boolean;
32
33
  get connected(): boolean;
34
+ get filters(): PlayerFilters;
33
35
  connect(channelId?: string, timeoutMs?: number): Promise<VoiceConnectPayload>;
34
36
  disconnect(): void;
35
37
  handleVoiceStateUpdate(data: RawVoiceStateUpdate): Promise<void>;
@@ -39,13 +41,12 @@ export declare class Player {
39
41
  resume(): Promise<void>;
40
42
  stop(): Promise<void>;
41
43
  seek(position: number): Promise<void>;
42
- setVolume(volume: number): Promise<void>;
43
44
  destroy(): Promise<void>;
44
45
  moveNode(targetNode: Node): Promise<unknown>;
45
- _updateState(data: PlayerUpdatePayload): void;
46
+ _onPlayerUpdate(data: PlayerUpdatePayload): void;
46
47
  _onTrackStart(data: TrackStartPayload): void;
47
48
  _onTrackEnd(data: TrackEndPayload): void;
49
+ _onVoiceConnect(): void;
48
50
  _onVoiceDisconnect(): void;
49
51
  _onMigrateReady(data: MigrateReadyPayload): void;
50
52
  }
51
- //# sourceMappingURL=player.d.ts.map