linkdave 0.1.6 → 0.2.0-dev.a8d4d2d
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 +4 -2
- package/dist/client.js +43 -11
- package/dist/filters.d.ts +61 -0
- package/dist/filters.js +108 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/node.d.ts +2 -5
- package/dist/node.js +8 -30
- package/dist/player.d.ts +8 -7
- package/dist/player.js +79 -59
- package/dist/queue.d.ts +8 -5
- package/dist/queue.js +7 -9
- package/dist/rest.d.ts +0 -1
- package/dist/rest.js +0 -1
- package/dist/types.d.ts +48 -36
- package/dist/types.js +35 -17
- package/dist/utils.d.ts +0 -1
- package/dist/utils.js +0 -1
- package/package.json +5 -5
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/node.d.ts.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/player.d.ts.map +0 -1
- package/dist/player.js.map +0 -1
- package/dist/queue.d.ts.map +0 -1
- package/dist/queue.js.map +0 -1
- package/dist/rest.d.ts.map +0 -1
- package/dist/rest.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
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
|
-
|
|
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.
|
|
67
|
-
lowestCount = node.
|
|
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.
|
|
87
|
+
const node = this.getPreferredNode(options?.nodeId);
|
|
78
88
|
if (!node) {
|
|
79
|
-
throw new Error(
|
|
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.#
|
|
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.
|
|
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
|
+
}
|
package/dist/filters.js
ADDED
|
@@ -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,
|
|
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
|
|
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
|
-
#
|
|
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
|
|
88
|
-
return this.#
|
|
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.#
|
|
93
|
+
this.#stats.players++;
|
|
98
94
|
}
|
|
99
95
|
decrementPlayerCount() {
|
|
100
|
-
if (this.#
|
|
101
|
-
|
|
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.#
|
|
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
|
-
|
|
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
|
-
|
|
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
|