yukimu 1.0.0
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/.cache/replit/modules/nodejs-20.res +1 -0
- package/.cache/replit/modules/replit.res +1 -0
- package/.cache/replit/modules.stamp +0 -0
- package/.cache/replit/nix/dotreplitenv.json +1 -0
- package/.cache/replit/toolchain.json +1 -0
- package/.local/state/workflow-logs/7zVU0iVo-fBL1ccMCmELy/configure_your_app.packager.installForAll.0 +9 -0
- package/.local/state/workflow-logs/7zVU0iVo-fBL1ccMCmELy/configure_your_app.shell.exec.1 +1 -0
- package/.local/state/workflow-logs/U0AinJQVHonnwGjj0RXLn/configure_your_app.packager.installForAll.0 +2 -0
- package/.replit +4 -0
- package/.upm/store.json +1 -0
- package/README.md +152 -0
- package/dist/Node.d.ts +32 -0
- package/dist/Node.d.ts.map +1 -0
- package/dist/Node.js +186 -0
- package/dist/Node.js.map +1 -0
- package/dist/Player.d.ts +63 -0
- package/dist/Player.d.ts.map +1 -0
- package/dist/Player.js +205 -0
- package/dist/Player.js.map +1 -0
- package/dist/Queue.d.ts +29 -0
- package/dist/Queue.d.ts.map +1 -0
- package/dist/Queue.js +75 -0
- package/dist/Queue.js.map +1 -0
- package/dist/Resolver.d.ts +30 -0
- package/dist/Resolver.d.ts.map +1 -0
- package/dist/Resolver.js +121 -0
- package/dist/Resolver.js.map +1 -0
- package/dist/Yukimu.d.ts +59 -0
- package/dist/Yukimu.d.ts.map +1 -0
- package/dist/Yukimu.js +135 -0
- package/dist/Yukimu.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +137 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/package.json +24 -0
- package/src/Node.ts +326 -0
- package/src/Player.ts +245 -0
- package/src/Queue.ts +82 -0
- package/src/Resolver.ts +127 -0
- package/src/Yukimu.ts +177 -0
- package/src/index.ts +6 -0
- package/src/types.ts +178 -0
- package/tsconfig.json +18 -0
package/dist/Player.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Player = void 0;
|
|
4
|
+
const Queue_1 = require("./Queue");
|
|
5
|
+
class Player {
|
|
6
|
+
constructor(manager, node, options) {
|
|
7
|
+
// State
|
|
8
|
+
this.playing = false;
|
|
9
|
+
this.paused = false;
|
|
10
|
+
this.connected = false;
|
|
11
|
+
this.position = 0;
|
|
12
|
+
this.ping = -1;
|
|
13
|
+
// Voice connection
|
|
14
|
+
this.sessionId = null;
|
|
15
|
+
this.voiceToken = null;
|
|
16
|
+
this.voiceEndpoint = null;
|
|
17
|
+
// Filters
|
|
18
|
+
this.filters = {};
|
|
19
|
+
// Loop mode
|
|
20
|
+
this.loop = "none";
|
|
21
|
+
this.manager = manager;
|
|
22
|
+
this.node = node;
|
|
23
|
+
this.queue = new Queue_1.Queue();
|
|
24
|
+
this.guildId = options.guildId;
|
|
25
|
+
this.voiceChannelId = options.voiceChannelId;
|
|
26
|
+
this.textChannelId = options.textChannelId;
|
|
27
|
+
this.volume = options.volume ?? 100;
|
|
28
|
+
// Send voice channel join payload to Discord
|
|
29
|
+
this.sendVoicePayload(options.voiceChannelId, options.selfDeaf ?? true, options.selfMute ?? false);
|
|
30
|
+
}
|
|
31
|
+
// ─── Voice ───────────────────────────────────────────────────────
|
|
32
|
+
sendVoicePayload(channelId, selfDeaf, selfMute) {
|
|
33
|
+
this.manager.sendPayload(this.guildId, {
|
|
34
|
+
op: 4,
|
|
35
|
+
d: {
|
|
36
|
+
guild_id: this.guildId,
|
|
37
|
+
channel_id: channelId,
|
|
38
|
+
self_deaf: selfDeaf,
|
|
39
|
+
self_mute: selfMute,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/** Called when both sessionId and voiceToken/endpoint are available */
|
|
44
|
+
checkVoiceReady() {
|
|
45
|
+
if (!this.sessionId || !this.voiceToken || !this.voiceEndpoint)
|
|
46
|
+
return;
|
|
47
|
+
const voiceState = {
|
|
48
|
+
token: this.voiceToken,
|
|
49
|
+
endpoint: this.voiceEndpoint,
|
|
50
|
+
sessionId: this.sessionId,
|
|
51
|
+
};
|
|
52
|
+
this.node
|
|
53
|
+
.request("PATCH", `/sessions/${this.node.sessionId}/players/${this.guildId}`, {
|
|
54
|
+
voice: voiceState,
|
|
55
|
+
})
|
|
56
|
+
.catch(console.error);
|
|
57
|
+
}
|
|
58
|
+
// ─── Playback ─────────────────────────────────────────────────────
|
|
59
|
+
/** Play a track */
|
|
60
|
+
async play(track, options) {
|
|
61
|
+
this.queue.current = track;
|
|
62
|
+
await this.node.request("PATCH", `/sessions/${this.node.sessionId}/players/${this.guildId}?noReplace=false`, {
|
|
63
|
+
track: { encoded: track.encoded },
|
|
64
|
+
volume: this.volume,
|
|
65
|
+
...(options?.startTime && { position: options.startTime }),
|
|
66
|
+
...(options?.endTime && { endTime: options.endTime }),
|
|
67
|
+
});
|
|
68
|
+
this.playing = true;
|
|
69
|
+
this.paused = false;
|
|
70
|
+
}
|
|
71
|
+
/** Pause or resume playback */
|
|
72
|
+
async pause(state = true) {
|
|
73
|
+
await this.node.request("PATCH", `/sessions/${this.node.sessionId}/players/${this.guildId}`, {
|
|
74
|
+
paused: state,
|
|
75
|
+
});
|
|
76
|
+
this.paused = state;
|
|
77
|
+
this.playing = !state;
|
|
78
|
+
}
|
|
79
|
+
/** Resume playback */
|
|
80
|
+
async resume() {
|
|
81
|
+
return this.pause(false);
|
|
82
|
+
}
|
|
83
|
+
/** Stop playback */
|
|
84
|
+
async stop() {
|
|
85
|
+
await this.node.request("PATCH", `/sessions/${this.node.sessionId}/players/${this.guildId}`, {
|
|
86
|
+
track: { encoded: null },
|
|
87
|
+
});
|
|
88
|
+
this.playing = false;
|
|
89
|
+
this.paused = false;
|
|
90
|
+
this.position = 0;
|
|
91
|
+
this.queue.current = null;
|
|
92
|
+
}
|
|
93
|
+
/** Skip to next track */
|
|
94
|
+
async skip() {
|
|
95
|
+
const next = this.queue.next();
|
|
96
|
+
if (next) {
|
|
97
|
+
await this.play(next);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
await this.stop();
|
|
101
|
+
this.manager.emit("queueEnd", this);
|
|
102
|
+
}
|
|
103
|
+
return next;
|
|
104
|
+
}
|
|
105
|
+
/** Seek to position in milliseconds */
|
|
106
|
+
async seek(position) {
|
|
107
|
+
if (!this.queue.current?.info.isSeekable)
|
|
108
|
+
throw new Error("Current track is not seekable");
|
|
109
|
+
await this.node.request("PATCH", `/sessions/${this.node.sessionId}/players/${this.guildId}`, {
|
|
110
|
+
position,
|
|
111
|
+
});
|
|
112
|
+
this.position = position;
|
|
113
|
+
}
|
|
114
|
+
/** Set volume (0–1000, Lavalink default 100) */
|
|
115
|
+
async setVolume(volume) {
|
|
116
|
+
if (volume < 0 || volume > 1000)
|
|
117
|
+
throw new Error("Volume must be between 0 and 1000");
|
|
118
|
+
await this.node.request("PATCH", `/sessions/${this.node.sessionId}/players/${this.guildId}`, {
|
|
119
|
+
volume,
|
|
120
|
+
});
|
|
121
|
+
this.volume = volume;
|
|
122
|
+
}
|
|
123
|
+
// ─── Filters ──────────────────────────────────────────────────────
|
|
124
|
+
/** Apply audio filters (bass boost, nightcore, 8D, etc.) */
|
|
125
|
+
async setFilters(filters) {
|
|
126
|
+
this.filters = filters;
|
|
127
|
+
await this.node.request("PATCH", `/sessions/${this.node.sessionId}/players/${this.guildId}`, {
|
|
128
|
+
filters,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/** Enable bass boost */
|
|
132
|
+
async setBassBoost(level) {
|
|
133
|
+
const bands = [];
|
|
134
|
+
const gains = {
|
|
135
|
+
off: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
136
|
+
low: [0.2, 0.15, 0.1, 0.05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
137
|
+
medium: [0.4, 0.3, 0.2, 0.1, 0.05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
138
|
+
high: [0.6, 0.5, 0.4, 0.25, 0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
139
|
+
};
|
|
140
|
+
for (let i = 0; i < 15; i++) {
|
|
141
|
+
bands.push({ band: i, gain: gains[level][i] });
|
|
142
|
+
}
|
|
143
|
+
await this.setFilters({ ...this.filters, equalizer: bands });
|
|
144
|
+
}
|
|
145
|
+
/** Enable nightcore effect */
|
|
146
|
+
async setNightcore(enabled) {
|
|
147
|
+
await this.setFilters({
|
|
148
|
+
...this.filters,
|
|
149
|
+
timescale: enabled ? { speed: 1.2, pitch: 1.2, rate: 1.0 } : {},
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/** Enable 8D audio */
|
|
153
|
+
async set8D(enabled) {
|
|
154
|
+
await this.setFilters({
|
|
155
|
+
...this.filters,
|
|
156
|
+
rotation: enabled ? { rotationHz: 0.2 } : {},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/** Clear all filters */
|
|
160
|
+
async clearFilters() {
|
|
161
|
+
this.filters = {};
|
|
162
|
+
await this.node.request("PATCH", `/sessions/${this.node.sessionId}/players/${this.guildId}`, {
|
|
163
|
+
filters: {},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// ─── Queue Helpers ────────────────────────────────────────────────
|
|
167
|
+
/** Add track(s) to queue and optionally start playing */
|
|
168
|
+
async add(tracks, playNow = false) {
|
|
169
|
+
const arr = Array.isArray(tracks) ? tracks : [tracks];
|
|
170
|
+
if (!this.queue.current && arr.length > 0) {
|
|
171
|
+
const first = arr.shift();
|
|
172
|
+
this.queue.current = first;
|
|
173
|
+
this.queue.add(arr);
|
|
174
|
+
await this.play(first);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
this.queue.add(arr);
|
|
178
|
+
if (playNow && arr.length > 0) {
|
|
179
|
+
await this.play(arr[0]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/** Set loop mode */
|
|
184
|
+
setLoop(mode) {
|
|
185
|
+
this.loop = mode;
|
|
186
|
+
}
|
|
187
|
+
// ─── Disconnect ───────────────────────────────────────────────────
|
|
188
|
+
/** Disconnect from voice and clean up */
|
|
189
|
+
async destroy() {
|
|
190
|
+
this.sendVoicePayload(null, false, false);
|
|
191
|
+
await this.node
|
|
192
|
+
.request("DELETE", `/sessions/${this.node.sessionId}/players/${this.guildId}`)
|
|
193
|
+
.catch(() => { });
|
|
194
|
+
this.playing = false;
|
|
195
|
+
this.connected = false;
|
|
196
|
+
this.queue.clear();
|
|
197
|
+
}
|
|
198
|
+
/** Move to a different voice channel */
|
|
199
|
+
async move(channelId, selfDeaf = true) {
|
|
200
|
+
this.voiceChannelId = channelId;
|
|
201
|
+
this.sendVoicePayload(channelId, selfDeaf, false);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.Player = Player;
|
|
205
|
+
//# sourceMappingURL=Player.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Player.js","sourceRoot":"","sources":["../src/Player.ts"],"names":[],"mappings":";;;AAAA,mCAAgC;AAKhC,MAAa,MAAM;IA6BjB,YAAY,OAAe,EAAE,IAAU,EAAE,OAAsB;QAnB/D,QAAQ;QACD,YAAO,GAAY,KAAK,CAAC;QACzB,WAAM,GAAY,KAAK,CAAC;QACxB,cAAS,GAAY,KAAK,CAAC;QAC3B,aAAQ,GAAW,CAAC,CAAC;QACrB,SAAI,GAAW,CAAC,CAAC,CAAC;QAGzB,mBAAmB;QACZ,cAAS,GAAkB,IAAI,CAAC;QAChC,eAAU,GAAkB,IAAI,CAAC;QACjC,kBAAa,GAAkB,IAAI,CAAC;QAE3C,UAAU;QACH,YAAO,GAA4B,EAAE,CAAC;QAE7C,YAAY;QACL,SAAI,GAA+B,MAAM,CAAC;QAG/C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,IAAI,aAAK,EAAE,CAAC;QAEzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC;QAEpC,6CAA6C;QAC7C,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC;IACrG,CAAC;IAED,oEAAoE;IAE5D,gBAAgB,CAAC,SAAwB,EAAE,QAAiB,EAAE,QAAiB;QACrF,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE;YACrC,EAAE,EAAE,CAAC;YACL,CAAC,EAAE;gBACD,QAAQ,EAAE,IAAI,CAAC,OAAO;gBACtB,UAAU,EAAE,SAAS;gBACrB,SAAS,EAAE,QAAQ;gBACnB,SAAS,EAAE,QAAQ;aACpB;SACF,CAAC,CAAC;IACL,CAAC;IAED,uEAAuE;IAChE,eAAe;QACpB,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO;QAEvE,MAAM,UAAU,GAAe;YAC7B,KAAK,EAAE,IAAI,CAAC,UAAU;YACtB,QAAQ,EAAE,IAAI,CAAC,aAAa;YAC5B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;QAEF,IAAI,CAAC,IAAI;aACN,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,EAAE;YAC5E,KAAK,EAAE,UAAU;SAClB,CAAC;aACD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,qEAAqE;IAErE,mBAAmB;IACZ,KAAK,CAAC,IAAI,CAAC,KAAY,EAAE,OAAkD;QAChF,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC;QAE3B,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,YAAY,IAAI,CAAC,OAAO,kBAAkB,EAAE;YAC3G,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;YACjC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,CAAC,OAAO,EAAE,SAAS,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;YAC1D,GAAG,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;SACtD,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,+BAA+B;IACxB,KAAK,CAAC,KAAK,CAAC,QAAiB,IAAI;QACtC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,EAAE;YAC3F,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,sBAAsB;IACf,KAAK,CAAC,MAAM;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,oBAAoB;IACb,KAAK,CAAC,IAAI;QACf,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,EAAE;YAC3F,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,yBAAyB;IAClB,KAAK,CAAC,IAAI;QACf,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uCAAuC;IAChC,KAAK,CAAC,IAAI,CAAC,QAAgB;QAChC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC3F,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,EAAE;YAC3F,QAAQ;SACT,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,gDAAgD;IACzC,KAAK,CAAC,SAAS,CAAC,MAAc;QACnC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACtF,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,EAAE;YAC3F,MAAM;SACP,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,qEAAqE;IAErE,4DAA4D;IACrD,KAAK,CAAC,UAAU,CAAC,OAAgC;QACtD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,EAAE;YAC3F,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,wBAAwB;IACjB,KAAK,CAAC,YAAY,CAAC,KAAwC;QAChE,MAAM,KAAK,GAAqC,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG;YACZ,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAClD,GAAG,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC5D,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAChE,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;SAC/D,CAAC;QAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,8BAA8B;IACvB,KAAK,CAAC,YAAY,CAAC,OAAgB;QACxC,MAAM,IAAI,CAAC,UAAU,CAAC;YACpB,GAAG,IAAI,CAAC,OAAO;YACf,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE;SAChE,CAAC,CAAC;IACL,CAAC;IAED,sBAAsB;IACf,KAAK,CAAC,KAAK,CAAC,OAAgB;QACjC,MAAM,IAAI,CAAC,UAAU,CAAC;YACpB,GAAG,IAAI,CAAC,OAAO;YACf,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE;SAC7C,CAAC,CAAC;IACL,CAAC;IAED,wBAAwB;IACjB,KAAK,CAAC,YAAY;QACvB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,EAAE;YAC3F,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;IACL,CAAC;IAED,qEAAqE;IAErE,yDAAyD;IAClD,KAAK,CAAC,GAAG,CAAC,MAAuB,EAAE,UAAmB,KAAK;QAChE,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAEtD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAG,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACpB,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACpB,IAAI,OAAO,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,oBAAoB;IACb,OAAO,CAAC,IAAgC;QAC7C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,qEAAqE;IAErE,yCAAyC;IAClC,KAAK,CAAC,OAAO;QAClB,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC1C,MAAM,IAAI,CAAC,IAAI;aACZ,OAAO,CAAC,QAAQ,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC;aAC7E,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,wCAAwC;IACjC,KAAK,CAAC,IAAI,CAAC,SAAiB,EAAE,WAAoB,IAAI;QAC3D,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACpD,CAAC;CACF;AA/OD,wBA+OC"}
|
package/dist/Queue.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Track } from "./types";
|
|
2
|
+
export declare class Queue {
|
|
3
|
+
current: Track | null;
|
|
4
|
+
previous: Track | null;
|
|
5
|
+
private tracks;
|
|
6
|
+
/** Add tracks to the end of the queue */
|
|
7
|
+
add(tracks: Track | Track[]): void;
|
|
8
|
+
/** Remove and return the next track */
|
|
9
|
+
next(): Track | null;
|
|
10
|
+
/** Peek at upcoming tracks without modifying queue */
|
|
11
|
+
peek(count?: number): Track[];
|
|
12
|
+
/** Remove a track at a specific index */
|
|
13
|
+
remove(index: number): Track | null;
|
|
14
|
+
/** Clear all queued tracks (does not affect current) */
|
|
15
|
+
clear(): void;
|
|
16
|
+
/** Fisher-Yates shuffle */
|
|
17
|
+
shuffle(): void;
|
|
18
|
+
/** Move a track from one position to another */
|
|
19
|
+
move(from: number, to: number): void;
|
|
20
|
+
/** Total tracks in queue (not including current) */
|
|
21
|
+
get size(): number;
|
|
22
|
+
/** Total duration of all queued tracks in ms */
|
|
23
|
+
get totalDuration(): number;
|
|
24
|
+
/** Whether the queue is empty */
|
|
25
|
+
get isEmpty(): boolean;
|
|
26
|
+
/** All tracks as array (read-only view) */
|
|
27
|
+
get list(): ReadonlyArray<Track>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=Queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Queue.d.ts","sourceRoot":"","sources":["../src/Queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,qBAAa,KAAK;IACT,OAAO,EAAE,KAAK,GAAG,IAAI,CAAQ;IAC7B,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAQ;IACrC,OAAO,CAAC,MAAM,CAAe;IAI7B,yCAAyC;IAClC,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,IAAI;IAKzC,uCAAuC;IAChC,IAAI,IAAI,KAAK,GAAG,IAAI;IAM3B,sDAAsD;IAC/C,IAAI,CAAC,KAAK,GAAE,MAAU,GAAG,KAAK,EAAE;IAIvC,yCAAyC;IAClC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAM1C,wDAAwD;IACjD,KAAK,IAAI,IAAI;IAQpB,2BAA2B;IACpB,OAAO,IAAI,IAAI;IAStB,gDAAgD;IACzC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAQ3C,oDAAoD;IACpD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,gDAAgD;IAChD,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,iCAAiC;IACjC,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,2CAA2C;IAC3C,IAAI,IAAI,IAAI,aAAa,CAAC,KAAK,CAAC,CAE/B;CACF"}
|
package/dist/Queue.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Queue = void 0;
|
|
4
|
+
class Queue {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.current = null;
|
|
7
|
+
this.previous = null;
|
|
8
|
+
this.tracks = [];
|
|
9
|
+
}
|
|
10
|
+
// ─── Basic Operations ─────────────────────────────────────────────
|
|
11
|
+
/** Add tracks to the end of the queue */
|
|
12
|
+
add(tracks) {
|
|
13
|
+
const arr = Array.isArray(tracks) ? tracks : [tracks];
|
|
14
|
+
this.tracks.push(...arr);
|
|
15
|
+
}
|
|
16
|
+
/** Remove and return the next track */
|
|
17
|
+
next() {
|
|
18
|
+
if (this.current)
|
|
19
|
+
this.previous = this.current;
|
|
20
|
+
this.current = this.tracks.shift() ?? null;
|
|
21
|
+
return this.current;
|
|
22
|
+
}
|
|
23
|
+
/** Peek at upcoming tracks without modifying queue */
|
|
24
|
+
peek(count = 5) {
|
|
25
|
+
return this.tracks.slice(0, count);
|
|
26
|
+
}
|
|
27
|
+
/** Remove a track at a specific index */
|
|
28
|
+
remove(index) {
|
|
29
|
+
if (index < 0 || index >= this.tracks.length)
|
|
30
|
+
return null;
|
|
31
|
+
const [removed] = this.tracks.splice(index, 1);
|
|
32
|
+
return removed;
|
|
33
|
+
}
|
|
34
|
+
/** Clear all queued tracks (does not affect current) */
|
|
35
|
+
clear() {
|
|
36
|
+
this.tracks = [];
|
|
37
|
+
this.current = null;
|
|
38
|
+
this.previous = null;
|
|
39
|
+
}
|
|
40
|
+
// ─── Shuffle ──────────────────────────────────────────────────────
|
|
41
|
+
/** Fisher-Yates shuffle */
|
|
42
|
+
shuffle() {
|
|
43
|
+
for (let i = this.tracks.length - 1; i > 0; i--) {
|
|
44
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
45
|
+
[this.tracks[i], this.tracks[j]] = [this.tracks[j], this.tracks[i]];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// ─── Move / Reorder ───────────────────────────────────────────────
|
|
49
|
+
/** Move a track from one position to another */
|
|
50
|
+
move(from, to) {
|
|
51
|
+
if (from < 0 || to < 0 || from >= this.tracks.length || to >= this.tracks.length)
|
|
52
|
+
return;
|
|
53
|
+
const [track] = this.tracks.splice(from, 1);
|
|
54
|
+
this.tracks.splice(to, 0, track);
|
|
55
|
+
}
|
|
56
|
+
// ─── Getters ──────────────────────────────────────────────────────
|
|
57
|
+
/** Total tracks in queue (not including current) */
|
|
58
|
+
get size() {
|
|
59
|
+
return this.tracks.length;
|
|
60
|
+
}
|
|
61
|
+
/** Total duration of all queued tracks in ms */
|
|
62
|
+
get totalDuration() {
|
|
63
|
+
return this.tracks.reduce((acc, t) => acc + (t.info.length ?? 0), 0);
|
|
64
|
+
}
|
|
65
|
+
/** Whether the queue is empty */
|
|
66
|
+
get isEmpty() {
|
|
67
|
+
return this.tracks.length === 0;
|
|
68
|
+
}
|
|
69
|
+
/** All tracks as array (read-only view) */
|
|
70
|
+
get list() {
|
|
71
|
+
return this.tracks;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.Queue = Queue;
|
|
75
|
+
//# sourceMappingURL=Queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Queue.js","sourceRoot":"","sources":["../src/Queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SearchResult, SearchSource } from "./types";
|
|
2
|
+
import type { Yukimu } from "./Yukimu";
|
|
3
|
+
export declare class Resolver {
|
|
4
|
+
private manager;
|
|
5
|
+
private spotifyToken;
|
|
6
|
+
private spotifyExpiry;
|
|
7
|
+
constructor(manager: Yukimu);
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a query or URL to Lavalink tracks
|
|
10
|
+
*/
|
|
11
|
+
resolve(query: string, source: SearchSource): Promise<SearchResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Detect what platform a URL belongs to
|
|
14
|
+
*/
|
|
15
|
+
detectSource(url: string): SearchSource | null;
|
|
16
|
+
/**
|
|
17
|
+
* Get Spotify API token (for resolving Spotify metadata without LavaSrc)
|
|
18
|
+
* Only needed if you're NOT using the LavaSrc Lavalink plugin
|
|
19
|
+
*/
|
|
20
|
+
getSpotifyToken(): Promise<string | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a Spotify URL to track metadata (title + artist for YouTube fallback search)
|
|
23
|
+
* Used when LavaSrc plugin is NOT installed
|
|
24
|
+
*/
|
|
25
|
+
resolveSpotifyFallback(url: string): Promise<{
|
|
26
|
+
title: string;
|
|
27
|
+
artist: string;
|
|
28
|
+
} | null>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=Resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Resolver.d.ts","sourceRoot":"","sources":["../src/Resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAkC,MAAM,SAAS,CAAC;AACrF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAgCvC,qBAAa,QAAQ;IACnB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,aAAa,CAAa;gBAEtB,OAAO,EAAE,MAAM;IAI3B;;OAEG;IACU,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAgBhF;;OAEG;IACI,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IASrD;;;OAGG;IACU,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAyBtD;;;OAGG;IACU,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAoBpG"}
|
package/dist/Resolver.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Resolver = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
// ─── URL Patterns ─────────────────────────────────────────────────────────────
|
|
6
|
+
const URL_PATTERNS = {
|
|
7
|
+
youtube: [
|
|
8
|
+
/^https?:\/\/(www\.)?(youtube\.com|youtu\.be)\/.+/,
|
|
9
|
+
/^https?:\/\/music\.youtube\.com\/.+/,
|
|
10
|
+
],
|
|
11
|
+
spotify: [
|
|
12
|
+
/^https?:\/\/open\.spotify\.com\/(track|album|playlist|artist)\/.+/,
|
|
13
|
+
],
|
|
14
|
+
soundcloud: [
|
|
15
|
+
/^https?:\/\/(www\.)?soundcloud\.com\/.+/,
|
|
16
|
+
],
|
|
17
|
+
deezer: [
|
|
18
|
+
/^https?:\/\/(www\.)?deezer\.com\/(track|album|playlist)\/.+/,
|
|
19
|
+
],
|
|
20
|
+
applemusic: [
|
|
21
|
+
/^https?:\/\/music\.apple\.com\/.+/,
|
|
22
|
+
],
|
|
23
|
+
tidal: [
|
|
24
|
+
/^https?:\/\/(www\.)?tidal\.com\/(browse\/)?(track|album|playlist)\/.+/,
|
|
25
|
+
],
|
|
26
|
+
jiosaavn: [
|
|
27
|
+
/^https?:\/\/(www\.)?jiosaavn\.com\/.+/,
|
|
28
|
+
],
|
|
29
|
+
yandexmusic: [
|
|
30
|
+
/^https?:\/\/music\.yandex\.(ru|com)\/.+/,
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
class Resolver {
|
|
34
|
+
constructor(manager) {
|
|
35
|
+
this.spotifyToken = null;
|
|
36
|
+
this.spotifyExpiry = 0;
|
|
37
|
+
this.manager = manager;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a query or URL to Lavalink tracks
|
|
41
|
+
*/
|
|
42
|
+
async resolve(query, source) {
|
|
43
|
+
const node = this.manager.getBestNode();
|
|
44
|
+
// Check if query is a direct URL
|
|
45
|
+
const detectedSource = this.detectSource(query);
|
|
46
|
+
if (detectedSource) {
|
|
47
|
+
// It's a URL — pass directly to Lavalink (LavaSrc handles platform resolution)
|
|
48
|
+
return node.loadTracks(query);
|
|
49
|
+
}
|
|
50
|
+
// It's a search query — use source prefix
|
|
51
|
+
const prefix = types_1.SourcePrefixes[source];
|
|
52
|
+
return node.loadTracks(`${prefix}:${query}`);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Detect what platform a URL belongs to
|
|
56
|
+
*/
|
|
57
|
+
detectSource(url) {
|
|
58
|
+
for (const [source, patterns] of Object.entries(URL_PATTERNS)) {
|
|
59
|
+
if (patterns.some(p => p.test(url))) {
|
|
60
|
+
return source;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get Spotify API token (for resolving Spotify metadata without LavaSrc)
|
|
67
|
+
* Only needed if you're NOT using the LavaSrc Lavalink plugin
|
|
68
|
+
*/
|
|
69
|
+
async getSpotifyToken() {
|
|
70
|
+
const opts = this.manager.options.spotify;
|
|
71
|
+
if (!opts)
|
|
72
|
+
return null;
|
|
73
|
+
if (this.spotifyToken && Date.now() < this.spotifyExpiry)
|
|
74
|
+
return this.spotifyToken;
|
|
75
|
+
try {
|
|
76
|
+
const res = await fetch("https://accounts.spotify.com/api/token", {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: {
|
|
79
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
80
|
+
Authorization: `Basic ${Buffer.from(`${opts.clientId}:${opts.clientSecret}`).toString("base64")}`,
|
|
81
|
+
},
|
|
82
|
+
body: "grant_type=client_credentials",
|
|
83
|
+
});
|
|
84
|
+
const data = await res.json();
|
|
85
|
+
this.spotifyToken = data.access_token;
|
|
86
|
+
this.spotifyExpiry = Date.now() + data.expires_in * 1000 - 5000;
|
|
87
|
+
return this.spotifyToken;
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.error("[Yukimu] Failed to fetch Spotify token:", err);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Resolve a Spotify URL to track metadata (title + artist for YouTube fallback search)
|
|
96
|
+
* Used when LavaSrc plugin is NOT installed
|
|
97
|
+
*/
|
|
98
|
+
async resolveSpotifyFallback(url) {
|
|
99
|
+
const token = await this.getSpotifyToken();
|
|
100
|
+
if (!token)
|
|
101
|
+
return null;
|
|
102
|
+
const match = url.match(/spotify\.com\/track\/([a-zA-Z0-9]+)/);
|
|
103
|
+
if (!match)
|
|
104
|
+
return null;
|
|
105
|
+
try {
|
|
106
|
+
const res = await fetch(`https://api.spotify.com/v1/tracks/${match[1]}`, {
|
|
107
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
108
|
+
});
|
|
109
|
+
const data = await res.json();
|
|
110
|
+
return {
|
|
111
|
+
title: data.name,
|
|
112
|
+
artist: data.artists[0]?.name ?? "Unknown",
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.Resolver = Resolver;
|
|
121
|
+
//# sourceMappingURL=Resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Resolver.js","sourceRoot":"","sources":["../src/Resolver.ts"],"names":[],"mappings":"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"}
|
package/dist/Yukimu.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { Node } from "./Node";
|
|
3
|
+
import { Player } from "./Player";
|
|
4
|
+
import { Resolver } from "./Resolver";
|
|
5
|
+
import { YukimuOptions, PlayerOptions, YukimuEvents, SearchSource, SearchResult } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Yukimu - A powerful Lavalink v4 wrapper for Discord bots
|
|
8
|
+
* Supports: YouTube, YouTube Music, Spotify, Deezer, Apple Music,
|
|
9
|
+
* JioSaavn, Tidal, SoundCloud, Yandex Music
|
|
10
|
+
*/
|
|
11
|
+
export declare class Yukimu extends EventEmitter {
|
|
12
|
+
readonly options: YukimuOptions;
|
|
13
|
+
readonly nodes: Map<string, Node>;
|
|
14
|
+
readonly players: Map<string, Player>;
|
|
15
|
+
readonly resolver: Resolver;
|
|
16
|
+
/** Send function — you must set this to send voice payloads to Discord */
|
|
17
|
+
sendPayload: (guildId: string, payload: unknown) => void;
|
|
18
|
+
constructor(options: YukimuOptions);
|
|
19
|
+
/** Add a new Lavalink node */
|
|
20
|
+
addNode(options: import("./types").NodeOptions): Node;
|
|
21
|
+
/** Remove a node by name */
|
|
22
|
+
removeNode(name: string): void;
|
|
23
|
+
/** Get the best available node (least load) */
|
|
24
|
+
getBestNode(): Node;
|
|
25
|
+
/** Create a new player for a guild */
|
|
26
|
+
createPlayer(options: PlayerOptions): Player;
|
|
27
|
+
/** Get an existing player */
|
|
28
|
+
getPlayer(guildId: string): Player | undefined;
|
|
29
|
+
/** Destroy a player */
|
|
30
|
+
destroyPlayer(guildId: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Search for tracks across any supported source
|
|
33
|
+
* @param query - Search query or direct URL
|
|
34
|
+
* @param source - Where to search (youtube, spotify, deezer, etc.)
|
|
35
|
+
*/
|
|
36
|
+
search(query: string, source?: SearchSource): Promise<SearchResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Handle Discord voice state updates — call this in your bot's
|
|
39
|
+
* voiceStateUpdate event handler
|
|
40
|
+
*/
|
|
41
|
+
handleVoiceStateUpdate(data: {
|
|
42
|
+
guild_id?: string;
|
|
43
|
+
user_id: string;
|
|
44
|
+
session_id: string;
|
|
45
|
+
channel_id?: string | null;
|
|
46
|
+
}): void;
|
|
47
|
+
/**
|
|
48
|
+
* Handle Discord voice server updates — call this in your bot's
|
|
49
|
+
* voiceServerUpdate event handler
|
|
50
|
+
*/
|
|
51
|
+
handleVoiceServerUpdate(data: {
|
|
52
|
+
guild_id: string;
|
|
53
|
+
token: string;
|
|
54
|
+
endpoint?: string | null;
|
|
55
|
+
}): void;
|
|
56
|
+
on<K extends keyof YukimuEvents>(event: K, listener: (...args: YukimuEvents[K]) => void): this;
|
|
57
|
+
emit<K extends keyof YukimuEvents>(event: K, ...args: YukimuEvents[K]): boolean;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=Yukimu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Yukimu.d.ts","sourceRoot":"","sources":["../src/Yukimu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,qBAAa,MAAO,SAAQ,YAAY;IACtC,SAAgB,OAAO,EAAE,aAAa,CAAC;IACvC,SAAgB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAa;IACrD,SAAgB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAa;IACzD,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IAEnC,0EAA0E;IACnE,WAAW,EAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;gBAErD,OAAO,EAAE,aAAa;IAalC,8BAA8B;IACvB,OAAO,CAAC,OAAO,EAAE,OAAO,SAAS,EAAE,WAAW,GAAG,IAAI;IAO5D,4BAA4B;IACrB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAOrC,+CAA+C;IACxC,WAAW,IAAI,IAAI;IAa1B,sCAAsC;IAC/B,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM;IAcnD,6BAA6B;IACtB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIrD,uBAAuB;IAChB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAU3C;;;;OAIG;IACU,MAAM,CACjB,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,YAAsD,GAC7D,OAAO,CAAC,YAAY,CAAC;IAMxB;;;OAGG;IACI,sBAAsB,CAAC,IAAI,EAAE;QAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,GAAG,IAAI;IAoBR;;;OAGG;IACI,uBAAuB,CAAC,IAAI,EAAE;QACnC,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,GAAG,IAAI;IAYD,EAAE,CAAC,CAAC,SAAS,MAAM,YAAY,EACpC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3C,IAAI;IAIA,IAAI,CAAC,CAAC,SAAS,MAAM,YAAY,EACtC,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,OAAO;CAGX"}
|