distube 4.0.3 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +66 -65
- package/dist/index.js +593 -552
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -22,7 +22,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
22
22
|
}
|
|
23
23
|
return to;
|
|
24
24
|
};
|
|
25
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
26
29
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
30
|
var __publicField = (obj, key, value) => {
|
|
28
31
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -56,7 +59,7 @@ var require_package = __commonJS({
|
|
|
56
59
|
"package.json"(exports, module2) {
|
|
57
60
|
module2.exports = {
|
|
58
61
|
name: "distube",
|
|
59
|
-
version: "4.0.
|
|
62
|
+
version: "4.0.4",
|
|
60
63
|
description: "A Discord.js module to simplify your music commands and play songs with audio filters on Discord without any API key.",
|
|
61
64
|
main: "./dist/index.js",
|
|
62
65
|
types: "./dist/index.d.ts",
|
|
@@ -70,7 +73,7 @@ var require_package = __commonJS({
|
|
|
70
73
|
],
|
|
71
74
|
scripts: {
|
|
72
75
|
test: "jest",
|
|
73
|
-
docs: "docgen -s src
|
|
76
|
+
docs: "docgen -s src/**/*.ts -o docs.json -c pages/index.yml -g -j jsdoc.config.json",
|
|
74
77
|
lint: "prettier --check . && eslint .",
|
|
75
78
|
"lint:fix": "eslint . --fix",
|
|
76
79
|
prettier: 'prettier --write "**/*.{ts,json,yml,yaml,md}"',
|
|
@@ -133,11 +136,11 @@ var require_package = __commonJS({
|
|
|
133
136
|
"@commitlint/cli": "^17.0.3",
|
|
134
137
|
"@commitlint/config-conventional": "^17.0.3",
|
|
135
138
|
"@discordjs/voice": "^0.11.0",
|
|
136
|
-
"@
|
|
139
|
+
"@distubejs/docgen": "distubejs/docgen",
|
|
137
140
|
"@types/jest": "^28.1.6",
|
|
138
|
-
"@types/node": "^18.6.
|
|
139
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
140
|
-
"@typescript-eslint/parser": "^5.
|
|
141
|
+
"@types/node": "^18.6.1",
|
|
142
|
+
"@typescript-eslint/eslint-plugin": "^5.31.0",
|
|
143
|
+
"@typescript-eslint/parser": "^5.31.0",
|
|
141
144
|
"babel-jest": "^28.1.3",
|
|
142
145
|
"discord.js": "^14.0.3",
|
|
143
146
|
eslint: "^8.20.0",
|
|
@@ -152,7 +155,7 @@ var require_package = __commonJS({
|
|
|
152
155
|
"npm-check-updates": "^16.0.0",
|
|
153
156
|
pinst: "^3.0.0",
|
|
154
157
|
prettier: "^2.7.1",
|
|
155
|
-
tsup: "^6.
|
|
158
|
+
tsup: "^6.2.0",
|
|
156
159
|
typescript: "^4.7.4"
|
|
157
160
|
},
|
|
158
161
|
peerDependencies: {
|
|
@@ -239,25 +242,6 @@ __export(src_exports, {
|
|
|
239
242
|
module.exports = __toCommonJS(src_exports);
|
|
240
243
|
|
|
241
244
|
// src/type.ts
|
|
242
|
-
var Events = /* @__PURE__ */ ((Events2) => {
|
|
243
|
-
Events2["ERROR"] = "error";
|
|
244
|
-
Events2["ADD_LIST"] = "addList";
|
|
245
|
-
Events2["ADD_SONG"] = "addSong";
|
|
246
|
-
Events2["PLAY_SONG"] = "playSong";
|
|
247
|
-
Events2["FINISH_SONG"] = "finishSong";
|
|
248
|
-
Events2["EMPTY"] = "empty";
|
|
249
|
-
Events2["FINISH"] = "finish";
|
|
250
|
-
Events2["INIT_QUEUE"] = "initQueue";
|
|
251
|
-
Events2["NO_RELATED"] = "noRelated";
|
|
252
|
-
Events2["DISCONNECT"] = "disconnect";
|
|
253
|
-
Events2["DELETE_QUEUE"] = "deleteQueue";
|
|
254
|
-
Events2["SEARCH_CANCEL"] = "searchCancel";
|
|
255
|
-
Events2["SEARCH_NO_RESULT"] = "searchNoResult";
|
|
256
|
-
Events2["SEARCH_DONE"] = "searchDone";
|
|
257
|
-
Events2["SEARCH_INVALID_ANSWER"] = "searchInvalidAnswer";
|
|
258
|
-
Events2["SEARCH_RESULT"] = "searchResult";
|
|
259
|
-
return Events2;
|
|
260
|
-
})(Events || {});
|
|
261
245
|
var RepeatMode = /* @__PURE__ */ ((RepeatMode2) => {
|
|
262
246
|
RepeatMode2[RepeatMode2["DISABLED"] = 0] = "DISABLED";
|
|
263
247
|
RepeatMode2[RepeatMode2["SONG"] = 1] = "SONG";
|
|
@@ -279,6 +263,25 @@ var StreamType = /* @__PURE__ */ ((StreamType2) => {
|
|
|
279
263
|
StreamType2[StreamType2["RAW"] = 1] = "RAW";
|
|
280
264
|
return StreamType2;
|
|
281
265
|
})(StreamType || {});
|
|
266
|
+
var Events = /* @__PURE__ */ ((Events2) => {
|
|
267
|
+
Events2["ERROR"] = "error";
|
|
268
|
+
Events2["ADD_LIST"] = "addList";
|
|
269
|
+
Events2["ADD_SONG"] = "addSong";
|
|
270
|
+
Events2["PLAY_SONG"] = "playSong";
|
|
271
|
+
Events2["FINISH_SONG"] = "finishSong";
|
|
272
|
+
Events2["EMPTY"] = "empty";
|
|
273
|
+
Events2["FINISH"] = "finish";
|
|
274
|
+
Events2["INIT_QUEUE"] = "initQueue";
|
|
275
|
+
Events2["NO_RELATED"] = "noRelated";
|
|
276
|
+
Events2["DISCONNECT"] = "disconnect";
|
|
277
|
+
Events2["DELETE_QUEUE"] = "deleteQueue";
|
|
278
|
+
Events2["SEARCH_CANCEL"] = "searchCancel";
|
|
279
|
+
Events2["SEARCH_NO_RESULT"] = "searchNoResult";
|
|
280
|
+
Events2["SEARCH_DONE"] = "searchDone";
|
|
281
|
+
Events2["SEARCH_INVALID_ANSWER"] = "searchInvalidAnswer";
|
|
282
|
+
Events2["SEARCH_RESULT"] = "searchResult";
|
|
283
|
+
return Events2;
|
|
284
|
+
})(Events || {});
|
|
282
285
|
|
|
283
286
|
// src/constant.ts
|
|
284
287
|
var defaultFilters = {
|
|
@@ -920,458 +923,140 @@ join_fn = /* @__PURE__ */ __name(function(channel) {
|
|
|
920
923
|
});
|
|
921
924
|
}, "#join");
|
|
922
925
|
|
|
923
|
-
// src/core/
|
|
924
|
-
var
|
|
925
|
-
var
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
create(channel) {
|
|
961
|
-
const existing = this.get(channel.guildId);
|
|
962
|
-
if (existing) {
|
|
963
|
-
existing.channel = channel;
|
|
964
|
-
return existing;
|
|
926
|
+
// src/core/DisTubeHandler.ts
|
|
927
|
+
var import_ytpl = __toESM(require("@distube/ytpl"));
|
|
928
|
+
var import_ytdl_core = __toESM(require("@distube/ytdl-core"));
|
|
929
|
+
var DisTubeHandler = class extends DisTubeBase {
|
|
930
|
+
constructor(distube) {
|
|
931
|
+
super(distube);
|
|
932
|
+
const client = this.client;
|
|
933
|
+
if (this.options.leaveOnEmpty) {
|
|
934
|
+
client.on("voiceStateUpdate", (oldState) => {
|
|
935
|
+
if (!oldState?.channel)
|
|
936
|
+
return;
|
|
937
|
+
const queue = this.queues.get(oldState);
|
|
938
|
+
if (!queue) {
|
|
939
|
+
if (isVoiceChannelEmpty(oldState)) {
|
|
940
|
+
setTimeout(() => {
|
|
941
|
+
if (!this.queues.get(oldState) && isVoiceChannelEmpty(oldState))
|
|
942
|
+
this.voices.leave(oldState);
|
|
943
|
+
}, this.options.emptyCooldown * 1e3).unref();
|
|
944
|
+
}
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
if (queue._emptyTimeout) {
|
|
948
|
+
clearTimeout(queue._emptyTimeout);
|
|
949
|
+
delete queue._emptyTimeout;
|
|
950
|
+
}
|
|
951
|
+
if (isVoiceChannelEmpty(oldState)) {
|
|
952
|
+
queue._emptyTimeout = setTimeout(() => {
|
|
953
|
+
delete queue._emptyTimeout;
|
|
954
|
+
if (isVoiceChannelEmpty(oldState)) {
|
|
955
|
+
queue.voice.leave();
|
|
956
|
+
this.emit("empty", queue);
|
|
957
|
+
if (queue.stopped)
|
|
958
|
+
queue.remove();
|
|
959
|
+
}
|
|
960
|
+
}, this.options.emptyCooldown * 1e3).unref();
|
|
961
|
+
}
|
|
962
|
+
});
|
|
965
963
|
}
|
|
966
|
-
return new DisTubeVoice(this, channel);
|
|
967
|
-
}
|
|
968
|
-
join(channel) {
|
|
969
|
-
const existing = this.get(channel.guildId);
|
|
970
|
-
if (existing)
|
|
971
|
-
return existing.join(channel);
|
|
972
|
-
return this.create(channel).join();
|
|
973
964
|
}
|
|
974
|
-
|
|
975
|
-
const
|
|
976
|
-
if (
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
965
|
+
get ytdlOptions() {
|
|
966
|
+
const options = this.options.ytdlOptions;
|
|
967
|
+
if (this.options.youtubeCookie) {
|
|
968
|
+
if (!options.requestOptions)
|
|
969
|
+
options.requestOptions = {};
|
|
970
|
+
if (!options.requestOptions.headers)
|
|
971
|
+
options.requestOptions.headers = {};
|
|
972
|
+
options.requestOptions.headers.cookie = this.options.youtubeCookie;
|
|
973
|
+
if (this.options.youtubeIdentityToken) {
|
|
974
|
+
options.requestOptions.headers["x-youtube-identity-token"] = this.options.youtubeIdentityToken;
|
|
982
975
|
}
|
|
983
976
|
}
|
|
977
|
+
return options;
|
|
984
978
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
var _validate, validate_fn, _resolveName, resolveName_fn, _resolveValue, resolveValue_fn, _apply, apply_fn;
|
|
990
|
-
var FilterManager = class extends BaseManager {
|
|
991
|
-
constructor(queue) {
|
|
992
|
-
super(queue.distube);
|
|
993
|
-
__privateAdd(this, _validate);
|
|
994
|
-
__privateAdd(this, _resolveName);
|
|
995
|
-
__privateAdd(this, _resolveValue);
|
|
996
|
-
__privateAdd(this, _apply);
|
|
997
|
-
__publicField(this, "queue");
|
|
998
|
-
this.queue = queue;
|
|
979
|
+
getYouTubeInfo(url, basic = false) {
|
|
980
|
+
if (basic)
|
|
981
|
+
return import_ytdl_core.default.getBasicInfo(url, this.ytdlOptions);
|
|
982
|
+
return import_ytdl_core.default.getInfo(url, this.ytdlOptions);
|
|
999
983
|
}
|
|
1000
|
-
|
|
1001
|
-
if (
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
if (this.has(o) && override) {
|
|
1008
|
-
this.remove(o);
|
|
1009
|
-
unique.push(o);
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
return unique;
|
|
1013
|
-
}, []).reverse();
|
|
1014
|
-
return this.set([...this.collection.values(), ...newFilters]);
|
|
984
|
+
async resolve(song, options = {}) {
|
|
985
|
+
if (song instanceof Song || song instanceof Playlist) {
|
|
986
|
+
if ("metadata" in options)
|
|
987
|
+
song.metadata = options.metadata;
|
|
988
|
+
if ("member" in options)
|
|
989
|
+
song.member = options.member;
|
|
990
|
+
return song;
|
|
1015
991
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
992
|
+
if (song instanceof SearchResultVideo)
|
|
993
|
+
return new Song(song, options);
|
|
994
|
+
if (song instanceof SearchResultPlaylist)
|
|
995
|
+
return this.resolvePlaylist(song.url, options);
|
|
996
|
+
if (isObject(song)) {
|
|
997
|
+
if (!("url" in song) && !("id" in song))
|
|
998
|
+
throw new DisTubeError("CANNOT_RESOLVE_SONG", song);
|
|
999
|
+
return new Song(song, options);
|
|
1000
|
+
}
|
|
1001
|
+
if (import_ytpl.default.validateID(song))
|
|
1002
|
+
return this.resolvePlaylist(song, options);
|
|
1003
|
+
if (import_ytdl_core.default.validateURL(song))
|
|
1004
|
+
return new Song(await this.getYouTubeInfo(song, true), options);
|
|
1005
|
+
if (isURL(song)) {
|
|
1006
|
+
for (const plugin of this.distube.extractorPlugins) {
|
|
1007
|
+
if (await plugin.validate(song))
|
|
1008
|
+
return plugin.resolve(song, options);
|
|
1009
|
+
}
|
|
1010
|
+
throw new DisTubeError("NOT_SUPPORTED_URL");
|
|
1011
|
+
}
|
|
1012
|
+
throw new DisTubeError("CANNOT_RESOLVE_SONG", song);
|
|
1020
1013
|
}
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1014
|
+
async resolvePlaylist(playlist, options = {}) {
|
|
1015
|
+
const { member, source, metadata } = { source: "youtube", ...options };
|
|
1016
|
+
if (playlist instanceof Playlist) {
|
|
1017
|
+
if ("metadata" in options)
|
|
1018
|
+
playlist.metadata = metadata;
|
|
1019
|
+
if ("member" in options)
|
|
1020
|
+
playlist.member = member;
|
|
1021
|
+
return playlist;
|
|
1026
1022
|
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1023
|
+
if (typeof playlist === "string") {
|
|
1024
|
+
const info = await (0, import_ytpl.default)(playlist, { limit: Infinity });
|
|
1025
|
+
const songs = info.items.filter((v) => !v.thumbnail.includes("no_thumbnail")).map((v) => new Song(v, { member, metadata }));
|
|
1026
|
+
return new Playlist(
|
|
1027
|
+
{
|
|
1028
|
+
source,
|
|
1029
|
+
songs,
|
|
1030
|
+
member,
|
|
1031
|
+
name: info.title,
|
|
1032
|
+
url: info.url,
|
|
1033
|
+
thumbnail: songs[0].thumbnail
|
|
1034
|
+
},
|
|
1035
|
+
{ metadata }
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
return new Playlist(playlist, { member, properties: { source }, metadata });
|
|
1029
1039
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
return this.
|
|
1050
|
-
}
|
|
1051
|
-
};
|
|
1052
|
-
__name(FilterManager, "FilterManager");
|
|
1053
|
-
_validate = new WeakSet();
|
|
1054
|
-
validate_fn = /* @__PURE__ */ __name(function(filter) {
|
|
1055
|
-
if (typeof filter === "string" && Object.prototype.hasOwnProperty.call(this.distube.filters, filter) || typeof filter === "object" && typeof filter.name === "string" && typeof filter.value === "string") {
|
|
1056
|
-
return filter;
|
|
1057
|
-
}
|
|
1058
|
-
throw new DisTubeError("INVALID_TYPE", "FilterResolvable", filter, "filter");
|
|
1059
|
-
}, "#validate");
|
|
1060
|
-
_resolveName = new WeakSet();
|
|
1061
|
-
resolveName_fn = /* @__PURE__ */ __name(function(filter) {
|
|
1062
|
-
return typeof filter === "string" ? filter : filter.name;
|
|
1063
|
-
}, "#resolveName");
|
|
1064
|
-
_resolveValue = new WeakSet();
|
|
1065
|
-
resolveValue_fn = /* @__PURE__ */ __name(function(filter) {
|
|
1066
|
-
return typeof filter === "string" ? this.distube.filters[filter] : filter.value;
|
|
1067
|
-
}, "#resolveValue");
|
|
1068
|
-
_apply = new WeakSet();
|
|
1069
|
-
apply_fn = /* @__PURE__ */ __name(function() {
|
|
1070
|
-
this.queue.beginTime = this.queue.currentTime;
|
|
1071
|
-
this.queues.playSong(this.queue);
|
|
1072
|
-
}, "#apply");
|
|
1073
|
-
|
|
1074
|
-
// src/core/manager/QueueManager.ts
|
|
1075
|
-
var _voiceEventHandler, voiceEventHandler_fn, _handleSongFinish, handleSongFinish_fn, _handlePlayingError, handlePlayingError_fn, _emitPlaySong, emitPlaySong_fn;
|
|
1076
|
-
var QueueManager = class extends GuildIdManager {
|
|
1077
|
-
constructor() {
|
|
1078
|
-
super(...arguments);
|
|
1079
|
-
__privateAdd(this, _voiceEventHandler);
|
|
1080
|
-
__privateAdd(this, _handleSongFinish);
|
|
1081
|
-
__privateAdd(this, _handlePlayingError);
|
|
1082
|
-
__privateAdd(this, _emitPlaySong);
|
|
1083
|
-
}
|
|
1084
|
-
async create(channel, song, textChannel) {
|
|
1085
|
-
if (this.has(channel.guildId))
|
|
1086
|
-
throw new DisTubeError("QUEUE_EXIST");
|
|
1087
|
-
const voice = this.voices.create(channel);
|
|
1088
|
-
const queue = new Queue(this.distube, voice, song, textChannel);
|
|
1089
|
-
await queue._taskQueue.queuing();
|
|
1090
|
-
try {
|
|
1091
|
-
await voice.join();
|
|
1092
|
-
__privateMethod(this, _voiceEventHandler, voiceEventHandler_fn).call(this, queue);
|
|
1093
|
-
this.add(queue.id, queue);
|
|
1094
|
-
this.emit("initQueue", queue);
|
|
1095
|
-
const err = await this.playSong(queue);
|
|
1096
|
-
return err || queue;
|
|
1097
|
-
} finally {
|
|
1098
|
-
queue._taskQueue.resolve();
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
createStream(queue) {
|
|
1102
|
-
const { duration, formats, isLive, source, streamURL } = queue.songs[0];
|
|
1103
|
-
const ffmpegArgs = queue.filters.size ? ["-af", queue.filters.values.join(",")] : void 0;
|
|
1104
|
-
const seek = duration ? queue.beginTime : void 0;
|
|
1105
|
-
const streamOptions = { ffmpegArgs, seek, isLive, type: this.options.streamType };
|
|
1106
|
-
if (source === "youtube")
|
|
1107
|
-
return DisTubeStream.YouTube(formats, streamOptions);
|
|
1108
|
-
return DisTubeStream.DirectLink(streamURL, streamOptions);
|
|
1109
|
-
}
|
|
1110
|
-
async playSong(queue) {
|
|
1111
|
-
if (!queue)
|
|
1112
|
-
return true;
|
|
1113
|
-
if (!queue.songs.length) {
|
|
1114
|
-
queue.stop();
|
|
1115
|
-
return true;
|
|
1116
|
-
}
|
|
1117
|
-
if (queue.stopped)
|
|
1118
|
-
return false;
|
|
1119
|
-
try {
|
|
1120
|
-
const song = queue.songs[0];
|
|
1121
|
-
const { url, source, formats, streamURL } = song;
|
|
1122
|
-
if (source === "youtube" && !formats)
|
|
1123
|
-
song._patchYouTube(await this.handler.getYouTubeInfo(url));
|
|
1124
|
-
if (source !== "youtube" && !streamURL) {
|
|
1125
|
-
for (const plugin of [...this.distube.extractorPlugins, ...this.distube.customPlugins]) {
|
|
1126
|
-
if (await plugin.validate(url)) {
|
|
1127
|
-
const info = [plugin.getStreamURL(url), plugin.getRelatedSongs(url)];
|
|
1128
|
-
const result = await Promise.all(info);
|
|
1129
|
-
song.streamURL = result[0];
|
|
1130
|
-
song.related = result[1];
|
|
1131
|
-
break;
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
const stream = this.createStream(queue);
|
|
1136
|
-
queue.voice.play(stream);
|
|
1137
|
-
song.streamURL = stream.url;
|
|
1138
|
-
if (queue.stopped)
|
|
1139
|
-
queue.stop();
|
|
1140
|
-
else if (queue.paused)
|
|
1141
|
-
queue.voice.pause();
|
|
1142
|
-
return false;
|
|
1143
|
-
} catch (e) {
|
|
1144
|
-
__privateMethod(this, _handlePlayingError, handlePlayingError_fn).call(this, queue, e);
|
|
1145
|
-
return true;
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
};
|
|
1149
|
-
__name(QueueManager, "QueueManager");
|
|
1150
|
-
_voiceEventHandler = new WeakSet();
|
|
1151
|
-
voiceEventHandler_fn = /* @__PURE__ */ __name(function(queue) {
|
|
1152
|
-
queue._listeners = {
|
|
1153
|
-
disconnect: (error) => {
|
|
1154
|
-
queue.remove();
|
|
1155
|
-
this.emit("disconnect", queue);
|
|
1156
|
-
if (error)
|
|
1157
|
-
this.emitError(error, queue.textChannel);
|
|
1158
|
-
},
|
|
1159
|
-
error: (error) => __privateMethod(this, _handlePlayingError, handlePlayingError_fn).call(this, queue, error),
|
|
1160
|
-
finish: () => __privateMethod(this, _handleSongFinish, handleSongFinish_fn).call(this, queue)
|
|
1161
|
-
};
|
|
1162
|
-
for (const event of objectKeys(queue._listeners)) {
|
|
1163
|
-
queue.voice.on(event, queue._listeners[event]);
|
|
1164
|
-
}
|
|
1165
|
-
}, "#voiceEventHandler");
|
|
1166
|
-
_handleSongFinish = new WeakSet();
|
|
1167
|
-
handleSongFinish_fn = /* @__PURE__ */ __name(async function(queue) {
|
|
1168
|
-
this.emit("finishSong", queue, queue.songs[0]);
|
|
1169
|
-
await queue._taskQueue.queuing();
|
|
1170
|
-
try {
|
|
1171
|
-
if (queue.stopped)
|
|
1172
|
-
return;
|
|
1173
|
-
if (queue.repeatMode === 2 /* QUEUE */ && !queue._prev)
|
|
1174
|
-
queue.songs.push(queue.songs[0]);
|
|
1175
|
-
if (queue._prev) {
|
|
1176
|
-
if (queue.repeatMode === 2 /* QUEUE */)
|
|
1177
|
-
queue.songs.unshift(queue.songs.pop());
|
|
1178
|
-
else
|
|
1179
|
-
queue.songs.unshift(queue.previousSongs.pop());
|
|
1180
|
-
}
|
|
1181
|
-
if (queue.songs.length <= 1 && (queue._next || queue.repeatMode === 0 /* DISABLED */)) {
|
|
1182
|
-
if (queue.autoplay) {
|
|
1183
|
-
try {
|
|
1184
|
-
await queue.addRelatedSong();
|
|
1185
|
-
} catch {
|
|
1186
|
-
this.emit("noRelated", queue);
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
if (queue.songs.length <= 1) {
|
|
1190
|
-
if (this.options.leaveOnFinish)
|
|
1191
|
-
queue.voice.leave();
|
|
1192
|
-
if (!queue.autoplay)
|
|
1193
|
-
this.emit("finish", queue);
|
|
1194
|
-
queue.remove();
|
|
1195
|
-
return;
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
const emitPlaySong = __privateMethod(this, _emitPlaySong, emitPlaySong_fn).call(this, queue);
|
|
1199
|
-
if (!queue._prev && (queue.repeatMode !== 1 /* SONG */ || queue._next)) {
|
|
1200
|
-
const prev = queue.songs.shift();
|
|
1201
|
-
delete prev.formats;
|
|
1202
|
-
delete prev.streamURL;
|
|
1203
|
-
if (this.options.savePreviousSongs)
|
|
1204
|
-
queue.previousSongs.push(prev);
|
|
1205
|
-
else
|
|
1206
|
-
queue.previousSongs.push({ id: prev.id });
|
|
1207
|
-
}
|
|
1208
|
-
queue._next = queue._prev = false;
|
|
1209
|
-
queue.beginTime = 0;
|
|
1210
|
-
const err = await this.playSong(queue);
|
|
1211
|
-
if (!err && emitPlaySong)
|
|
1212
|
-
this.emit("playSong", queue, queue.songs[0]);
|
|
1213
|
-
} finally {
|
|
1214
|
-
queue._taskQueue.resolve();
|
|
1215
|
-
}
|
|
1216
|
-
}, "#handleSongFinish");
|
|
1217
|
-
_handlePlayingError = new WeakSet();
|
|
1218
|
-
handlePlayingError_fn = /* @__PURE__ */ __name(function(queue, error) {
|
|
1219
|
-
const song = queue.songs.shift();
|
|
1220
|
-
try {
|
|
1221
|
-
error.name = "PlayingError";
|
|
1222
|
-
error.message = `${error.message}
|
|
1223
|
-
Id: ${song.id}
|
|
1224
|
-
Name: ${song.name}`;
|
|
1225
|
-
} catch {
|
|
1226
|
-
}
|
|
1227
|
-
this.emitError(error, queue.textChannel);
|
|
1228
|
-
if (queue.songs.length > 0) {
|
|
1229
|
-
queue._next = queue._prev = false;
|
|
1230
|
-
queue.beginTime = 0;
|
|
1231
|
-
this.playSong(queue).then((e) => {
|
|
1232
|
-
if (!e)
|
|
1233
|
-
this.emit("playSong", queue, queue.songs[0]);
|
|
1234
|
-
});
|
|
1235
|
-
} else {
|
|
1236
|
-
queue.stop();
|
|
1237
|
-
}
|
|
1238
|
-
}, "#handlePlayingError");
|
|
1239
|
-
_emitPlaySong = new WeakSet();
|
|
1240
|
-
emitPlaySong_fn = /* @__PURE__ */ __name(function(queue) {
|
|
1241
|
-
return !this.options.emitNewSongOnly || queue.repeatMode === 1 /* SONG */ && queue._next || queue.repeatMode !== 1 /* SONG */ && queue.songs[0]?.id !== queue.songs[1]?.id;
|
|
1242
|
-
}, "#emitPlaySong");
|
|
1243
|
-
|
|
1244
|
-
// src/core/DisTubeHandler.ts
|
|
1245
|
-
var import_ytpl = __toESM(require("@distube/ytpl"));
|
|
1246
|
-
var import_ytdl_core = __toESM(require("@distube/ytdl-core"));
|
|
1247
|
-
var DisTubeHandler = class extends DisTubeBase {
|
|
1248
|
-
constructor(distube) {
|
|
1249
|
-
super(distube);
|
|
1250
|
-
const client = this.client;
|
|
1251
|
-
if (this.options.leaveOnEmpty) {
|
|
1252
|
-
client.on("voiceStateUpdate", (oldState) => {
|
|
1253
|
-
if (!oldState?.channel)
|
|
1254
|
-
return;
|
|
1255
|
-
const queue = this.queues.get(oldState);
|
|
1256
|
-
if (!queue) {
|
|
1257
|
-
if (isVoiceChannelEmpty(oldState)) {
|
|
1258
|
-
setTimeout(() => {
|
|
1259
|
-
if (!this.queues.get(oldState) && isVoiceChannelEmpty(oldState))
|
|
1260
|
-
this.voices.leave(oldState);
|
|
1261
|
-
}, this.options.emptyCooldown * 1e3).unref();
|
|
1262
|
-
}
|
|
1263
|
-
return;
|
|
1264
|
-
}
|
|
1265
|
-
if (queue._emptyTimeout) {
|
|
1266
|
-
clearTimeout(queue._emptyTimeout);
|
|
1267
|
-
delete queue._emptyTimeout;
|
|
1268
|
-
}
|
|
1269
|
-
if (isVoiceChannelEmpty(oldState)) {
|
|
1270
|
-
queue._emptyTimeout = setTimeout(() => {
|
|
1271
|
-
delete queue._emptyTimeout;
|
|
1272
|
-
if (isVoiceChannelEmpty(oldState)) {
|
|
1273
|
-
queue.voice.leave();
|
|
1274
|
-
this.emit("empty", queue);
|
|
1275
|
-
if (queue.stopped)
|
|
1276
|
-
queue.remove();
|
|
1277
|
-
}
|
|
1278
|
-
}, this.options.emptyCooldown * 1e3).unref();
|
|
1279
|
-
}
|
|
1280
|
-
});
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
get ytdlOptions() {
|
|
1284
|
-
const options = this.options.ytdlOptions;
|
|
1285
|
-
if (this.options.youtubeCookie) {
|
|
1286
|
-
if (!options.requestOptions)
|
|
1287
|
-
options.requestOptions = {};
|
|
1288
|
-
if (!options.requestOptions.headers)
|
|
1289
|
-
options.requestOptions.headers = {};
|
|
1290
|
-
options.requestOptions.headers.cookie = this.options.youtubeCookie;
|
|
1291
|
-
if (this.options.youtubeIdentityToken) {
|
|
1292
|
-
options.requestOptions.headers["x-youtube-identity-token"] = this.options.youtubeIdentityToken;
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
return options;
|
|
1296
|
-
}
|
|
1297
|
-
getYouTubeInfo(url, basic = false) {
|
|
1298
|
-
if (basic)
|
|
1299
|
-
return import_ytdl_core.default.getBasicInfo(url, this.ytdlOptions);
|
|
1300
|
-
return import_ytdl_core.default.getInfo(url, this.ytdlOptions);
|
|
1301
|
-
}
|
|
1302
|
-
async resolve(song, options = {}) {
|
|
1303
|
-
if (song instanceof Song || song instanceof Playlist) {
|
|
1304
|
-
if ("metadata" in options)
|
|
1305
|
-
song.metadata = options.metadata;
|
|
1306
|
-
if ("member" in options)
|
|
1307
|
-
song.member = options.member;
|
|
1308
|
-
return song;
|
|
1309
|
-
}
|
|
1310
|
-
if (song instanceof SearchResultVideo)
|
|
1311
|
-
return new Song(song, options);
|
|
1312
|
-
if (song instanceof SearchResultPlaylist)
|
|
1313
|
-
return this.resolvePlaylist(song.url, options);
|
|
1314
|
-
if (isObject(song)) {
|
|
1315
|
-
if (!("url" in song) && !("id" in song))
|
|
1316
|
-
throw new DisTubeError("CANNOT_RESOLVE_SONG", song);
|
|
1317
|
-
return new Song(song, options);
|
|
1318
|
-
}
|
|
1319
|
-
if (import_ytpl.default.validateID(song))
|
|
1320
|
-
return this.resolvePlaylist(song, options);
|
|
1321
|
-
if (import_ytdl_core.default.validateURL(song))
|
|
1322
|
-
return new Song(await this.getYouTubeInfo(song), options);
|
|
1323
|
-
if (isURL(song)) {
|
|
1324
|
-
for (const plugin of this.distube.extractorPlugins) {
|
|
1325
|
-
if (await plugin.validate(song))
|
|
1326
|
-
return plugin.resolve(song, options);
|
|
1327
|
-
}
|
|
1328
|
-
throw new DisTubeError("NOT_SUPPORTED_URL");
|
|
1329
|
-
}
|
|
1330
|
-
throw new DisTubeError("CANNOT_RESOLVE_SONG", song);
|
|
1331
|
-
}
|
|
1332
|
-
async resolvePlaylist(playlist, options = {}) {
|
|
1333
|
-
const { member, source, metadata } = { source: "youtube", ...options };
|
|
1334
|
-
if (playlist instanceof Playlist) {
|
|
1335
|
-
if ("metadata" in options)
|
|
1336
|
-
playlist.metadata = metadata;
|
|
1337
|
-
if ("member" in options)
|
|
1338
|
-
playlist.member = member;
|
|
1339
|
-
return playlist;
|
|
1340
|
-
}
|
|
1341
|
-
if (typeof playlist === "string") {
|
|
1342
|
-
const info = await (0, import_ytpl.default)(playlist, { limit: Infinity });
|
|
1343
|
-
const songs = info.items.filter((v) => !v.thumbnail.includes("no_thumbnail")).map((v) => new Song(v, { member, metadata }));
|
|
1344
|
-
return new Playlist({
|
|
1345
|
-
source,
|
|
1346
|
-
songs,
|
|
1347
|
-
member,
|
|
1348
|
-
name: info.title,
|
|
1349
|
-
url: info.url,
|
|
1350
|
-
thumbnail: songs[0].thumbnail
|
|
1351
|
-
}, { metadata });
|
|
1352
|
-
}
|
|
1353
|
-
return new Playlist(playlist, { member, properties: { source }, metadata });
|
|
1354
|
-
}
|
|
1355
|
-
async searchSong(message, query) {
|
|
1356
|
-
if (!isMessageInstance(message))
|
|
1357
|
-
throw new DisTubeError("INVALID_TYPE", "Discord.Message", message, "message");
|
|
1358
|
-
if (typeof query !== "string")
|
|
1359
|
-
throw new DisTubeError("INVALID_TYPE", "string", query, "query");
|
|
1360
|
-
if (query.length === 0)
|
|
1361
|
-
throw new DisTubeError("EMPTY_STRING", "query");
|
|
1362
|
-
const limit = this.options.searchSongs > 1 ? this.options.searchSongs : 1;
|
|
1363
|
-
const results = await this.distube.search(query, {
|
|
1364
|
-
limit,
|
|
1365
|
-
safeSearch: this.options.nsfw ? false : !message.channel?.nsfw
|
|
1366
|
-
}).catch(() => {
|
|
1367
|
-
if (!this.emit("searchNoResult", message, query)) {
|
|
1368
|
-
console.warn("searchNoResult event does not have any listeners! Emits `error` event instead.");
|
|
1369
|
-
throw new DisTubeError("NO_RESULT");
|
|
1370
|
-
}
|
|
1371
|
-
});
|
|
1372
|
-
if (!results)
|
|
1373
|
-
return null;
|
|
1374
|
-
return this.createSearchMessageCollector(message, results, query);
|
|
1040
|
+
async searchSong(message, query) {
|
|
1041
|
+
if (!isMessageInstance(message))
|
|
1042
|
+
throw new DisTubeError("INVALID_TYPE", "Discord.Message", message, "message");
|
|
1043
|
+
if (typeof query !== "string")
|
|
1044
|
+
throw new DisTubeError("INVALID_TYPE", "string", query, "query");
|
|
1045
|
+
if (query.length === 0)
|
|
1046
|
+
throw new DisTubeError("EMPTY_STRING", "query");
|
|
1047
|
+
const limit = this.options.searchSongs > 1 ? this.options.searchSongs : 1;
|
|
1048
|
+
const results = await this.distube.search(query, {
|
|
1049
|
+
limit,
|
|
1050
|
+
safeSearch: this.options.nsfw ? false : !message.channel?.nsfw
|
|
1051
|
+
}).catch(() => {
|
|
1052
|
+
if (!this.emit("searchNoResult", message, query)) {
|
|
1053
|
+
console.warn("searchNoResult event does not have any listeners! Emits `error` event instead.");
|
|
1054
|
+
throw new DisTubeError("NO_RESULT");
|
|
1055
|
+
}
|
|
1056
|
+
});
|
|
1057
|
+
if (!results)
|
|
1058
|
+
return null;
|
|
1059
|
+
return this.createSearchMessageCollector(message, results, query);
|
|
1375
1060
|
}
|
|
1376
1061
|
async createSearchMessageCollector(message, results, query) {
|
|
1377
1062
|
if (!isMessageInstance(message))
|
|
@@ -1390,8 +1075,10 @@ var DisTubeHandler = class extends DisTubeBase {
|
|
|
1390
1075
|
for (const evn of searchEvents) {
|
|
1391
1076
|
if (this.distube.listenerCount(evn) === 0) {
|
|
1392
1077
|
console.warn(`"searchSongs" option is disabled due to missing "${evn}" listener.`);
|
|
1393
|
-
console.warn(
|
|
1394
|
-
|
|
1078
|
+
console.warn(
|
|
1079
|
+
`If you don't want to use "${evn}" event, simply add an empty listener (not recommended):
|
|
1080
|
+
<DisTube>.on("${evn}", () => {})`
|
|
1081
|
+
);
|
|
1395
1082
|
this.options.searchSongs = 0;
|
|
1396
1083
|
}
|
|
1397
1084
|
}
|
|
@@ -1554,13 +1241,23 @@ validateOptions_fn = /* @__PURE__ */ __name(function(options = this) {
|
|
|
1554
1241
|
throw new DisTubeError("INVALID_TYPE", "boolean", options.savePreviousSongs, "DisTubeOptions.savePreviousSongs");
|
|
1555
1242
|
}
|
|
1556
1243
|
if (typeof options.joinNewVoiceChannel !== "boolean") {
|
|
1557
|
-
throw new DisTubeError(
|
|
1244
|
+
throw new DisTubeError(
|
|
1245
|
+
"INVALID_TYPE",
|
|
1246
|
+
"boolean",
|
|
1247
|
+
options.joinNewVoiceChannel,
|
|
1248
|
+
"DisTubeOptions.joinNewVoiceChannel"
|
|
1249
|
+
);
|
|
1558
1250
|
}
|
|
1559
1251
|
if (typeof options.youtubeCookie !== "undefined" && typeof options.youtubeCookie !== "string") {
|
|
1560
1252
|
throw new DisTubeError("INVALID_TYPE", "string", options.youtubeCookie, "DisTubeOptions.youtubeCookie");
|
|
1561
1253
|
}
|
|
1562
1254
|
if (typeof options.youtubeIdentityToken !== "undefined" && typeof options.youtubeIdentityToken !== "string") {
|
|
1563
|
-
throw new DisTubeError(
|
|
1255
|
+
throw new DisTubeError(
|
|
1256
|
+
"INVALID_TYPE",
|
|
1257
|
+
"string",
|
|
1258
|
+
options.youtubeIdentityToken,
|
|
1259
|
+
"DisTubeOptions.youtubeIdentityToken"
|
|
1260
|
+
);
|
|
1564
1261
|
}
|
|
1565
1262
|
if (typeof options.customFilters !== "undefined" && typeof options.customFilters !== "object" || Array.isArray(options.customFilters)) {
|
|
1566
1263
|
throw new DisTubeError("INVALID_TYPE", "object", options.customFilters, "DisTubeOptions.customFilters");
|
|
@@ -1583,91 +1280,425 @@ validateOptions_fn = /* @__PURE__ */ __name(function(options = this) {
|
|
|
1583
1280
|
if (typeof options.nsfw !== "boolean") {
|
|
1584
1281
|
throw new DisTubeError("INVALID_TYPE", "boolean", options.nsfw, "DisTubeOptions.nsfw");
|
|
1585
1282
|
}
|
|
1586
|
-
if (typeof options.emitAddSongWhenCreatingQueue !== "boolean") {
|
|
1587
|
-
throw new DisTubeError(
|
|
1283
|
+
if (typeof options.emitAddSongWhenCreatingQueue !== "boolean") {
|
|
1284
|
+
throw new DisTubeError(
|
|
1285
|
+
"INVALID_TYPE",
|
|
1286
|
+
"boolean",
|
|
1287
|
+
options.emitAddSongWhenCreatingQueue,
|
|
1288
|
+
"DisTubeOptions.emitAddSongWhenCreatingQueue"
|
|
1289
|
+
);
|
|
1290
|
+
}
|
|
1291
|
+
if (typeof options.emitAddListWhenCreatingQueue !== "boolean") {
|
|
1292
|
+
throw new DisTubeError(
|
|
1293
|
+
"INVALID_TYPE",
|
|
1294
|
+
"boolean",
|
|
1295
|
+
options.emitAddListWhenCreatingQueue,
|
|
1296
|
+
"DisTubeOptions.emitAddListWhenCreatingQueue"
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
if (typeof options.streamType !== "number" || isNaN(options.streamType) || !StreamType[options.streamType]) {
|
|
1300
|
+
throw new DisTubeError("INVALID_TYPE", "StreamType", options.streamType, "DisTubeOptions.streamType");
|
|
1301
|
+
}
|
|
1302
|
+
if (typeof options.directLink !== "boolean") {
|
|
1303
|
+
throw new DisTubeError("INVALID_TYPE", "boolean", options.directLink, "DisTubeOptions.directLink");
|
|
1304
|
+
}
|
|
1305
|
+
}, "#validateOptions");
|
|
1306
|
+
|
|
1307
|
+
// src/core/DisTubeStream.ts
|
|
1308
|
+
var import_prism_media = require("prism-media");
|
|
1309
|
+
var import_voice2 = require("@discordjs/voice");
|
|
1310
|
+
var chooseBestVideoFormat = /* @__PURE__ */ __name((formats, isLive = false) => {
|
|
1311
|
+
let filter = /* @__PURE__ */ __name((format) => format.hasAudio, "filter");
|
|
1312
|
+
if (isLive)
|
|
1313
|
+
filter = /* @__PURE__ */ __name((format) => format.hasAudio && format.isHLS, "filter");
|
|
1314
|
+
formats = formats.filter(filter).sort((a, b) => Number(b.audioBitrate) - Number(a.audioBitrate) || Number(a.bitrate) - Number(b.bitrate));
|
|
1315
|
+
return formats.find((format) => !format.hasVideo) || formats.sort((a, b) => Number(a.bitrate) - Number(b.bitrate))[0];
|
|
1316
|
+
}, "chooseBestVideoFormat");
|
|
1317
|
+
var DisTubeStream = class {
|
|
1318
|
+
constructor(url, options) {
|
|
1319
|
+
__publicField(this, "type");
|
|
1320
|
+
__publicField(this, "stream");
|
|
1321
|
+
__publicField(this, "url");
|
|
1322
|
+
this.url = url;
|
|
1323
|
+
this.type = !options.type ? import_voice2.StreamType.OggOpus : import_voice2.StreamType.Raw;
|
|
1324
|
+
const args = [
|
|
1325
|
+
"-reconnect",
|
|
1326
|
+
"1",
|
|
1327
|
+
"-reconnect_streamed",
|
|
1328
|
+
"1",
|
|
1329
|
+
"-reconnect_delay_max",
|
|
1330
|
+
"5",
|
|
1331
|
+
"-i",
|
|
1332
|
+
url,
|
|
1333
|
+
"-analyzeduration",
|
|
1334
|
+
"0",
|
|
1335
|
+
"-loglevel",
|
|
1336
|
+
"0",
|
|
1337
|
+
"-ar",
|
|
1338
|
+
"48000",
|
|
1339
|
+
"-ac",
|
|
1340
|
+
"2",
|
|
1341
|
+
"-f"
|
|
1342
|
+
];
|
|
1343
|
+
if (!options.type) {
|
|
1344
|
+
args.push("opus", "-acodec", "libopus");
|
|
1345
|
+
} else {
|
|
1346
|
+
args.push("s16le");
|
|
1347
|
+
}
|
|
1348
|
+
if (typeof options.seek === "number" && options.seek > 0) {
|
|
1349
|
+
args.unshift("-ss", options.seek.toString());
|
|
1350
|
+
}
|
|
1351
|
+
if (Array.isArray(options.ffmpegArgs)) {
|
|
1352
|
+
args.push(...options.ffmpegArgs);
|
|
1353
|
+
}
|
|
1354
|
+
this.stream = new import_prism_media.FFmpeg({ args, shell: false });
|
|
1355
|
+
this.stream._readableState && (this.stream._readableState.highWaterMark = 1 << 25);
|
|
1356
|
+
}
|
|
1357
|
+
static YouTube(formats, options = {}) {
|
|
1358
|
+
if (!formats || !formats.length)
|
|
1359
|
+
throw new DisTubeError("UNAVAILABLE_VIDEO");
|
|
1360
|
+
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
1361
|
+
throw new DisTubeError("INVALID_TYPE", "object", options, "options");
|
|
1362
|
+
}
|
|
1363
|
+
const bestFormat = chooseBestVideoFormat(formats, options.isLive);
|
|
1364
|
+
if (!bestFormat)
|
|
1365
|
+
throw new DisTubeError("UNPLAYABLE_FORMATS");
|
|
1366
|
+
return new DisTubeStream(bestFormat.url, options);
|
|
1367
|
+
}
|
|
1368
|
+
static DirectLink(url, options = {}) {
|
|
1369
|
+
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
1370
|
+
throw new DisTubeError("INVALID_TYPE", "object", options, "options");
|
|
1371
|
+
}
|
|
1372
|
+
if (typeof url !== "string" || !isURL(url)) {
|
|
1373
|
+
throw new DisTubeError("INVALID_TYPE", "an URL", url);
|
|
1374
|
+
}
|
|
1375
|
+
return new DisTubeStream(url, options);
|
|
1376
|
+
}
|
|
1377
|
+
};
|
|
1378
|
+
__name(DisTubeStream, "DisTubeStream");
|
|
1379
|
+
|
|
1380
|
+
// src/core/manager/BaseManager.ts
|
|
1381
|
+
var import_discord2 = require("discord.js");
|
|
1382
|
+
var BaseManager = class extends DisTubeBase {
|
|
1383
|
+
constructor() {
|
|
1384
|
+
super(...arguments);
|
|
1385
|
+
__publicField(this, "collection", new import_discord2.Collection());
|
|
1386
|
+
}
|
|
1387
|
+
get size() {
|
|
1388
|
+
return this.collection.size;
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1391
|
+
__name(BaseManager, "BaseManager");
|
|
1392
|
+
|
|
1393
|
+
// src/core/manager/GuildIdManager.ts
|
|
1394
|
+
var GuildIdManager = class extends BaseManager {
|
|
1395
|
+
add(idOrInstance, data) {
|
|
1396
|
+
const id = resolveGuildId(idOrInstance);
|
|
1397
|
+
const existing = this.get(id);
|
|
1398
|
+
if (existing)
|
|
1399
|
+
return this;
|
|
1400
|
+
return this.collection.set(id, data);
|
|
1401
|
+
}
|
|
1402
|
+
get(idOrInstance) {
|
|
1403
|
+
return this.collection.get(resolveGuildId(idOrInstance));
|
|
1404
|
+
}
|
|
1405
|
+
remove(idOrInstance) {
|
|
1406
|
+
return this.collection.delete(resolveGuildId(idOrInstance));
|
|
1407
|
+
}
|
|
1408
|
+
has(idOrInstance) {
|
|
1409
|
+
return this.collection.has(resolveGuildId(idOrInstance));
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
__name(GuildIdManager, "GuildIdManager");
|
|
1413
|
+
|
|
1414
|
+
// src/core/manager/DisTubeVoiceManager.ts
|
|
1415
|
+
var import_voice3 = require("@discordjs/voice");
|
|
1416
|
+
var DisTubeVoiceManager = class extends GuildIdManager {
|
|
1417
|
+
create(channel) {
|
|
1418
|
+
const existing = this.get(channel.guildId);
|
|
1419
|
+
if (existing) {
|
|
1420
|
+
existing.channel = channel;
|
|
1421
|
+
return existing;
|
|
1422
|
+
}
|
|
1423
|
+
return new DisTubeVoice(this, channel);
|
|
1424
|
+
}
|
|
1425
|
+
join(channel) {
|
|
1426
|
+
const existing = this.get(channel.guildId);
|
|
1427
|
+
if (existing)
|
|
1428
|
+
return existing.join(channel);
|
|
1429
|
+
return this.create(channel).join();
|
|
1430
|
+
}
|
|
1431
|
+
leave(guild) {
|
|
1432
|
+
const voice = this.get(guild);
|
|
1433
|
+
if (voice) {
|
|
1434
|
+
voice.leave();
|
|
1435
|
+
} else {
|
|
1436
|
+
const connection = (0, import_voice3.getVoiceConnection)(resolveGuildId(guild), this.client.user?.id) ?? (0, import_voice3.getVoiceConnection)(resolveGuildId(guild));
|
|
1437
|
+
if (connection && connection.state.status !== import_voice3.VoiceConnectionStatus.Destroyed) {
|
|
1438
|
+
connection.destroy();
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
};
|
|
1443
|
+
__name(DisTubeVoiceManager, "DisTubeVoiceManager");
|
|
1444
|
+
|
|
1445
|
+
// src/core/manager/FilterManager.ts
|
|
1446
|
+
var _validate, validate_fn, _resolveName, resolveName_fn, _resolveValue, resolveValue_fn, _apply, apply_fn;
|
|
1447
|
+
var FilterManager = class extends BaseManager {
|
|
1448
|
+
constructor(queue) {
|
|
1449
|
+
super(queue.distube);
|
|
1450
|
+
__privateAdd(this, _validate);
|
|
1451
|
+
__privateAdd(this, _resolveName);
|
|
1452
|
+
__privateAdd(this, _resolveValue);
|
|
1453
|
+
__privateAdd(this, _apply);
|
|
1454
|
+
__publicField(this, "queue");
|
|
1455
|
+
this.queue = queue;
|
|
1456
|
+
}
|
|
1457
|
+
add(filterOrFilters, override = false) {
|
|
1458
|
+
if (Array.isArray(filterOrFilters)) {
|
|
1459
|
+
const resolvedFilters = filterOrFilters.map((f) => __privateMethod(this, _validate, validate_fn).call(this, f));
|
|
1460
|
+
const newFilters = resolvedFilters.reduceRight((unique, o) => {
|
|
1461
|
+
if (!unique.some((obj) => obj === o && obj.name === o) && !unique.some((obj) => obj !== o.name && obj.name !== o.name)) {
|
|
1462
|
+
if (!this.has(o))
|
|
1463
|
+
unique.push(o);
|
|
1464
|
+
if (this.has(o) && override) {
|
|
1465
|
+
this.remove(o);
|
|
1466
|
+
unique.push(o);
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
return unique;
|
|
1470
|
+
}, []).reverse();
|
|
1471
|
+
return this.set([...this.collection.values(), ...newFilters]);
|
|
1472
|
+
}
|
|
1473
|
+
return this.set([...this.collection.values(), filterOrFilters]);
|
|
1474
|
+
}
|
|
1475
|
+
clear() {
|
|
1476
|
+
return this.set([]);
|
|
1477
|
+
}
|
|
1478
|
+
set(filters) {
|
|
1479
|
+
this.collection.clear();
|
|
1480
|
+
for (const filter of filters) {
|
|
1481
|
+
const resolved = __privateMethod(this, _validate, validate_fn).call(this, filter);
|
|
1482
|
+
this.collection.set(__privateMethod(this, _resolveName, resolveName_fn).call(this, resolved), resolved);
|
|
1483
|
+
}
|
|
1484
|
+
__privateMethod(this, _apply, apply_fn).call(this);
|
|
1485
|
+
return this;
|
|
1486
|
+
}
|
|
1487
|
+
remove(filterOrFilters) {
|
|
1488
|
+
const remove = /* @__PURE__ */ __name((f) => this.collection.delete(__privateMethod(this, _resolveName, resolveName_fn).call(this, __privateMethod(this, _validate, validate_fn).call(this, f))), "remove");
|
|
1489
|
+
if (Array.isArray(filterOrFilters))
|
|
1490
|
+
filterOrFilters.map(remove);
|
|
1491
|
+
else
|
|
1492
|
+
remove(filterOrFilters);
|
|
1493
|
+
__privateMethod(this, _apply, apply_fn).call(this);
|
|
1494
|
+
return this;
|
|
1495
|
+
}
|
|
1496
|
+
has(filter) {
|
|
1497
|
+
return this.collection.has(__privateMethod(this, _resolveName, resolveName_fn).call(this, filter));
|
|
1498
|
+
}
|
|
1499
|
+
get names() {
|
|
1500
|
+
return this.collection.map((f) => __privateMethod(this, _resolveName, resolveName_fn).call(this, f));
|
|
1588
1501
|
}
|
|
1589
|
-
|
|
1590
|
-
|
|
1502
|
+
get values() {
|
|
1503
|
+
return this.collection.map((f) => __privateMethod(this, _resolveValue, resolveValue_fn).call(this, f));
|
|
1591
1504
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1505
|
+
toString() {
|
|
1506
|
+
return this.names.toString();
|
|
1594
1507
|
}
|
|
1595
|
-
|
|
1596
|
-
|
|
1508
|
+
};
|
|
1509
|
+
__name(FilterManager, "FilterManager");
|
|
1510
|
+
_validate = new WeakSet();
|
|
1511
|
+
validate_fn = /* @__PURE__ */ __name(function(filter) {
|
|
1512
|
+
if (typeof filter === "string" && Object.prototype.hasOwnProperty.call(this.distube.filters, filter) || typeof filter === "object" && typeof filter.name === "string" && typeof filter.value === "string") {
|
|
1513
|
+
return filter;
|
|
1597
1514
|
}
|
|
1598
|
-
|
|
1515
|
+
throw new DisTubeError("INVALID_TYPE", "FilterResolvable", filter, "filter");
|
|
1516
|
+
}, "#validate");
|
|
1517
|
+
_resolveName = new WeakSet();
|
|
1518
|
+
resolveName_fn = /* @__PURE__ */ __name(function(filter) {
|
|
1519
|
+
return typeof filter === "string" ? filter : filter.name;
|
|
1520
|
+
}, "#resolveName");
|
|
1521
|
+
_resolveValue = new WeakSet();
|
|
1522
|
+
resolveValue_fn = /* @__PURE__ */ __name(function(filter) {
|
|
1523
|
+
return typeof filter === "string" ? this.distube.filters[filter] : filter.value;
|
|
1524
|
+
}, "#resolveValue");
|
|
1525
|
+
_apply = new WeakSet();
|
|
1526
|
+
apply_fn = /* @__PURE__ */ __name(function() {
|
|
1527
|
+
this.queue.beginTime = this.queue.currentTime;
|
|
1528
|
+
this.queues.playSong(this.queue);
|
|
1529
|
+
}, "#apply");
|
|
1599
1530
|
|
|
1600
|
-
// src/core/
|
|
1601
|
-
var
|
|
1602
|
-
var
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
"
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
url,
|
|
1626
|
-
"-analyzeduration",
|
|
1627
|
-
"0",
|
|
1628
|
-
"-loglevel",
|
|
1629
|
-
"0",
|
|
1630
|
-
"-ar",
|
|
1631
|
-
"48000",
|
|
1632
|
-
"-ac",
|
|
1633
|
-
"2",
|
|
1634
|
-
"-f"
|
|
1635
|
-
];
|
|
1636
|
-
if (!options.type) {
|
|
1637
|
-
args.push("opus", "-acodec", "libopus");
|
|
1638
|
-
} else {
|
|
1639
|
-
args.push("s16le");
|
|
1531
|
+
// src/core/manager/QueueManager.ts
|
|
1532
|
+
var _voiceEventHandler, voiceEventHandler_fn, _handleSongFinish, handleSongFinish_fn, _handlePlayingError, handlePlayingError_fn, _emitPlaySong, emitPlaySong_fn;
|
|
1533
|
+
var QueueManager = class extends GuildIdManager {
|
|
1534
|
+
constructor() {
|
|
1535
|
+
super(...arguments);
|
|
1536
|
+
__privateAdd(this, _voiceEventHandler);
|
|
1537
|
+
__privateAdd(this, _handleSongFinish);
|
|
1538
|
+
__privateAdd(this, _handlePlayingError);
|
|
1539
|
+
__privateAdd(this, _emitPlaySong);
|
|
1540
|
+
}
|
|
1541
|
+
async create(channel, song, textChannel) {
|
|
1542
|
+
if (this.has(channel.guildId))
|
|
1543
|
+
throw new DisTubeError("QUEUE_EXIST");
|
|
1544
|
+
const voice = this.voices.create(channel);
|
|
1545
|
+
const queue = new Queue(this.distube, voice, song, textChannel);
|
|
1546
|
+
await queue._taskQueue.queuing();
|
|
1547
|
+
try {
|
|
1548
|
+
await voice.join();
|
|
1549
|
+
__privateMethod(this, _voiceEventHandler, voiceEventHandler_fn).call(this, queue);
|
|
1550
|
+
this.add(queue.id, queue);
|
|
1551
|
+
this.emit("initQueue", queue);
|
|
1552
|
+
const err = await this.playSong(queue);
|
|
1553
|
+
return err || queue;
|
|
1554
|
+
} finally {
|
|
1555
|
+
queue._taskQueue.resolve();
|
|
1640
1556
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1557
|
+
}
|
|
1558
|
+
createStream(queue) {
|
|
1559
|
+
const { duration, formats, isLive, source, streamURL } = queue.songs[0];
|
|
1560
|
+
const ffmpegArgs = queue.filters.size ? ["-af", queue.filters.values.join(",")] : void 0;
|
|
1561
|
+
const seek = duration ? queue.beginTime : void 0;
|
|
1562
|
+
const streamOptions = { ffmpegArgs, seek, isLive, type: this.options.streamType };
|
|
1563
|
+
if (source === "youtube")
|
|
1564
|
+
return DisTubeStream.YouTube(formats, streamOptions);
|
|
1565
|
+
return DisTubeStream.DirectLink(streamURL, streamOptions);
|
|
1566
|
+
}
|
|
1567
|
+
async playSong(queue) {
|
|
1568
|
+
if (!queue)
|
|
1569
|
+
return true;
|
|
1570
|
+
if (!queue.songs.length) {
|
|
1571
|
+
queue.stop();
|
|
1572
|
+
return true;
|
|
1643
1573
|
}
|
|
1644
|
-
if (
|
|
1645
|
-
|
|
1574
|
+
if (queue.stopped)
|
|
1575
|
+
return false;
|
|
1576
|
+
try {
|
|
1577
|
+
const song = queue.songs[0];
|
|
1578
|
+
const { url, source, formats, streamURL, isLive } = song;
|
|
1579
|
+
if (source === "youtube") {
|
|
1580
|
+
if (!formats || !chooseBestVideoFormat(formats, isLive)) {
|
|
1581
|
+
song._patchYouTube(await this.handler.getYouTubeInfo(url));
|
|
1582
|
+
}
|
|
1583
|
+
} else if (!streamURL) {
|
|
1584
|
+
for (const plugin of [...this.distube.extractorPlugins, ...this.distube.customPlugins]) {
|
|
1585
|
+
if (await plugin.validate(url)) {
|
|
1586
|
+
const info = [plugin.getStreamURL(url), plugin.getRelatedSongs(url)];
|
|
1587
|
+
const result = await Promise.all(info);
|
|
1588
|
+
song.streamURL = result[0];
|
|
1589
|
+
song.related = result[1];
|
|
1590
|
+
break;
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
const stream = this.createStream(queue);
|
|
1595
|
+
queue.voice.play(stream);
|
|
1596
|
+
song.streamURL = stream.url;
|
|
1597
|
+
if (queue.stopped)
|
|
1598
|
+
queue.stop();
|
|
1599
|
+
else if (queue.paused)
|
|
1600
|
+
queue.voice.pause();
|
|
1601
|
+
return false;
|
|
1602
|
+
} catch (e) {
|
|
1603
|
+
__privateMethod(this, _handlePlayingError, handlePlayingError_fn).call(this, queue, e);
|
|
1604
|
+
return true;
|
|
1646
1605
|
}
|
|
1647
|
-
this.stream = new import_prism_media.FFmpeg({ args, shell: false });
|
|
1648
1606
|
}
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1607
|
+
};
|
|
1608
|
+
__name(QueueManager, "QueueManager");
|
|
1609
|
+
_voiceEventHandler = new WeakSet();
|
|
1610
|
+
voiceEventHandler_fn = /* @__PURE__ */ __name(function(queue) {
|
|
1611
|
+
queue._listeners = {
|
|
1612
|
+
disconnect: (error) => {
|
|
1613
|
+
queue.remove();
|
|
1614
|
+
this.emit("disconnect", queue);
|
|
1615
|
+
if (error)
|
|
1616
|
+
this.emitError(error, queue.textChannel);
|
|
1617
|
+
},
|
|
1618
|
+
error: (error) => __privateMethod(this, _handlePlayingError, handlePlayingError_fn).call(this, queue, error),
|
|
1619
|
+
finish: () => __privateMethod(this, _handleSongFinish, handleSongFinish_fn).call(this, queue)
|
|
1620
|
+
};
|
|
1621
|
+
for (const event of objectKeys(queue._listeners)) {
|
|
1622
|
+
queue.voice.on(event, queue._listeners[event]);
|
|
1659
1623
|
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1624
|
+
}, "#voiceEventHandler");
|
|
1625
|
+
_handleSongFinish = new WeakSet();
|
|
1626
|
+
handleSongFinish_fn = /* @__PURE__ */ __name(async function(queue) {
|
|
1627
|
+
this.emit("finishSong", queue, queue.songs[0]);
|
|
1628
|
+
await queue._taskQueue.queuing();
|
|
1629
|
+
try {
|
|
1630
|
+
if (queue.stopped)
|
|
1631
|
+
return;
|
|
1632
|
+
if (queue.repeatMode === 2 /* QUEUE */ && !queue._prev)
|
|
1633
|
+
queue.songs.push(queue.songs[0]);
|
|
1634
|
+
if (queue._prev) {
|
|
1635
|
+
if (queue.repeatMode === 2 /* QUEUE */)
|
|
1636
|
+
queue.songs.unshift(queue.songs.pop());
|
|
1637
|
+
else
|
|
1638
|
+
queue.songs.unshift(queue.previousSongs.pop());
|
|
1663
1639
|
}
|
|
1664
|
-
if (
|
|
1665
|
-
|
|
1640
|
+
if (queue.songs.length <= 1 && (queue._next || queue.repeatMode === 0 /* DISABLED */)) {
|
|
1641
|
+
if (queue.autoplay) {
|
|
1642
|
+
try {
|
|
1643
|
+
await queue.addRelatedSong();
|
|
1644
|
+
} catch {
|
|
1645
|
+
this.emit("noRelated", queue);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
if (queue.songs.length <= 1) {
|
|
1649
|
+
if (this.options.leaveOnFinish)
|
|
1650
|
+
queue.voice.leave();
|
|
1651
|
+
if (!queue.autoplay)
|
|
1652
|
+
this.emit("finish", queue);
|
|
1653
|
+
queue.remove();
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1666
1656
|
}
|
|
1667
|
-
|
|
1657
|
+
const emitPlaySong = __privateMethod(this, _emitPlaySong, emitPlaySong_fn).call(this, queue);
|
|
1658
|
+
if (!queue._prev && (queue.repeatMode !== 1 /* SONG */ || queue._next)) {
|
|
1659
|
+
const prev = queue.songs.shift();
|
|
1660
|
+
delete prev.formats;
|
|
1661
|
+
delete prev.streamURL;
|
|
1662
|
+
if (this.options.savePreviousSongs)
|
|
1663
|
+
queue.previousSongs.push(prev);
|
|
1664
|
+
else
|
|
1665
|
+
queue.previousSongs.push({ id: prev.id });
|
|
1666
|
+
}
|
|
1667
|
+
queue._next = queue._prev = false;
|
|
1668
|
+
queue.beginTime = 0;
|
|
1669
|
+
const err = await this.playSong(queue);
|
|
1670
|
+
if (!err && emitPlaySong)
|
|
1671
|
+
this.emit("playSong", queue, queue.songs[0]);
|
|
1672
|
+
} finally {
|
|
1673
|
+
queue._taskQueue.resolve();
|
|
1668
1674
|
}
|
|
1669
|
-
};
|
|
1670
|
-
|
|
1675
|
+
}, "#handleSongFinish");
|
|
1676
|
+
_handlePlayingError = new WeakSet();
|
|
1677
|
+
handlePlayingError_fn = /* @__PURE__ */ __name(function(queue, error) {
|
|
1678
|
+
const song = queue.songs.shift();
|
|
1679
|
+
try {
|
|
1680
|
+
error.name = "PlayingError";
|
|
1681
|
+
error.message = `${error.message}
|
|
1682
|
+
Id: ${song.id}
|
|
1683
|
+
Name: ${song.name}`;
|
|
1684
|
+
} catch {
|
|
1685
|
+
}
|
|
1686
|
+
this.emitError(error, queue.textChannel);
|
|
1687
|
+
if (queue.songs.length > 0) {
|
|
1688
|
+
queue._next = queue._prev = false;
|
|
1689
|
+
queue.beginTime = 0;
|
|
1690
|
+
this.playSong(queue).then((e) => {
|
|
1691
|
+
if (!e)
|
|
1692
|
+
this.emit("playSong", queue, queue.songs[0]);
|
|
1693
|
+
});
|
|
1694
|
+
} else {
|
|
1695
|
+
queue.stop();
|
|
1696
|
+
}
|
|
1697
|
+
}, "#handlePlayingError");
|
|
1698
|
+
_emitPlaySong = new WeakSet();
|
|
1699
|
+
emitPlaySong_fn = /* @__PURE__ */ __name(function(queue) {
|
|
1700
|
+
return !this.options.emitNewSongOnly || queue.repeatMode === 1 /* SONG */ && queue._next || queue.repeatMode !== 1 /* SONG */ && queue.songs[0]?.id !== queue.songs[1]?.id;
|
|
1701
|
+
}, "#emitPlaySong");
|
|
1671
1702
|
|
|
1672
1703
|
// src/struct/Queue.ts
|
|
1673
1704
|
var _filters;
|
|
@@ -2151,10 +2182,14 @@ var DirectLinkPlugin = class extends ExtractorPlugin {
|
|
|
2151
2182
|
}
|
|
2152
2183
|
async resolve(url, options = {}) {
|
|
2153
2184
|
url = url.replace(/\/+$/, "");
|
|
2154
|
-
return new Song(
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2185
|
+
return new Song(
|
|
2186
|
+
{
|
|
2187
|
+
name: url.substring(url.lastIndexOf("/") + 1).replace(/((\?|#).*)?$/, "") || url,
|
|
2188
|
+
url,
|
|
2189
|
+
src: "direct_link"
|
|
2190
|
+
},
|
|
2191
|
+
options
|
|
2192
|
+
);
|
|
2158
2193
|
}
|
|
2159
2194
|
};
|
|
2160
2195
|
__name(DirectLinkPlugin, "DirectLinkPlugin");
|
|
@@ -2268,7 +2303,9 @@ ${e.message}`;
|
|
|
2268
2303
|
throw new DisTubeError("INVALID_TYPE", "Array", songs, "songs");
|
|
2269
2304
|
if (!songs.length)
|
|
2270
2305
|
throw new DisTubeError("EMPTY_ARRAY", "songs");
|
|
2271
|
-
const filteredSongs = songs.filter(
|
|
2306
|
+
const filteredSongs = songs.filter(
|
|
2307
|
+
(song) => song instanceof Song || isURL(song) || typeof song !== "string" && song.type === "video" /* VIDEO */
|
|
2308
|
+
);
|
|
2272
2309
|
if (!filteredSongs.length)
|
|
2273
2310
|
throw new DisTubeError("NO_VALID_SONG");
|
|
2274
2311
|
if (member && !isMemberInstance(member)) {
|
|
@@ -2278,7 +2315,9 @@ ${e.message}`;
|
|
|
2278
2315
|
throw new DisTubeError("NO_VALID_SONG");
|
|
2279
2316
|
let resolvedSongs;
|
|
2280
2317
|
if (parallel) {
|
|
2281
|
-
const promises = filteredSongs.map(
|
|
2318
|
+
const promises = filteredSongs.map(
|
|
2319
|
+
(song) => this.handler.resolve(song, { member, metadata }).catch(() => void 0)
|
|
2320
|
+
);
|
|
2282
2321
|
resolvedSongs = (await Promise.all(promises)).filter((s) => !!s);
|
|
2283
2322
|
} else {
|
|
2284
2323
|
const resolved = [];
|
|
@@ -2400,7 +2439,9 @@ ${e.message}`;
|
|
|
2400
2439
|
} else {
|
|
2401
2440
|
console.error(error);
|
|
2402
2441
|
console.warn("Unhandled 'error' event.");
|
|
2403
|
-
console.warn(
|
|
2442
|
+
console.warn(
|
|
2443
|
+
"See: https://distube.js.org/#/docs/DisTube/stable/class/DisTube?scrollTo=e-error and https://nodejs.org/api/events.html#events_error_events"
|
|
2444
|
+
);
|
|
2404
2445
|
}
|
|
2405
2446
|
}
|
|
2406
2447
|
};
|