distube 4.2.0 → 4.2.1
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 +47 -21
- package/dist/index.js +98 -35
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
# DisTube
|
|
21
21
|
|
|
22
|
-
A Discord.js module
|
|
22
|
+
A powerful Discord.js module for simplifying music commands and effortless playback of various sources with integrated audio filters.
|
|
23
23
|
|
|
24
24
|
[DisTube Support Server](https://discord.gg/feaDd9h) - [Frequently Asked Questions](https://discord.gg/feaDd9h)
|
|
25
25
|
|
package/dist/index.d.ts
CHANGED
|
@@ -127,7 +127,7 @@ type DisTubeOptions = {
|
|
|
127
127
|
searchCooldown?: number;
|
|
128
128
|
/**
|
|
129
129
|
* YouTube cookies. Guide: {@link
|
|
130
|
-
* https://
|
|
130
|
+
* https://github.com/skick1234/DisTube/wiki/YouTube-Cookies | YouTube Cookies}
|
|
131
131
|
*/
|
|
132
132
|
youtubeCookie?: Cookie[] | string;
|
|
133
133
|
/**
|
|
@@ -167,12 +167,31 @@ type DisTubeOptions = {
|
|
|
167
167
|
directLink?: boolean;
|
|
168
168
|
/**
|
|
169
169
|
* FFmpeg path
|
|
170
|
+
* @deprecated
|
|
170
171
|
*/
|
|
171
172
|
ffmpegPath?: string;
|
|
172
173
|
/**
|
|
173
174
|
* FFmpeg default arguments
|
|
174
|
-
|
|
175
|
-
|
|
175
|
+
* @deprecated
|
|
176
|
+
*/
|
|
177
|
+
ffmpegDefaultArgs?: FFmpegArgs;
|
|
178
|
+
/**
|
|
179
|
+
* FFmpeg options
|
|
180
|
+
*/
|
|
181
|
+
ffmpeg?: {
|
|
182
|
+
/**
|
|
183
|
+
* FFmpeg path
|
|
184
|
+
*/
|
|
185
|
+
path?: string;
|
|
186
|
+
/**
|
|
187
|
+
* FFmpeg default arguments
|
|
188
|
+
*/
|
|
189
|
+
args?: {
|
|
190
|
+
global?: FFmpegArgs;
|
|
191
|
+
input?: FFmpegArgs;
|
|
192
|
+
output?: FFmpegArgs;
|
|
193
|
+
};
|
|
194
|
+
};
|
|
176
195
|
};
|
|
177
196
|
/**
|
|
178
197
|
* Data that can be resolved to give a guild id string. This can be:
|
|
@@ -364,7 +383,15 @@ declare enum Events {
|
|
|
364
383
|
SEARCH_RESULT = "searchResult",
|
|
365
384
|
FFMPEG_DEBUG = "ffmpegDebug"
|
|
366
385
|
}
|
|
367
|
-
type
|
|
386
|
+
type FFmpegArgs = Record<string, string | number | boolean | Array<string | null | undefined> | null | undefined>;
|
|
387
|
+
type FFmpegOptions = {
|
|
388
|
+
path: string;
|
|
389
|
+
args: {
|
|
390
|
+
global: FFmpegArgs;
|
|
391
|
+
input: FFmpegArgs;
|
|
392
|
+
output: FFmpegArgs;
|
|
393
|
+
};
|
|
394
|
+
};
|
|
368
395
|
|
|
369
396
|
/**
|
|
370
397
|
* Default DisTube audio filters.
|
|
@@ -387,11 +414,6 @@ declare const defaultOptions: {
|
|
|
387
414
|
joinNewVoiceChannel: true;
|
|
388
415
|
streamType: StreamType.OPUS;
|
|
389
416
|
directLink: true;
|
|
390
|
-
ffmpegPath: string;
|
|
391
|
-
ffmpegDefaultArgs: {
|
|
392
|
-
analyzeduration: number;
|
|
393
|
-
hide_banner: true;
|
|
394
|
-
};
|
|
395
417
|
};
|
|
396
418
|
|
|
397
419
|
declare const ERROR_MESSAGES: {
|
|
@@ -413,6 +435,8 @@ declare const ERROR_MESSAGES: {
|
|
|
413
435
|
VOICE_RECONNECT_FAILED: string;
|
|
414
436
|
VOICE_DIFFERENT_GUILD: string;
|
|
415
437
|
VOICE_DIFFERENT_CLIENT: string;
|
|
438
|
+
FFMPEG_EXITED: (code: number) => string;
|
|
439
|
+
FFMPEG_NOT_INSTALLED: (path: string) => string;
|
|
416
440
|
NO_QUEUE: string;
|
|
417
441
|
QUEUE_EXIST: string;
|
|
418
442
|
PAUSED: string;
|
|
@@ -759,19 +783,18 @@ declare class DisTubeVoice extends TypedEmitter<DisTubeVoiceEvents> {
|
|
|
759
783
|
}
|
|
760
784
|
|
|
761
785
|
interface StreamOptions {
|
|
762
|
-
ffmpeg:
|
|
763
|
-
path: string;
|
|
764
|
-
args: FFmpegOptions;
|
|
765
|
-
};
|
|
786
|
+
ffmpeg: FFmpegOptions;
|
|
766
787
|
seek?: number;
|
|
767
788
|
type?: StreamType;
|
|
768
789
|
}
|
|
769
790
|
declare const chooseBestVideoFormat: ({ duration, formats, isLive }: Song) => ytdl.videoFormat | undefined;
|
|
791
|
+
declare const checkFFmpeg: (distube: DisTube) => void;
|
|
770
792
|
/**
|
|
771
793
|
* Create a stream to play with {@link DisTubeVoice}
|
|
772
794
|
*/
|
|
773
795
|
declare class DisTubeStream extends TypedEmitter<{
|
|
774
796
|
debug: (debug: string) => Awaitable;
|
|
797
|
+
error: (error: Error) => Awaitable;
|
|
775
798
|
}> {
|
|
776
799
|
private killed;
|
|
777
800
|
process: ChildProcess;
|
|
@@ -899,8 +922,11 @@ declare class Options {
|
|
|
899
922
|
joinNewVoiceChannel: boolean;
|
|
900
923
|
streamType: StreamType;
|
|
901
924
|
directLink: boolean;
|
|
902
|
-
|
|
903
|
-
|
|
925
|
+
/** @deprecated */
|
|
926
|
+
ffmpegPath: undefined;
|
|
927
|
+
/** @deprecated */
|
|
928
|
+
ffmpegDefaultArgs: undefined;
|
|
929
|
+
ffmpeg: FFmpegOptions;
|
|
904
930
|
constructor(options: DisTubeOptions);
|
|
905
931
|
}
|
|
906
932
|
|
|
@@ -1011,7 +1037,7 @@ declare class FilterManager extends BaseManager<Filter> {
|
|
|
1011
1037
|
* Array of enabled filters
|
|
1012
1038
|
*/
|
|
1013
1039
|
get values(): Filter[];
|
|
1014
|
-
get ffmpegArgs():
|
|
1040
|
+
get ffmpegArgs(): FFmpegArgs;
|
|
1015
1041
|
toString(): string;
|
|
1016
1042
|
}
|
|
1017
1043
|
|
|
@@ -1616,9 +1642,9 @@ declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
|
|
|
1616
1642
|
readonly filters: Filters;
|
|
1617
1643
|
/**
|
|
1618
1644
|
* @deprecated Use `youtubeCookie: Cookie[]` instead. Guide: {@link
|
|
1619
|
-
* https://
|
|
1645
|
+
* https://github.com/skick1234/DisTube/wiki/YouTube-Cookies | YouTube Cookies}
|
|
1620
1646
|
*/
|
|
1621
|
-
constructor(client: Client,
|
|
1647
|
+
constructor(client: Client, opts: DisTubeOptions & {
|
|
1622
1648
|
youtubeCookie: string;
|
|
1623
1649
|
});
|
|
1624
1650
|
/**
|
|
@@ -1638,9 +1664,9 @@ declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
|
|
|
1638
1664
|
* @throws {@link DisTubeError}
|
|
1639
1665
|
*
|
|
1640
1666
|
* @param client - Discord.JS client
|
|
1641
|
-
* @param
|
|
1667
|
+
* @param opts - Custom DisTube options
|
|
1642
1668
|
*/
|
|
1643
|
-
constructor(client: Client,
|
|
1669
|
+
constructor(client: Client, opts?: DisTubeOptions);
|
|
1644
1670
|
static get version(): string;
|
|
1645
1671
|
/**
|
|
1646
1672
|
* DisTube version
|
|
@@ -1965,4 +1991,4 @@ declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
|
|
|
1965
1991
|
emitError(error: Error, channel?: GuildTextBasedChannel): void;
|
|
1966
1992
|
}
|
|
1967
1993
|
|
|
1968
|
-
export { type Awaitable, BaseManager, type Chapter, type CustomPlaylistOptions, CustomPlugin, DirectLinkPlugin, DisTube, DisTubeBase, DisTubeError, type DisTubeEvents, DisTubeHandler, type DisTubeOptions, DisTubeStream, DisTubeVoice, type DisTubeVoiceEvents, DisTubeVoiceManager, Events, ExtractorPlugin, type FFmpegOptions, type Filter, FilterManager, type FilterResolvable, type Filters, GuildIdManager, type GuildIdResolvable, Options, type OtherSongInfo, type PlayHandlerOptions, type PlayOptions, Playlist, type PlaylistInfo, Plugin, PluginType, Queue, QueueManager, type RelatedSong, RepeatMode, type ResolveOptions, type ResolvePlaylistOptions, type SearchResult, SearchResultPlaylist, SearchResultType, SearchResultVideo, Song, StreamType, TaskQueue, type TypedDisTubeEvents, checkIntents, checkInvalidKey, chooseBestVideoFormat, DisTube as default, defaultFilters, defaultOptions, formatDuration, isClientInstance, isGuildInstance, isMemberInstance, isMessageInstance, isNsfwChannel, isObject, isRecord, isSnowflake, isSupportedVoiceChannel, isTextChannelInstance, isTruthy, isURL, isVoiceChannelEmpty, objectKeys, parseNumber, resolveGuildId, toSecond, version };
|
|
1994
|
+
export { type Awaitable, BaseManager, type Chapter, type CustomPlaylistOptions, CustomPlugin, DirectLinkPlugin, DisTube, DisTubeBase, DisTubeError, type DisTubeEvents, DisTubeHandler, type DisTubeOptions, DisTubeStream, DisTubeVoice, type DisTubeVoiceEvents, DisTubeVoiceManager, Events, ExtractorPlugin, type FFmpegArgs, type FFmpegOptions, type Filter, FilterManager, type FilterResolvable, type Filters, GuildIdManager, type GuildIdResolvable, Options, type OtherSongInfo, type PlayHandlerOptions, type PlayOptions, Playlist, type PlaylistInfo, Plugin, PluginType, Queue, QueueManager, type RelatedSong, RepeatMode, type ResolveOptions, type ResolvePlaylistOptions, type SearchResult, SearchResultPlaylist, SearchResultType, SearchResultVideo, Song, StreamType, TaskQueue, type TypedDisTubeEvents, checkFFmpeg, checkIntents, checkInvalidKey, chooseBestVideoFormat, DisTube as default, defaultFilters, defaultOptions, formatDuration, isClientInstance, isGuildInstance, isMemberInstance, isMessageInstance, isNsfwChannel, isObject, isRecord, isSnowflake, isSupportedVoiceChannel, isTextChannelInstance, isTruthy, isURL, isVoiceChannelEmpty, objectKeys, parseNumber, resolveGuildId, toSecond, version };
|
package/dist/index.js
CHANGED
|
@@ -63,7 +63,7 @@ var require_package = __commonJS({
|
|
|
63
63
|
"package.json"(exports2, module2) {
|
|
64
64
|
module2.exports = {
|
|
65
65
|
name: "distube",
|
|
66
|
-
version: "4.2.
|
|
66
|
+
version: "4.2.1",
|
|
67
67
|
description: "A Discord.js module to simplify your music commands and play songs with audio filters on Discord without any API key.",
|
|
68
68
|
main: "./dist/index.js",
|
|
69
69
|
types: "./dist/index.d.ts",
|
|
@@ -202,6 +202,7 @@ __export(src_exports, {
|
|
|
202
202
|
Song: () => Song,
|
|
203
203
|
StreamType: () => StreamType,
|
|
204
204
|
TaskQueue: () => TaskQueue,
|
|
205
|
+
checkFFmpeg: () => checkFFmpeg,
|
|
205
206
|
checkIntents: () => checkIntents,
|
|
206
207
|
checkInvalidKey: () => checkInvalidKey,
|
|
207
208
|
chooseBestVideoFormat: () => chooseBestVideoFormat,
|
|
@@ -307,12 +308,7 @@ var defaultOptions = {
|
|
|
307
308
|
emitAddListWhenCreatingQueue: true,
|
|
308
309
|
joinNewVoiceChannel: true,
|
|
309
310
|
streamType: 0 /* OPUS */,
|
|
310
|
-
directLink: true
|
|
311
|
-
ffmpegPath: "ffmpeg",
|
|
312
|
-
ffmpegDefaultArgs: {
|
|
313
|
-
analyzeduration: 0,
|
|
314
|
-
hide_banner: true
|
|
315
|
-
}
|
|
311
|
+
directLink: true
|
|
316
312
|
};
|
|
317
313
|
|
|
318
314
|
// src/struct/DisTubeError.ts
|
|
@@ -336,6 +332,8 @@ var ERROR_MESSAGES = {
|
|
|
336
332
|
VOICE_RECONNECT_FAILED: "Cannot reconnect to the voice channel",
|
|
337
333
|
VOICE_DIFFERENT_GUILD: "Cannot join a voice channel in a different guild",
|
|
338
334
|
VOICE_DIFFERENT_CLIENT: "Cannot join a voice channel created by a different client",
|
|
335
|
+
FFMPEG_EXITED: (code) => `ffmpeg exited with code ${code}`,
|
|
336
|
+
FFMPEG_NOT_INSTALLED: (path) => `ffmpeg is not installed at '${path}' path`,
|
|
339
337
|
NO_QUEUE: "There is no playing queue in this guild",
|
|
340
338
|
QUEUE_EXIST: "This guild has a Queue already",
|
|
341
339
|
PAUSED: "The queue has been paused already",
|
|
@@ -962,7 +960,7 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
962
960
|
*/
|
|
963
961
|
play(dtStream) {
|
|
964
962
|
this.emittedError = false;
|
|
965
|
-
dtStream.
|
|
963
|
+
dtStream.on("error", (error) => {
|
|
966
964
|
if (this.emittedError || error.code === "ERR_STREAM_PREMATURE_CLOSE")
|
|
967
965
|
return;
|
|
968
966
|
this.emittedError = true;
|
|
@@ -1080,11 +1078,41 @@ __name(_DisTubeVoice, "DisTubeVoice");
|
|
|
1080
1078
|
var DisTubeVoice = _DisTubeVoice;
|
|
1081
1079
|
|
|
1082
1080
|
// src/core/DisTubeStream.ts
|
|
1083
|
-
var import_child_process = require("child_process");
|
|
1084
1081
|
var import_node_stream = require("stream");
|
|
1082
|
+
var import_child_process = require("child_process");
|
|
1085
1083
|
var import_tiny_typed_emitter2 = require("tiny-typed-emitter");
|
|
1086
1084
|
var import_voice2 = require("@discordjs/voice");
|
|
1087
1085
|
var chooseBestVideoFormat = /* @__PURE__ */ __name(({ duration, formats, isLive }) => formats && formats.filter((f) => f.hasAudio && (duration < 10 * 60 || f.hasVideo) && (!isLive || f.isHLS)).sort((a, b) => Number(b.audioBitrate) - Number(a.audioBitrate) || Number(a.bitrate) - Number(b.bitrate))[0], "chooseBestVideoFormat");
|
|
1086
|
+
var checked = process.env.NODE_ENV === "test";
|
|
1087
|
+
var checkFFmpeg = /* @__PURE__ */ __name((distube) => {
|
|
1088
|
+
if (checked)
|
|
1089
|
+
return;
|
|
1090
|
+
const path = distube.options.ffmpeg.path;
|
|
1091
|
+
const debug = /* @__PURE__ */ __name((str) => distube.emit("ffmpegDebug" /* FFMPEG_DEBUG */, str), "debug");
|
|
1092
|
+
try {
|
|
1093
|
+
debug(`[test] spawn ffmpeg at '${path}' path`);
|
|
1094
|
+
const process2 = (0, import_child_process.spawnSync)(path, ["-h"], { windowsHide: true, shell: true, encoding: "utf-8" });
|
|
1095
|
+
if (process2.error)
|
|
1096
|
+
throw process2.error;
|
|
1097
|
+
if (process2.stderr && !process2.stdout)
|
|
1098
|
+
throw new Error(process2.stderr);
|
|
1099
|
+
const result = process2.output.join("\n");
|
|
1100
|
+
const version2 = /ffmpeg version (\S+)/iu.exec(result)?.[1];
|
|
1101
|
+
if (!version2)
|
|
1102
|
+
throw new Error("Invalid FFmpeg version");
|
|
1103
|
+
debug(`[test] ffmpeg version: ${version2}`);
|
|
1104
|
+
if (result.includes("--enable-libopus")) {
|
|
1105
|
+
debug("[test] ffmpeg supports libopus");
|
|
1106
|
+
} else {
|
|
1107
|
+
debug("[test] ffmpeg does not support libopus");
|
|
1108
|
+
distube.options.streamType = 1 /* RAW */;
|
|
1109
|
+
}
|
|
1110
|
+
} catch (e) {
|
|
1111
|
+
debug(`[test] failed to spawn ffmpeg at '${path}': ${e?.stack ?? e}`);
|
|
1112
|
+
throw new DisTubeError("FFMPEG_NOT_INSTALLED", path);
|
|
1113
|
+
}
|
|
1114
|
+
checked = true;
|
|
1115
|
+
}, "checkFFmpeg");
|
|
1088
1116
|
var _DisTubeStream = class _DisTubeStream extends import_tiny_typed_emitter2.TypedEmitter {
|
|
1089
1117
|
/**
|
|
1090
1118
|
* Create a DisTubeStream to play with {@link DisTubeVoice}
|
|
@@ -1103,13 +1131,16 @@ var _DisTubeStream = class _DisTubeStream extends import_tiny_typed_emitter2.Typ
|
|
|
1103
1131
|
this.type = !type ? import_voice2.StreamType.OggOpus : import_voice2.StreamType.Raw;
|
|
1104
1132
|
const opts = {
|
|
1105
1133
|
reconnect: 1,
|
|
1106
|
-
reconnect_on_network_error: 1,
|
|
1107
1134
|
reconnect_streamed: 1,
|
|
1108
1135
|
reconnect_delay_max: 5,
|
|
1136
|
+
analyzeduration: 0,
|
|
1137
|
+
hide_banner: true,
|
|
1138
|
+
...ffmpeg.args.global,
|
|
1139
|
+
...ffmpeg.args.input,
|
|
1109
1140
|
i: url,
|
|
1110
1141
|
ar: 48e3,
|
|
1111
1142
|
ac: 2,
|
|
1112
|
-
...ffmpeg.args
|
|
1143
|
+
...ffmpeg.args.output
|
|
1113
1144
|
};
|
|
1114
1145
|
if (!type) {
|
|
1115
1146
|
opts.f = "opus";
|
|
@@ -1129,19 +1160,26 @@ var _DisTubeStream = class _DisTubeStream extends import_tiny_typed_emitter2.Typ
|
|
|
1129
1160
|
).flat(),
|
|
1130
1161
|
"pipe:1"
|
|
1131
1162
|
],
|
|
1132
|
-
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
1133
|
-
).on("error", (err) =>
|
|
1163
|
+
{ stdio: ["ignore", "pipe", "pipe"], shell: false, windowsHide: true }
|
|
1164
|
+
).on("error", (err) => {
|
|
1165
|
+
this.debug(`[process] error: ${err.message}`);
|
|
1166
|
+
this.emit("error", err);
|
|
1167
|
+
}).on("exit", (code, signal) => {
|
|
1134
1168
|
this.debug(`[process] exit: code=${code ?? "unknown"} signal=${signal ?? "unknown"}`);
|
|
1135
1169
|
if (!code || [0, 255].includes(code))
|
|
1136
1170
|
return;
|
|
1137
1171
|
this.debug(`[process] error: ffmpeg exited with code ${code}`);
|
|
1172
|
+
this.emit("error", new DisTubeError("FFMPEG_EXITED", code));
|
|
1138
1173
|
});
|
|
1139
1174
|
if (!this.process.stdout || !this.process.stderr) {
|
|
1140
1175
|
this.kill();
|
|
1141
1176
|
throw new Error("Failed to create ffmpeg process");
|
|
1142
1177
|
}
|
|
1143
1178
|
this.stream = new import_node_stream.PassThrough();
|
|
1144
|
-
this.stream.on("close", () => this.kill()).on("error", (err) =>
|
|
1179
|
+
this.stream.on("close", () => this.kill()).on("error", (err) => {
|
|
1180
|
+
this.debug(`[stream] error: ${err.message}`);
|
|
1181
|
+
this.emit("error", err);
|
|
1182
|
+
}).on("finish", () => this.debug("[stream] log: stream finished"));
|
|
1145
1183
|
this.process.stdout.pipe(this.stream);
|
|
1146
1184
|
this.process.stderr.setEncoding("utf8")?.on("data", (data) => {
|
|
1147
1185
|
const lines = data.split(/\r\n|\r|\n/u);
|
|
@@ -1247,7 +1285,7 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1247
1285
|
const cookies = __privateSet(this, _cookie, this.options.youtubeCookie);
|
|
1248
1286
|
if (typeof cookies === "string") {
|
|
1249
1287
|
console.warn(
|
|
1250
|
-
"\x1B[33mWARNING:\x1B[0m You are using the old YouTube cookie format, please use the new one instead. (https://
|
|
1288
|
+
"\x1B[33mWARNING:\x1B[0m You are using the old YouTube cookie format, please use the new one instead. (https://github.com/skick1234/DisTube/wiki/YouTube-Cookies)"
|
|
1251
1289
|
);
|
|
1252
1290
|
options.agent = import_ytdl_core.default.createAgent(
|
|
1253
1291
|
cookies.split(";").map((c) => import_tough_cookie.Cookie.parse(c)).filter(isTruthy)
|
|
@@ -1544,10 +1582,11 @@ __name(_DisTubeHandler, "DisTubeHandler");
|
|
|
1544
1582
|
var DisTubeHandler = _DisTubeHandler;
|
|
1545
1583
|
|
|
1546
1584
|
// src/core/DisTubeOptions.ts
|
|
1547
|
-
var _validateOptions, validateOptions_fn;
|
|
1585
|
+
var _validateOptions, validateOptions_fn, _ffmpegOption, ffmpegOption_fn;
|
|
1548
1586
|
var _Options = class _Options {
|
|
1549
1587
|
constructor(options) {
|
|
1550
1588
|
__privateAdd(this, _validateOptions);
|
|
1589
|
+
__privateAdd(this, _ffmpegOption);
|
|
1551
1590
|
__publicField(this, "plugins");
|
|
1552
1591
|
__publicField(this, "emitNewSongOnly");
|
|
1553
1592
|
__publicField(this, "leaveOnFinish");
|
|
@@ -1566,8 +1605,11 @@ var _Options = class _Options {
|
|
|
1566
1605
|
__publicField(this, "joinNewVoiceChannel");
|
|
1567
1606
|
__publicField(this, "streamType");
|
|
1568
1607
|
__publicField(this, "directLink");
|
|
1608
|
+
/** @deprecated */
|
|
1569
1609
|
__publicField(this, "ffmpegPath");
|
|
1610
|
+
/** @deprecated */
|
|
1570
1611
|
__publicField(this, "ffmpegDefaultArgs");
|
|
1612
|
+
__publicField(this, "ffmpeg");
|
|
1571
1613
|
if (typeof options !== "object" || Array.isArray(options)) {
|
|
1572
1614
|
throw new DisTubeError("INVALID_TYPE", "object", options, "DisTubeOptions");
|
|
1573
1615
|
}
|
|
@@ -1590,8 +1632,7 @@ var _Options = class _Options {
|
|
|
1590
1632
|
this.joinNewVoiceChannel = opts.joinNewVoiceChannel;
|
|
1591
1633
|
this.streamType = opts.streamType;
|
|
1592
1634
|
this.directLink = opts.directLink;
|
|
1593
|
-
this.
|
|
1594
|
-
this.ffmpegDefaultArgs = opts.ffmpegDefaultArgs;
|
|
1635
|
+
this.ffmpeg = __privateMethod(this, _ffmpegOption, ffmpegOption_fn).call(this, options);
|
|
1595
1636
|
checkInvalidKey(opts, this, "DisTubeOptions");
|
|
1596
1637
|
__privateMethod(this, _validateOptions, validateOptions_fn).call(this);
|
|
1597
1638
|
}
|
|
@@ -1611,8 +1652,8 @@ validateOptions_fn = /* @__PURE__ */ __name(function(options = this) {
|
|
|
1611
1652
|
"directLink"
|
|
1612
1653
|
]);
|
|
1613
1654
|
const numberOptions = /* @__PURE__ */ new Set(["searchCooldown", "emptyCooldown", "searchSongs"]);
|
|
1614
|
-
const stringOptions = /* @__PURE__ */ new Set(
|
|
1615
|
-
const objectOptions = /* @__PURE__ */ new Set(["customFilters", "ytdlOptions", "
|
|
1655
|
+
const stringOptions = /* @__PURE__ */ new Set();
|
|
1656
|
+
const objectOptions = /* @__PURE__ */ new Set(["customFilters", "ytdlOptions", "ffmpeg"]);
|
|
1616
1657
|
const optionalOptions = /* @__PURE__ */ new Set(["youtubeCookie", "customFilters"]);
|
|
1617
1658
|
for (const [key, value] of Object.entries(options)) {
|
|
1618
1659
|
if (value === void 0 && optionalOptions.has(key))
|
|
@@ -1642,6 +1683,29 @@ validateOptions_fn = /* @__PURE__ */ __name(function(options = this) {
|
|
|
1642
1683
|
}
|
|
1643
1684
|
}
|
|
1644
1685
|
}, "#validateOptions");
|
|
1686
|
+
_ffmpegOption = new WeakSet();
|
|
1687
|
+
ffmpegOption_fn = /* @__PURE__ */ __name(function(opts) {
|
|
1688
|
+
let path;
|
|
1689
|
+
const args = { global: {}, input: {}, output: {} };
|
|
1690
|
+
if (opts.ffmpegPath) {
|
|
1691
|
+
console.warn("`DisTubeOptions.ffmpegPath` is deprecated. Use `ffmpeg.path` instead.");
|
|
1692
|
+
path = opts.ffmpegPath;
|
|
1693
|
+
}
|
|
1694
|
+
if (opts.ffmpegDefaultArgs) {
|
|
1695
|
+
console.warn("`DisTubeOptions.ffmpegDefaultArgs` is deprecated. Use `ffmpeg.args` instead.");
|
|
1696
|
+
args.global = opts.ffmpegDefaultArgs;
|
|
1697
|
+
}
|
|
1698
|
+
path ??= opts.ffmpeg?.path ?? `ffmpeg${process.platform === "win32" ? ".exe" : ""}`;
|
|
1699
|
+
if (opts.ffmpeg?.args) {
|
|
1700
|
+
if (opts.ffmpeg.args.global)
|
|
1701
|
+
args.global = opts.ffmpeg.args.global;
|
|
1702
|
+
if (opts.ffmpeg.args.input)
|
|
1703
|
+
args.input = opts.ffmpeg.args.input;
|
|
1704
|
+
if (opts.ffmpeg.args.output)
|
|
1705
|
+
args.output = opts.ffmpeg.args.output;
|
|
1706
|
+
}
|
|
1707
|
+
return { path, args };
|
|
1708
|
+
}, "#ffmpegOption");
|
|
1645
1709
|
__name(_Options, "Options");
|
|
1646
1710
|
var Options = _Options;
|
|
1647
1711
|
|
|
@@ -1920,6 +1984,7 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1920
1984
|
const queue = new Queue(this.distube, voice, song, textChannel);
|
|
1921
1985
|
await queue._taskQueue.queuing();
|
|
1922
1986
|
try {
|
|
1987
|
+
checkFFmpeg(this.distube);
|
|
1923
1988
|
await voice.join();
|
|
1924
1989
|
__privateMethod(this, _voiceEventHandler, voiceEventHandler_fn).call(this, queue);
|
|
1925
1990
|
this.add(queue.id, queue);
|
|
@@ -1940,10 +2005,11 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1940
2005
|
const { duration, source, streamURL } = song;
|
|
1941
2006
|
const streamOptions = {
|
|
1942
2007
|
ffmpeg: {
|
|
1943
|
-
path: this.options.
|
|
2008
|
+
path: this.options.ffmpeg.path,
|
|
1944
2009
|
args: {
|
|
1945
|
-
...this.options.
|
|
1946
|
-
...
|
|
2010
|
+
global: { ...this.options.ffmpeg.args.global },
|
|
2011
|
+
input: { ...this.options.ffmpeg.args.input },
|
|
2012
|
+
output: { ...this.options.ffmpeg.args.output, ...queue.filters.ffmpegArgs }
|
|
1947
2013
|
}
|
|
1948
2014
|
},
|
|
1949
2015
|
seek: duration ? queue.beginTime : void 0,
|
|
@@ -1951,6 +2017,8 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1951
2017
|
};
|
|
1952
2018
|
if (source === "youtube")
|
|
1953
2019
|
return DisTubeStream.YouTube(song, streamOptions);
|
|
2020
|
+
if (!streamURL)
|
|
2021
|
+
throw new Error("No streamURL, something went wrong");
|
|
1954
2022
|
return DisTubeStream.DirectLink(streamURL, streamOptions);
|
|
1955
2023
|
}
|
|
1956
2024
|
/**
|
|
@@ -2737,15 +2805,9 @@ var _DirectLinkPlugin = class _DirectLinkPlugin extends ExtractorPlugin {
|
|
|
2737
2805
|
return false;
|
|
2738
2806
|
}
|
|
2739
2807
|
resolve(url, options = {}) {
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
name: url.substring(url.lastIndexOf("/") + 1).replace(/((\?|#).*)?$/, "") || url,
|
|
2744
|
-
url,
|
|
2745
|
-
src: "direct_link"
|
|
2746
|
-
},
|
|
2747
|
-
options
|
|
2748
|
-
);
|
|
2808
|
+
const u = new URL(url);
|
|
2809
|
+
const name = u.pathname.split("/").pop() || u.href;
|
|
2810
|
+
return new Song({ name, url, src: "direct_link" }, options);
|
|
2749
2811
|
}
|
|
2750
2812
|
};
|
|
2751
2813
|
__name(_DirectLinkPlugin, "DirectLinkPlugin");
|
|
@@ -2757,7 +2819,7 @@ var import_tiny_typed_emitter3 = require("tiny-typed-emitter");
|
|
|
2757
2819
|
var { version } = require_package();
|
|
2758
2820
|
var _getQueue, getQueue_fn;
|
|
2759
2821
|
var _DisTube = class _DisTube extends import_tiny_typed_emitter3.TypedEmitter {
|
|
2760
|
-
constructor(client,
|
|
2822
|
+
constructor(client, opts = {}) {
|
|
2761
2823
|
super();
|
|
2762
2824
|
__privateAdd(this, _getQueue);
|
|
2763
2825
|
__publicField(this, "handler");
|
|
@@ -2773,7 +2835,7 @@ var _DisTube = class _DisTube extends import_tiny_typed_emitter3.TypedEmitter {
|
|
|
2773
2835
|
throw new DisTubeError("INVALID_TYPE", "Discord.Client", client, "client");
|
|
2774
2836
|
this.client = client;
|
|
2775
2837
|
checkIntents(client.options);
|
|
2776
|
-
this.options = new Options(
|
|
2838
|
+
this.options = new Options(opts);
|
|
2777
2839
|
this.voices = new DisTubeVoiceManager(this);
|
|
2778
2840
|
this.handler = new DisTubeHandler(this);
|
|
2779
2841
|
this.queues = new QueueManager(this);
|
|
@@ -3261,7 +3323,7 @@ ${e.message}`;
|
|
|
3261
3323
|
console.error(error);
|
|
3262
3324
|
console.warn("Unhandled 'error' event.");
|
|
3263
3325
|
console.warn(
|
|
3264
|
-
"See: https://distube.js.org
|
|
3326
|
+
"See: https://distube.js.org/classes/DisTube.html#error and https://nodejs.org/api/events.html#events_error_events"
|
|
3265
3327
|
);
|
|
3266
3328
|
}
|
|
3267
3329
|
}
|
|
@@ -3304,6 +3366,7 @@ var DisTube = _DisTube;
|
|
|
3304
3366
|
Song,
|
|
3305
3367
|
StreamType,
|
|
3306
3368
|
TaskQueue,
|
|
3369
|
+
checkFFmpeg,
|
|
3307
3370
|
checkIntents,
|
|
3308
3371
|
checkInvalidKey,
|
|
3309
3372
|
chooseBestVideoFormat,
|