distube 4.1.1 → 4.2.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/README.md +18 -28
- package/dist/index.d.ts +776 -508
- package/dist/index.js +493 -453
- package/dist/index.js.map +1 -1
- package/package.json +40 -64
package/dist/index.js
CHANGED
|
@@ -60,10 +60,10 @@ var __privateMethod = (obj, member, method) => {
|
|
|
60
60
|
|
|
61
61
|
// package.json
|
|
62
62
|
var require_package = __commonJS({
|
|
63
|
-
"package.json"(
|
|
63
|
+
"package.json"(exports2, module2) {
|
|
64
64
|
module2.exports = {
|
|
65
65
|
name: "distube",
|
|
66
|
-
version: "4.
|
|
66
|
+
version: "4.2.0",
|
|
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",
|
|
@@ -77,16 +77,16 @@ var require_package = __commonJS({
|
|
|
77
77
|
],
|
|
78
78
|
scripts: {
|
|
79
79
|
test: "jest",
|
|
80
|
-
docs: "
|
|
80
|
+
docs: "typedoc",
|
|
81
81
|
lint: "prettier --check . && eslint .",
|
|
82
82
|
"lint:fix": "eslint . --fix",
|
|
83
83
|
prettier: 'prettier --write "**/*.{ts,json,yml,yaml,md}"',
|
|
84
84
|
build: "tsup",
|
|
85
85
|
"build:check": "tsc --noEmit",
|
|
86
|
-
update: "
|
|
87
|
-
postinstall: "husky
|
|
88
|
-
prepublishOnly: "
|
|
89
|
-
prepack: "
|
|
86
|
+
update: "pnpm up -L",
|
|
87
|
+
postinstall: "husky",
|
|
88
|
+
prepublishOnly: "pnpm run lint && pnpm run test",
|
|
89
|
+
prepack: "pnpm run build && pinst --disable",
|
|
90
90
|
postpack: "pinst --enable",
|
|
91
91
|
"dev:add-docs-to-worktree": "git worktree add --track -b docs docs origin/docs"
|
|
92
92
|
},
|
|
@@ -112,70 +112,50 @@ var require_package = __commonJS({
|
|
|
112
112
|
bugs: {
|
|
113
113
|
url: "https://github.com/skick1234/DisTube/issues"
|
|
114
114
|
},
|
|
115
|
-
funding:
|
|
116
|
-
{
|
|
117
|
-
type: "individual",
|
|
118
|
-
url: "https://paypal.me/Skickkk"
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
type: "patreon",
|
|
122
|
-
url: "https://patreon.com/DisTube"
|
|
123
|
-
}
|
|
124
|
-
],
|
|
115
|
+
funding: "https://github.com/skick1234/DisTube?sponsor=1",
|
|
125
116
|
homepage: "https://distube.js.org/",
|
|
126
117
|
dependencies: {
|
|
127
|
-
"@distube/ytdl-core": "^4.13.
|
|
118
|
+
"@distube/ytdl-core": "^4.13.3",
|
|
128
119
|
"@distube/ytpl": "^1.2.1",
|
|
129
|
-
"@distube/ytsr": "^
|
|
130
|
-
"prism-media": "npm:@distube/prism-media@latest",
|
|
120
|
+
"@distube/ytsr": "^2.0.0",
|
|
131
121
|
"tiny-typed-emitter": "^2.1.0",
|
|
132
122
|
"tough-cookie": "^4.1.3",
|
|
133
123
|
tslib: "^2.6.2",
|
|
134
|
-
undici: "^
|
|
124
|
+
undici: "^6.13.0"
|
|
135
125
|
},
|
|
136
126
|
devDependencies: {
|
|
137
|
-
"@babel/core": "^7.
|
|
138
|
-
"@babel/plugin-
|
|
139
|
-
"@babel/plugin-
|
|
140
|
-
"@babel/plugin-transform-private-methods": "^7.
|
|
141
|
-
"@babel/preset-env": "^7.
|
|
142
|
-
"@babel/preset-typescript": "^7.
|
|
143
|
-
"@commitlint/cli": "^
|
|
144
|
-
"@commitlint/config-conventional": "^
|
|
145
|
-
"@discordjs/voice": "^0.16.
|
|
146
|
-
"@
|
|
147
|
-
"@types/
|
|
148
|
-
"@types/node": "^20.9.0",
|
|
127
|
+
"@babel/core": "^7.24.4",
|
|
128
|
+
"@babel/plugin-transform-class-properties": "^7.24.1",
|
|
129
|
+
"@babel/plugin-transform-object-rest-spread": "^7.24.1",
|
|
130
|
+
"@babel/plugin-transform-private-methods": "^7.24.1",
|
|
131
|
+
"@babel/preset-env": "^7.24.4",
|
|
132
|
+
"@babel/preset-typescript": "^7.24.1",
|
|
133
|
+
"@commitlint/cli": "^19.2.2",
|
|
134
|
+
"@commitlint/config-conventional": "^19.2.2",
|
|
135
|
+
"@discordjs/voice": "^0.16.1",
|
|
136
|
+
"@types/jest": "^29.5.12",
|
|
137
|
+
"@types/node": "^20.12.7",
|
|
149
138
|
"@types/tough-cookie": "^4.0.5",
|
|
150
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
151
|
-
"@typescript-eslint/parser": "^
|
|
139
|
+
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
|
140
|
+
"@typescript-eslint/parser": "^7.7.0",
|
|
152
141
|
"babel-jest": "^29.7.0",
|
|
153
|
-
"discord.js": "^14.
|
|
154
|
-
eslint: "^8.
|
|
155
|
-
"eslint-config-distube": "^1.
|
|
156
|
-
|
|
157
|
-
"eslint-plugin-deprecation": "^2.0.0",
|
|
158
|
-
"eslint-plugin-jsdoc": "^46.8.2",
|
|
159
|
-
husky: "^8.0.3",
|
|
142
|
+
"discord.js": "^14.14.1",
|
|
143
|
+
eslint: "^8.57.0",
|
|
144
|
+
"eslint-config-distube": "^1.7.0",
|
|
145
|
+
husky: "^9.0.11",
|
|
160
146
|
jest: "^29.7.0",
|
|
161
|
-
"jsdoc-babel": "^0.5.0",
|
|
162
147
|
"nano-staged": "^0.8.0",
|
|
163
|
-
"npm-check-updates": "^16.14.6",
|
|
164
148
|
pinst: "^3.0.0",
|
|
165
|
-
prettier: "^3.
|
|
166
|
-
tsup: "^
|
|
167
|
-
|
|
149
|
+
prettier: "^3.2.5",
|
|
150
|
+
tsup: "^8.0.2",
|
|
151
|
+
typedoc: "^0.25.13",
|
|
152
|
+
"typedoc-material-theme": "^1.0.2",
|
|
153
|
+
typescript: "^5.4.5"
|
|
168
154
|
},
|
|
169
155
|
peerDependencies: {
|
|
170
|
-
"@discordjs/opus": "*",
|
|
171
156
|
"@discordjs/voice": "*",
|
|
172
157
|
"discord.js": "14"
|
|
173
158
|
},
|
|
174
|
-
peerDependenciesMeta: {
|
|
175
|
-
"@discordjs/opus": {
|
|
176
|
-
optional: true
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
159
|
"nano-staged": {
|
|
180
160
|
"*.ts": [
|
|
181
161
|
"prettier --write",
|
|
@@ -186,9 +166,8 @@ var require_package = __commonJS({
|
|
|
186
166
|
]
|
|
187
167
|
},
|
|
188
168
|
engines: {
|
|
189
|
-
node: ">=
|
|
190
|
-
}
|
|
191
|
-
packageManager: "yarn@3.6.1"
|
|
169
|
+
node: ">=18.17"
|
|
170
|
+
}
|
|
192
171
|
};
|
|
193
172
|
}
|
|
194
173
|
});
|
|
@@ -290,6 +269,7 @@ var Events = /* @__PURE__ */ ((Events2) => {
|
|
|
290
269
|
Events2["SEARCH_DONE"] = "searchDone";
|
|
291
270
|
Events2["SEARCH_INVALID_ANSWER"] = "searchInvalidAnswer";
|
|
292
271
|
Events2["SEARCH_RESULT"] = "searchResult";
|
|
272
|
+
Events2["FFMPEG_DEBUG"] = "ffmpegDebug";
|
|
293
273
|
return Events2;
|
|
294
274
|
})(Events || {});
|
|
295
275
|
|
|
@@ -327,7 +307,12 @@ var defaultOptions = {
|
|
|
327
307
|
emitAddListWhenCreatingQueue: true,
|
|
328
308
|
joinNewVoiceChannel: true,
|
|
329
309
|
streamType: 0 /* OPUS */,
|
|
330
|
-
directLink: true
|
|
310
|
+
directLink: true,
|
|
311
|
+
ffmpegPath: "ffmpeg",
|
|
312
|
+
ffmpegDefaultArgs: {
|
|
313
|
+
analyzeduration: 0,
|
|
314
|
+
hide_banner: true
|
|
315
|
+
}
|
|
331
316
|
};
|
|
332
317
|
|
|
333
318
|
// src/struct/DisTubeError.ts
|
|
@@ -411,15 +396,13 @@ var _TaskQueue = class _TaskQueue {
|
|
|
411
396
|
constructor() {
|
|
412
397
|
/**
|
|
413
398
|
* The task array
|
|
414
|
-
* @type {Task[]}
|
|
415
|
-
* @private
|
|
416
399
|
*/
|
|
417
400
|
__privateAdd(this, _tasks, []);
|
|
418
401
|
}
|
|
419
402
|
/**
|
|
420
403
|
* Waits for last task finished and queues a new task
|
|
421
|
-
*
|
|
422
|
-
* @
|
|
404
|
+
*
|
|
405
|
+
* @param resolveInfo - Whether the task is a resolving info task
|
|
423
406
|
*/
|
|
424
407
|
queuing(resolveInfo = false) {
|
|
425
408
|
const next = this.remaining ? __privateGet(this, _tasks)[__privateGet(this, _tasks).length - 1].promise : Promise.resolve();
|
|
@@ -434,14 +417,12 @@ var _TaskQueue = class _TaskQueue {
|
|
|
434
417
|
}
|
|
435
418
|
/**
|
|
436
419
|
* The remaining number of tasks
|
|
437
|
-
* @type {number}
|
|
438
420
|
*/
|
|
439
421
|
get remaining() {
|
|
440
422
|
return __privateGet(this, _tasks).length;
|
|
441
423
|
}
|
|
442
424
|
/**
|
|
443
425
|
* Whether or not having a resolving info task
|
|
444
|
-
* @type {boolean}
|
|
445
426
|
*/
|
|
446
427
|
get hasResolveTask() {
|
|
447
428
|
return __privateGet(this, _tasks).some((t) => t.resolveInfo);
|
|
@@ -456,11 +437,9 @@ var _metadata, _member;
|
|
|
456
437
|
var _Playlist = class _Playlist {
|
|
457
438
|
/**
|
|
458
439
|
* Create a playlist
|
|
459
|
-
*
|
|
460
|
-
* @param
|
|
461
|
-
* @param
|
|
462
|
-
* @param {Object} [options.properties] Custom properties
|
|
463
|
-
* @param {T} [options.metadata] Playlist metadata
|
|
440
|
+
*
|
|
441
|
+
* @param playlist - Playlist
|
|
442
|
+
* @param options - Optional options
|
|
464
443
|
*/
|
|
465
444
|
constructor(playlist, options = {}) {
|
|
466
445
|
__publicField(this, "source");
|
|
@@ -504,21 +483,18 @@ var _Playlist = class _Playlist {
|
|
|
504
483
|
}
|
|
505
484
|
/**
|
|
506
485
|
* Playlist duration in second.
|
|
507
|
-
* @type {number}
|
|
508
486
|
*/
|
|
509
487
|
get duration() {
|
|
510
488
|
return this.songs.reduce((prev, next) => prev + next.duration, 0);
|
|
511
489
|
}
|
|
512
490
|
/**
|
|
513
491
|
* Formatted duration string `hh:mm:ss`.
|
|
514
|
-
* @type {string}
|
|
515
492
|
*/
|
|
516
493
|
get formattedDuration() {
|
|
517
494
|
return formatDuration(this.duration);
|
|
518
495
|
}
|
|
519
496
|
/**
|
|
520
497
|
* User requested.
|
|
521
|
-
* @type {Discord.GuildMember?}
|
|
522
498
|
*/
|
|
523
499
|
get member() {
|
|
524
500
|
return __privateGet(this, _member);
|
|
@@ -531,7 +507,6 @@ var _Playlist = class _Playlist {
|
|
|
531
507
|
}
|
|
532
508
|
/**
|
|
533
509
|
* User requested.
|
|
534
|
-
* @type {Discord.User?}
|
|
535
510
|
*/
|
|
536
511
|
get user() {
|
|
537
512
|
return this.member?.user;
|
|
@@ -553,7 +528,8 @@ var Playlist = _Playlist;
|
|
|
553
528
|
var _ISearchResult = class _ISearchResult {
|
|
554
529
|
/**
|
|
555
530
|
* Create a search result
|
|
556
|
-
*
|
|
531
|
+
*
|
|
532
|
+
* @param info - ytsr result
|
|
557
533
|
*/
|
|
558
534
|
constructor(info) {
|
|
559
535
|
__publicField(this, "source");
|
|
@@ -621,11 +597,9 @@ var _metadata2, _member2, _playlist;
|
|
|
621
597
|
var _Song = class _Song {
|
|
622
598
|
/**
|
|
623
599
|
* Create a Song
|
|
624
|
-
*
|
|
625
|
-
* @param
|
|
626
|
-
* @param
|
|
627
|
-
* @param {string} [options.source="youtube"] Song source
|
|
628
|
-
* @param {T} [options.metadata] Song metadata
|
|
600
|
+
*
|
|
601
|
+
* @param info - Raw info
|
|
602
|
+
* @param options - Optional options
|
|
629
603
|
*/
|
|
630
604
|
constructor(info, options = {}) {
|
|
631
605
|
__publicField(this, "source");
|
|
@@ -702,8 +676,8 @@ var _Song = class _Song {
|
|
|
702
676
|
}
|
|
703
677
|
/**
|
|
704
678
|
* Patch data from other source
|
|
705
|
-
*
|
|
706
|
-
* @
|
|
679
|
+
*
|
|
680
|
+
* @param info - Video info
|
|
707
681
|
*/
|
|
708
682
|
_patchOther(info) {
|
|
709
683
|
this.id = info.id;
|
|
@@ -737,7 +711,6 @@ var _Song = class _Song {
|
|
|
737
711
|
}
|
|
738
712
|
/**
|
|
739
713
|
* The playlist added this song
|
|
740
|
-
* @type {Playlist?}
|
|
741
714
|
*/
|
|
742
715
|
get playlist() {
|
|
743
716
|
return __privateGet(this, _playlist);
|
|
@@ -750,7 +723,6 @@ var _Song = class _Song {
|
|
|
750
723
|
}
|
|
751
724
|
/**
|
|
752
725
|
* User requested.
|
|
753
|
-
* @type {Discord.GuildMember?}
|
|
754
726
|
*/
|
|
755
727
|
get member() {
|
|
756
728
|
return __privateGet(this, _member2);
|
|
@@ -761,7 +733,6 @@ var _Song = class _Song {
|
|
|
761
733
|
}
|
|
762
734
|
/**
|
|
763
735
|
* User requested.
|
|
764
|
-
* @type {Discord.User?}
|
|
765
736
|
*/
|
|
766
737
|
get user() {
|
|
767
738
|
return this.member?.user;
|
|
@@ -787,57 +758,48 @@ var _DisTubeBase = class _DisTubeBase {
|
|
|
787
758
|
}
|
|
788
759
|
/**
|
|
789
760
|
* Emit the {@link DisTube} of this base
|
|
790
|
-
*
|
|
791
|
-
* @param
|
|
792
|
-
* @
|
|
761
|
+
*
|
|
762
|
+
* @param eventName - Event name
|
|
763
|
+
* @param args - arguments
|
|
793
764
|
*/
|
|
794
765
|
emit(eventName, ...args) {
|
|
795
766
|
return this.distube.emit(eventName, ...args);
|
|
796
767
|
}
|
|
797
768
|
/**
|
|
798
769
|
* Emit error event
|
|
799
|
-
*
|
|
800
|
-
* @param
|
|
770
|
+
*
|
|
771
|
+
* @param error - error
|
|
772
|
+
* @param channel - Text channel where the error is encountered.
|
|
801
773
|
*/
|
|
802
774
|
emitError(error, channel) {
|
|
803
775
|
this.distube.emitError(error, channel);
|
|
804
776
|
}
|
|
805
777
|
/**
|
|
806
778
|
* The queue manager
|
|
807
|
-
* @type {QueueManager}
|
|
808
|
-
* @readonly
|
|
809
779
|
*/
|
|
810
780
|
get queues() {
|
|
811
781
|
return this.distube.queues;
|
|
812
782
|
}
|
|
813
783
|
/**
|
|
814
784
|
* The voice manager
|
|
815
|
-
* @type {DisTubeVoiceManager}
|
|
816
|
-
* @readonly
|
|
817
785
|
*/
|
|
818
786
|
get voices() {
|
|
819
787
|
return this.distube.voices;
|
|
820
788
|
}
|
|
821
789
|
/**
|
|
822
790
|
* Discord.js client
|
|
823
|
-
* @type {Discord.Client}
|
|
824
|
-
* @readonly
|
|
825
791
|
*/
|
|
826
792
|
get client() {
|
|
827
793
|
return this.distube.client;
|
|
828
794
|
}
|
|
829
795
|
/**
|
|
830
796
|
* DisTube options
|
|
831
|
-
* @type {DisTubeOptions}
|
|
832
|
-
* @readonly
|
|
833
797
|
*/
|
|
834
798
|
get options() {
|
|
835
799
|
return this.distube.options;
|
|
836
800
|
}
|
|
837
801
|
/**
|
|
838
802
|
* DisTube handler
|
|
839
|
-
* @type {DisTubeHandler}
|
|
840
|
-
* @readonly
|
|
841
803
|
*/
|
|
842
804
|
get handler() {
|
|
843
805
|
return this.distube.handler;
|
|
@@ -863,6 +825,7 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
863
825
|
__publicField(this, "audioResource");
|
|
864
826
|
__publicField(this, "emittedError");
|
|
865
827
|
__publicField(this, "isDisconnected", false);
|
|
828
|
+
__publicField(this, "stream");
|
|
866
829
|
__privateAdd(this, _channel, void 0);
|
|
867
830
|
__privateAdd(this, _volume, 100);
|
|
868
831
|
this.voices = voiceManager;
|
|
@@ -906,7 +869,6 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
906
869
|
}
|
|
907
870
|
/**
|
|
908
871
|
* The voice channel id the bot is in
|
|
909
|
-
* @type {Snowflake?}
|
|
910
872
|
*/
|
|
911
873
|
get channelId() {
|
|
912
874
|
return this.connection?.joinConfig?.channelId ?? void 0;
|
|
@@ -949,8 +911,8 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
949
911
|
}
|
|
950
912
|
/**
|
|
951
913
|
* Join a voice channel with this connection
|
|
952
|
-
*
|
|
953
|
-
* @
|
|
914
|
+
*
|
|
915
|
+
* @param channel - A voice channel
|
|
954
916
|
*/
|
|
955
917
|
async join(channel) {
|
|
956
918
|
const TIMEOUT = 3e4;
|
|
@@ -970,7 +932,8 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
970
932
|
}
|
|
971
933
|
/**
|
|
972
934
|
* Leave the voice channel of this connection
|
|
973
|
-
*
|
|
935
|
+
*
|
|
936
|
+
* @param error - Optional, an error to emit with 'error' event.
|
|
974
937
|
*/
|
|
975
938
|
leave(error) {
|
|
976
939
|
this.stop(true);
|
|
@@ -984,33 +947,36 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
984
947
|
}
|
|
985
948
|
/**
|
|
986
949
|
* Stop the playing stream
|
|
987
|
-
*
|
|
988
|
-
*
|
|
989
|
-
* @
|
|
950
|
+
*
|
|
951
|
+
* @param force - If true, will force the {@link DisTubeVoice#audioPlayer} to enter the Idle state even
|
|
952
|
+
* if the {@link DisTubeVoice#audioResource} has silence padding frames.
|
|
990
953
|
*/
|
|
991
954
|
stop(force = false) {
|
|
992
955
|
this.audioPlayer.stop(force);
|
|
956
|
+
this.stream?.kill?.();
|
|
993
957
|
}
|
|
994
958
|
/**
|
|
995
|
-
* Play a
|
|
996
|
-
*
|
|
997
|
-
* @param
|
|
959
|
+
* Play a {@link DisTubeStream}
|
|
960
|
+
*
|
|
961
|
+
* @param dtStream - DisTubeStream
|
|
998
962
|
*/
|
|
999
|
-
play(
|
|
963
|
+
play(dtStream) {
|
|
1000
964
|
this.emittedError = false;
|
|
1001
|
-
|
|
965
|
+
dtStream.stream.on("error", (error) => {
|
|
1002
966
|
if (this.emittedError || error.code === "ERR_STREAM_PREMATURE_CLOSE")
|
|
1003
967
|
return;
|
|
1004
968
|
this.emittedError = true;
|
|
1005
969
|
this.emit("error", error);
|
|
1006
970
|
});
|
|
1007
|
-
this.audioResource = (0, import_voice.createAudioResource)(
|
|
1008
|
-
inputType:
|
|
971
|
+
this.audioResource = (0, import_voice.createAudioResource)(dtStream.stream, {
|
|
972
|
+
inputType: dtStream.type,
|
|
1009
973
|
inlineVolume: true
|
|
1010
974
|
});
|
|
1011
975
|
this.volume = __privateGet(this, _volume);
|
|
1012
976
|
if (this.audioPlayer.state.status !== import_voice.AudioPlayerStatus.Paused)
|
|
1013
977
|
this.audioPlayer.play(this.audioResource);
|
|
978
|
+
this.stream?.kill?.();
|
|
979
|
+
this.stream = dtStream;
|
|
1014
980
|
}
|
|
1015
981
|
set volume(volume) {
|
|
1016
982
|
if (typeof volume !== "number" || isNaN(volume)) {
|
|
@@ -1027,7 +993,6 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
1027
993
|
}
|
|
1028
994
|
/**
|
|
1029
995
|
* Playback duration of the audio resource in seconds
|
|
1030
|
-
* @type {number}
|
|
1031
996
|
*/
|
|
1032
997
|
get playbackDuration() {
|
|
1033
998
|
return (this.audioResource?.playbackDuration ?? 0) / 1e3;
|
|
@@ -1046,22 +1011,22 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
1046
1011
|
}
|
|
1047
1012
|
/**
|
|
1048
1013
|
* Whether the bot is self-deafened
|
|
1049
|
-
* @type {boolean}
|
|
1050
1014
|
*/
|
|
1051
1015
|
get selfDeaf() {
|
|
1052
1016
|
return this.connection.joinConfig.selfDeaf;
|
|
1053
1017
|
}
|
|
1054
1018
|
/**
|
|
1055
1019
|
* Whether the bot is self-muted
|
|
1056
|
-
* @type {boolean}
|
|
1057
1020
|
*/
|
|
1058
1021
|
get selfMute() {
|
|
1059
1022
|
return this.connection.joinConfig.selfMute;
|
|
1060
1023
|
}
|
|
1061
1024
|
/**
|
|
1062
1025
|
* Self-deafens/undeafens the bot.
|
|
1063
|
-
*
|
|
1064
|
-
* @
|
|
1026
|
+
*
|
|
1027
|
+
* @param selfDeaf - Whether or not the bot should be self-deafened
|
|
1028
|
+
*
|
|
1029
|
+
* @returns true if the voice state was successfully updated, otherwise false
|
|
1065
1030
|
*/
|
|
1066
1031
|
setSelfDeaf(selfDeaf) {
|
|
1067
1032
|
if (typeof selfDeaf !== "boolean") {
|
|
@@ -1074,8 +1039,10 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
1074
1039
|
}
|
|
1075
1040
|
/**
|
|
1076
1041
|
* Self-mutes/unmutes the bot.
|
|
1077
|
-
*
|
|
1078
|
-
* @
|
|
1042
|
+
*
|
|
1043
|
+
* @param selfMute - Whether or not the bot should be self-muted
|
|
1044
|
+
*
|
|
1045
|
+
* @returns true if the voice state was successfully updated, otherwise false
|
|
1079
1046
|
*/
|
|
1080
1047
|
setSelfMute(selfMute) {
|
|
1081
1048
|
if (typeof selfMute !== "boolean") {
|
|
@@ -1088,7 +1055,6 @@ var _DisTubeVoice = class _DisTubeVoice extends import_tiny_typed_emitter.TypedE
|
|
|
1088
1055
|
}
|
|
1089
1056
|
/**
|
|
1090
1057
|
* The voice state of this connection
|
|
1091
|
-
* @type {Discord.VoiceState?}
|
|
1092
1058
|
*/
|
|
1093
1059
|
get voiceState() {
|
|
1094
1060
|
return this.channel?.guild?.members?.me?.voice;
|
|
@@ -1114,60 +1080,94 @@ __name(_DisTubeVoice, "DisTubeVoice");
|
|
|
1114
1080
|
var DisTubeVoice = _DisTubeVoice;
|
|
1115
1081
|
|
|
1116
1082
|
// src/core/DisTubeStream.ts
|
|
1117
|
-
var
|
|
1083
|
+
var import_child_process = require("child_process");
|
|
1084
|
+
var import_node_stream = require("stream");
|
|
1085
|
+
var import_tiny_typed_emitter2 = require("tiny-typed-emitter");
|
|
1118
1086
|
var import_voice2 = require("@discordjs/voice");
|
|
1119
1087
|
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");
|
|
1120
|
-
var _DisTubeStream = class _DisTubeStream {
|
|
1088
|
+
var _DisTubeStream = class _DisTubeStream extends import_tiny_typed_emitter2.TypedEmitter {
|
|
1121
1089
|
/**
|
|
1122
1090
|
* Create a DisTubeStream to play with {@link DisTubeVoice}
|
|
1123
|
-
*
|
|
1124
|
-
* @param
|
|
1125
|
-
* @
|
|
1091
|
+
*
|
|
1092
|
+
* @param url - Stream URL
|
|
1093
|
+
* @param options - Stream options
|
|
1126
1094
|
*/
|
|
1127
|
-
constructor(url,
|
|
1128
|
-
|
|
1095
|
+
constructor(url, { ffmpeg, seek, type }) {
|
|
1096
|
+
super();
|
|
1097
|
+
__publicField(this, "killed", false);
|
|
1098
|
+
__publicField(this, "process");
|
|
1129
1099
|
__publicField(this, "stream");
|
|
1100
|
+
__publicField(this, "type");
|
|
1130
1101
|
__publicField(this, "url");
|
|
1131
1102
|
this.url = url;
|
|
1132
|
-
this.type = !
|
|
1133
|
-
const
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
"
|
|
1145
|
-
"
|
|
1146
|
-
|
|
1147
|
-
"
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1103
|
+
this.type = !type ? import_voice2.StreamType.OggOpus : import_voice2.StreamType.Raw;
|
|
1104
|
+
const opts = {
|
|
1105
|
+
reconnect: 1,
|
|
1106
|
+
reconnect_on_network_error: 1,
|
|
1107
|
+
reconnect_streamed: 1,
|
|
1108
|
+
reconnect_delay_max: 5,
|
|
1109
|
+
i: url,
|
|
1110
|
+
ar: 48e3,
|
|
1111
|
+
ac: 2,
|
|
1112
|
+
...ffmpeg.args
|
|
1113
|
+
};
|
|
1114
|
+
if (!type) {
|
|
1115
|
+
opts.f = "opus";
|
|
1116
|
+
opts.acodec = "libopus";
|
|
1117
|
+
} else {
|
|
1118
|
+
opts.f = "s16le";
|
|
1119
|
+
}
|
|
1120
|
+
if (typeof seek === "number" && seek > 0)
|
|
1121
|
+
opts.ss = seek.toString();
|
|
1122
|
+
if (typeof ffmpeg.args === "object")
|
|
1123
|
+
Object.assign(opts, ffmpeg.args);
|
|
1124
|
+
this.process = (0, import_child_process.spawn)(
|
|
1125
|
+
ffmpeg.path,
|
|
1126
|
+
[
|
|
1127
|
+
...Object.entries(opts).flatMap(
|
|
1128
|
+
([key, value]) => Array.isArray(value) ? value.filter(Boolean).map((v) => [`-${key}`, String(v)]) : value == null || value === false ? [] : [value === true ? `-${key}` : [`-${key}`, String(value)]]
|
|
1129
|
+
).flat(),
|
|
1130
|
+
"pipe:1"
|
|
1131
|
+
],
|
|
1132
|
+
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
1133
|
+
).on("error", (err) => this.debug(`[process] error: ${err.message}`)).on("exit", (code, signal) => {
|
|
1134
|
+
this.debug(`[process] exit: code=${code ?? "unknown"} signal=${signal ?? "unknown"}`);
|
|
1135
|
+
if (!code || [0, 255].includes(code))
|
|
1136
|
+
return;
|
|
1137
|
+
this.debug(`[process] error: ffmpeg exited with code ${code}`);
|
|
1138
|
+
});
|
|
1139
|
+
if (!this.process.stdout || !this.process.stderr) {
|
|
1140
|
+
this.kill();
|
|
1141
|
+
throw new Error("Failed to create ffmpeg process");
|
|
1142
|
+
}
|
|
1143
|
+
this.stream = new import_node_stream.PassThrough();
|
|
1144
|
+
this.stream.on("close", () => this.kill()).on("error", (err) => this.debug(`[stream] error: ${err.message}`)).on("finish", () => this.debug("[stream] log: stream finished"));
|
|
1145
|
+
this.process.stdout.pipe(this.stream);
|
|
1146
|
+
this.process.stderr.setEncoding("utf8")?.on("data", (data) => {
|
|
1147
|
+
const lines = data.split(/\r\n|\r|\n/u);
|
|
1148
|
+
for (const line of lines) {
|
|
1149
|
+
if (/^\s*$/.test(line))
|
|
1150
|
+
continue;
|
|
1151
|
+
this.debug(`[ffmpeg] log: ${line}`);
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
debug(debug) {
|
|
1156
|
+
this.emit("debug", debug);
|
|
1157
|
+
}
|
|
1158
|
+
kill() {
|
|
1159
|
+
if (this.killed)
|
|
1160
|
+
return;
|
|
1161
|
+
this.process.kill("SIGKILL");
|
|
1162
|
+
this.killed = true;
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Create a stream from a YouTube {@link Song}
|
|
1166
|
+
*
|
|
1167
|
+
* @param song - A YouTube Song
|
|
1168
|
+
* @param options - options
|
|
1169
|
+
*/
|
|
1170
|
+
static YouTube(song, options) {
|
|
1171
1171
|
if (song.source !== "youtube")
|
|
1172
1172
|
throw new DisTubeError("INVALID_TYPE", "youtube", song.source, "Song#source");
|
|
1173
1173
|
if (!song.formats?.length)
|
|
@@ -1182,18 +1182,17 @@ var _DisTubeStream = class _DisTubeStream {
|
|
|
1182
1182
|
}
|
|
1183
1183
|
/**
|
|
1184
1184
|
* Create a stream from a stream url
|
|
1185
|
-
*
|
|
1186
|
-
* @param
|
|
1187
|
-
* @
|
|
1188
|
-
* @private
|
|
1185
|
+
*
|
|
1186
|
+
* @param url - stream url
|
|
1187
|
+
* @param options - options
|
|
1189
1188
|
*/
|
|
1190
|
-
static DirectLink(url, options
|
|
1191
|
-
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
1192
|
-
throw new DisTubeError("INVALID_TYPE", "object", options, "options");
|
|
1193
|
-
}
|
|
1189
|
+
static DirectLink(url, options) {
|
|
1194
1190
|
if (typeof url !== "string" || !isURL(url)) {
|
|
1195
1191
|
throw new DisTubeError("INVALID_TYPE", "an URL", url);
|
|
1196
1192
|
}
|
|
1193
|
+
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
1194
|
+
throw new DisTubeError("INVALID_TYPE", "object", options, "options");
|
|
1195
|
+
}
|
|
1197
1196
|
return new _DisTubeStream(url, options);
|
|
1198
1197
|
}
|
|
1199
1198
|
};
|
|
@@ -1233,7 +1232,7 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1233
1232
|
delete queue._emptyTimeout;
|
|
1234
1233
|
if (isVoiceChannelEmpty(oldState)) {
|
|
1235
1234
|
queue.voice.leave();
|
|
1236
|
-
this.emit("empty"
|
|
1235
|
+
this.emit("empty" /* EMPTY */, queue);
|
|
1237
1236
|
if (queue.stopped)
|
|
1238
1237
|
queue.remove();
|
|
1239
1238
|
}
|
|
@@ -1267,9 +1266,8 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1267
1266
|
return jar.getCookieStringSync("https://www.youtube.com");
|
|
1268
1267
|
}
|
|
1269
1268
|
/**
|
|
1270
|
-
* @param
|
|
1271
|
-
* @param
|
|
1272
|
-
* @returns {Promise<ytdl.videoInfo>}
|
|
1269
|
+
* @param url - url
|
|
1270
|
+
* @param basic - getBasicInfo?
|
|
1273
1271
|
*/
|
|
1274
1272
|
getYouTubeInfo(url, basic = false) {
|
|
1275
1273
|
if (basic)
|
|
@@ -1278,10 +1276,13 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1278
1276
|
}
|
|
1279
1277
|
/**
|
|
1280
1278
|
* Resolve a url or a supported object to a {@link Song} or {@link Playlist}
|
|
1281
|
-
*
|
|
1282
|
-
* @
|
|
1283
|
-
*
|
|
1284
|
-
* @
|
|
1279
|
+
*
|
|
1280
|
+
* @throws {@link DisTubeError}
|
|
1281
|
+
*
|
|
1282
|
+
* @param song - URL | {@link Song}| {@link SearchResult} | {@link Playlist}
|
|
1283
|
+
* @param options - Optional options
|
|
1284
|
+
*
|
|
1285
|
+
* @returns Resolved
|
|
1285
1286
|
*/
|
|
1286
1287
|
async resolve(song, options = {}) {
|
|
1287
1288
|
if (song instanceof Song || song instanceof Playlist) {
|
|
@@ -1315,9 +1316,9 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1315
1316
|
}
|
|
1316
1317
|
/**
|
|
1317
1318
|
* Resolve Song[] or YouTube playlist url to a Playlist
|
|
1318
|
-
*
|
|
1319
|
-
* @param
|
|
1320
|
-
* @
|
|
1319
|
+
*
|
|
1320
|
+
* @param playlist - Resolvable playlist
|
|
1321
|
+
* @param options - Optional options
|
|
1321
1322
|
*/
|
|
1322
1323
|
async resolvePlaylist(playlist, options = {}) {
|
|
1323
1324
|
const { member, source, metadata } = { source: "youtube", ...options };
|
|
@@ -1346,11 +1347,14 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1346
1347
|
return new Playlist(playlist, { member, properties: { source }, metadata });
|
|
1347
1348
|
}
|
|
1348
1349
|
/**
|
|
1349
|
-
* Search for a song, fire {@link DisTube#
|
|
1350
|
-
*
|
|
1351
|
-
* @
|
|
1352
|
-
*
|
|
1353
|
-
* @
|
|
1350
|
+
* Search for a song, fire {@link DisTube#error} if not found.
|
|
1351
|
+
*
|
|
1352
|
+
* @throws {@link DisTubeError}
|
|
1353
|
+
*
|
|
1354
|
+
* @param message - The original message from an user
|
|
1355
|
+
* @param query - The query string
|
|
1356
|
+
*
|
|
1357
|
+
* @returns Song info
|
|
1354
1358
|
*/
|
|
1355
1359
|
async searchSong(message, query) {
|
|
1356
1360
|
if (!isMessageInstance(message))
|
|
@@ -1364,7 +1368,7 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1364
1368
|
limit,
|
|
1365
1369
|
safeSearch: this.options.nsfw ? false : !isNsfwChannel(message.channel)
|
|
1366
1370
|
}).catch(() => {
|
|
1367
|
-
if (!this.emit("searchNoResult"
|
|
1371
|
+
if (!this.emit("searchNoResult" /* SEARCH_NO_RESULT */, message, query)) {
|
|
1368
1372
|
console.warn("searchNoResult event does not have any listeners! Emits `error` event instead.");
|
|
1369
1373
|
throw new DisTubeError("NO_RESULT");
|
|
1370
1374
|
}
|
|
@@ -1376,13 +1380,16 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1376
1380
|
/**
|
|
1377
1381
|
* Create a message collector for selecting search results.
|
|
1378
1382
|
*
|
|
1379
|
-
* Needed events: {@link DisTube#
|
|
1380
|
-
* {@link DisTube#
|
|
1381
|
-
*
|
|
1382
|
-
* @
|
|
1383
|
-
*
|
|
1384
|
-
* @
|
|
1385
|
-
* @
|
|
1383
|
+
* Needed events: {@link DisTube#searchResult}, {@link DisTube#searchCancel},
|
|
1384
|
+
* {@link DisTube#searchInvalidAnswer}, {@link DisTube#searchDone}.
|
|
1385
|
+
*
|
|
1386
|
+
* @throws {@link DisTubeError}
|
|
1387
|
+
*
|
|
1388
|
+
* @param message - The original message from an user
|
|
1389
|
+
* @param results - The search results
|
|
1390
|
+
* @param query - The query string
|
|
1391
|
+
*
|
|
1392
|
+
* @returns Selected result
|
|
1386
1393
|
*/
|
|
1387
1394
|
async createSearchMessageCollector(message, results, query) {
|
|
1388
1395
|
if (!isMessageInstance(message))
|
|
@@ -1392,11 +1399,11 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1392
1399
|
}
|
|
1393
1400
|
if (this.options.searchSongs > 1) {
|
|
1394
1401
|
const searchEvents = [
|
|
1395
|
-
"searchNoResult"
|
|
1396
|
-
"searchResult"
|
|
1397
|
-
"searchCancel"
|
|
1398
|
-
"searchInvalidAnswer"
|
|
1399
|
-
"searchDone"
|
|
1402
|
+
"searchNoResult" /* SEARCH_NO_RESULT */,
|
|
1403
|
+
"searchResult" /* SEARCH_RESULT */,
|
|
1404
|
+
"searchCancel" /* SEARCH_CANCEL */,
|
|
1405
|
+
"searchInvalidAnswer" /* SEARCH_INVALID_ANSWER */,
|
|
1406
|
+
"searchDone" /* SEARCH_DONE */
|
|
1400
1407
|
];
|
|
1401
1408
|
for (const evn of searchEvents) {
|
|
1402
1409
|
if (this.distube.listenerCount(evn) === 0) {
|
|
@@ -1413,7 +1420,7 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1413
1420
|
let result = results[0];
|
|
1414
1421
|
if (limit > 1) {
|
|
1415
1422
|
results.splice(limit);
|
|
1416
|
-
this.emit("searchResult"
|
|
1423
|
+
this.emit("searchResult" /* SEARCH_RESULT */, message, results, query);
|
|
1417
1424
|
const answers = await message.channel.awaitMessages({
|
|
1418
1425
|
filter: (m) => m.author.id === message.author.id,
|
|
1419
1426
|
max: 1,
|
|
@@ -1422,26 +1429,27 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1422
1429
|
}).catch(() => void 0);
|
|
1423
1430
|
const ans = answers?.first();
|
|
1424
1431
|
if (!ans) {
|
|
1425
|
-
this.emit("searchCancel"
|
|
1432
|
+
this.emit("searchCancel" /* SEARCH_CANCEL */, message, query);
|
|
1426
1433
|
return null;
|
|
1427
1434
|
}
|
|
1428
1435
|
const index = parseInt(ans.content, 10);
|
|
1429
1436
|
if (isNaN(index) || index > results.length || index < 1) {
|
|
1430
|
-
this.emit("searchInvalidAnswer"
|
|
1437
|
+
this.emit("searchInvalidAnswer" /* SEARCH_INVALID_ANSWER */, message, ans, query);
|
|
1431
1438
|
return null;
|
|
1432
1439
|
}
|
|
1433
|
-
this.emit("searchDone"
|
|
1440
|
+
this.emit("searchDone" /* SEARCH_DONE */, message, ans, query);
|
|
1434
1441
|
result = results[index - 1];
|
|
1435
1442
|
}
|
|
1436
1443
|
return result;
|
|
1437
1444
|
}
|
|
1438
1445
|
/**
|
|
1439
1446
|
* Play or add a {@link Playlist} to the queue.
|
|
1440
|
-
*
|
|
1441
|
-
* @
|
|
1442
|
-
*
|
|
1443
|
-
* @
|
|
1444
|
-
* @
|
|
1447
|
+
*
|
|
1448
|
+
* @throws {@link DisTubeError}
|
|
1449
|
+
*
|
|
1450
|
+
* @param voiceChannel - A voice channel
|
|
1451
|
+
* @param playlist - A YouTube playlist url | a Playlist
|
|
1452
|
+
* @param options - Optional options
|
|
1445
1453
|
*/
|
|
1446
1454
|
async playPlaylist(voiceChannel, playlist, options = {}) {
|
|
1447
1455
|
const { textChannel, skip } = { skip: false, ...options };
|
|
@@ -1464,23 +1472,24 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1464
1472
|
if (skip)
|
|
1465
1473
|
queue.skip();
|
|
1466
1474
|
else
|
|
1467
|
-
this.emit("addList"
|
|
1475
|
+
this.emit("addList" /* ADD_LIST */, queue, playlist);
|
|
1468
1476
|
} else {
|
|
1469
1477
|
const newQueue = await this.queues.create(voiceChannel, playlist.songs, textChannel);
|
|
1470
1478
|
if (newQueue instanceof Queue) {
|
|
1471
1479
|
if (this.options.emitAddListWhenCreatingQueue)
|
|
1472
|
-
this.emit("addList"
|
|
1473
|
-
this.emit("playSong"
|
|
1480
|
+
this.emit("addList" /* ADD_LIST */, newQueue, playlist);
|
|
1481
|
+
this.emit("playSong" /* PLAY_SONG */, newQueue, newQueue.songs[0]);
|
|
1474
1482
|
}
|
|
1475
1483
|
}
|
|
1476
1484
|
}
|
|
1477
1485
|
/**
|
|
1478
1486
|
* Play or add a {@link Song} to the queue.
|
|
1479
|
-
*
|
|
1480
|
-
* @
|
|
1481
|
-
*
|
|
1482
|
-
* @
|
|
1483
|
-
* @
|
|
1487
|
+
*
|
|
1488
|
+
* @throws {@link DisTubeError}
|
|
1489
|
+
*
|
|
1490
|
+
* @param voiceChannel - A voice channel
|
|
1491
|
+
* @param song - A YouTube playlist url | a Playlist
|
|
1492
|
+
* @param options - Optional options
|
|
1484
1493
|
*/
|
|
1485
1494
|
async playSong(voiceChannel, song, options = {}) {
|
|
1486
1495
|
if (!(song instanceof Song))
|
|
@@ -1498,27 +1507,26 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1498
1507
|
if (skip)
|
|
1499
1508
|
queue.skip();
|
|
1500
1509
|
else
|
|
1501
|
-
this.emit("addSong"
|
|
1510
|
+
this.emit("addSong" /* ADD_SONG */, queue, song);
|
|
1502
1511
|
} else {
|
|
1503
1512
|
const newQueue = await this.queues.create(voiceChannel, song, textChannel);
|
|
1504
1513
|
if (newQueue instanceof Queue) {
|
|
1505
1514
|
if (this.options.emitAddSongWhenCreatingQueue)
|
|
1506
|
-
this.emit("addSong"
|
|
1507
|
-
this.emit("playSong"
|
|
1515
|
+
this.emit("addSong" /* ADD_SONG */, newQueue, song);
|
|
1516
|
+
this.emit("playSong" /* PLAY_SONG */, newQueue, song);
|
|
1508
1517
|
}
|
|
1509
1518
|
}
|
|
1510
1519
|
}
|
|
1511
1520
|
/**
|
|
1512
1521
|
* Get {@link Song}'s stream info and attach it to the song.
|
|
1513
|
-
*
|
|
1522
|
+
*
|
|
1523
|
+
* @param song - A Song
|
|
1514
1524
|
*/
|
|
1515
1525
|
async attachStreamInfo(song) {
|
|
1516
|
-
const { url, source
|
|
1526
|
+
const { url, source } = song;
|
|
1517
1527
|
if (source === "youtube") {
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
}
|
|
1521
|
-
} else if (!streamURL) {
|
|
1528
|
+
song._patchYouTube(await this.handler.getYouTubeInfo(url));
|
|
1529
|
+
} else {
|
|
1522
1530
|
for (const plugin of [...this.distube.extractorPlugins, ...this.distube.customPlugins]) {
|
|
1523
1531
|
if (await plugin.validate(url)) {
|
|
1524
1532
|
const info = [plugin.getStreamURL(url), plugin.getRelatedSongs(url)];
|
|
@@ -1558,6 +1566,8 @@ var _Options = class _Options {
|
|
|
1558
1566
|
__publicField(this, "joinNewVoiceChannel");
|
|
1559
1567
|
__publicField(this, "streamType");
|
|
1560
1568
|
__publicField(this, "directLink");
|
|
1569
|
+
__publicField(this, "ffmpegPath");
|
|
1570
|
+
__publicField(this, "ffmpegDefaultArgs");
|
|
1561
1571
|
if (typeof options !== "object" || Array.isArray(options)) {
|
|
1562
1572
|
throw new DisTubeError("INVALID_TYPE", "object", options, "DisTubeOptions");
|
|
1563
1573
|
}
|
|
@@ -1580,6 +1590,8 @@ var _Options = class _Options {
|
|
|
1580
1590
|
this.joinNewVoiceChannel = opts.joinNewVoiceChannel;
|
|
1581
1591
|
this.streamType = opts.streamType;
|
|
1582
1592
|
this.directLink = opts.directLink;
|
|
1593
|
+
this.ffmpegPath = opts.ffmpegPath;
|
|
1594
|
+
this.ffmpegDefaultArgs = opts.ffmpegDefaultArgs;
|
|
1583
1595
|
checkInvalidKey(opts, this, "DisTubeOptions");
|
|
1584
1596
|
__privateMethod(this, _validateOptions, validateOptions_fn).call(this);
|
|
1585
1597
|
}
|
|
@@ -1599,8 +1611,8 @@ validateOptions_fn = /* @__PURE__ */ __name(function(options = this) {
|
|
|
1599
1611
|
"directLink"
|
|
1600
1612
|
]);
|
|
1601
1613
|
const numberOptions = /* @__PURE__ */ new Set(["searchCooldown", "emptyCooldown", "searchSongs"]);
|
|
1602
|
-
const stringOptions = /* @__PURE__ */ new Set();
|
|
1603
|
-
const objectOptions = /* @__PURE__ */ new Set(["customFilters", "ytdlOptions"]);
|
|
1614
|
+
const stringOptions = /* @__PURE__ */ new Set(["ffmpegPath"]);
|
|
1615
|
+
const objectOptions = /* @__PURE__ */ new Set(["customFilters", "ytdlOptions", "ffmpegDefaultArgs"]);
|
|
1604
1616
|
const optionalOptions = /* @__PURE__ */ new Set(["youtubeCookie", "customFilters"]);
|
|
1605
1617
|
for (const [key, value] of Object.entries(options)) {
|
|
1606
1618
|
if (value === void 0 && optionalOptions.has(key))
|
|
@@ -1640,14 +1652,11 @@ var _BaseManager = class _BaseManager extends DisTubeBase {
|
|
|
1640
1652
|
super(...arguments);
|
|
1641
1653
|
/**
|
|
1642
1654
|
* The collection of items for this manager.
|
|
1643
|
-
* @type {Collection}
|
|
1644
|
-
* @name BaseManager#collection
|
|
1645
1655
|
*/
|
|
1646
1656
|
__publicField(this, "collection", new import_discord2.Collection());
|
|
1647
1657
|
}
|
|
1648
1658
|
/**
|
|
1649
1659
|
* The size of the collection.
|
|
1650
|
-
* @type {number}
|
|
1651
1660
|
*/
|
|
1652
1661
|
get size() {
|
|
1653
1662
|
return this.collection.size;
|
|
@@ -1663,7 +1672,8 @@ var _GuildIdManager = class _GuildIdManager extends BaseManager {
|
|
|
1663
1672
|
const existing = this.get(id);
|
|
1664
1673
|
if (existing)
|
|
1665
1674
|
return this;
|
|
1666
|
-
|
|
1675
|
+
this.collection.set(id, data);
|
|
1676
|
+
return this;
|
|
1667
1677
|
}
|
|
1668
1678
|
get(idOrInstance) {
|
|
1669
1679
|
return this.collection.get(resolveGuildId(idOrInstance));
|
|
@@ -1683,21 +1693,16 @@ var import_voice3 = require("@discordjs/voice");
|
|
|
1683
1693
|
var _DisTubeVoiceManager = class _DisTubeVoiceManager extends GuildIdManager {
|
|
1684
1694
|
/**
|
|
1685
1695
|
* Get a {@link DisTubeVoice}.
|
|
1686
|
-
*
|
|
1687
|
-
* @
|
|
1688
|
-
* @param {GuildIdResolvable} guild The queue resolvable to resolve
|
|
1689
|
-
* @returns {DisTubeVoice?}
|
|
1696
|
+
*
|
|
1697
|
+
* @param guild - The queue resolvable to resolve
|
|
1690
1698
|
*/
|
|
1691
1699
|
/**
|
|
1692
1700
|
* Collection of {@link DisTubeVoice}.
|
|
1693
|
-
* @name DisTubeVoiceManager#collection
|
|
1694
|
-
* @type {Discord.Collection<string, DisTubeVoice>}
|
|
1695
1701
|
*/
|
|
1696
1702
|
/**
|
|
1697
1703
|
* Create a {@link DisTubeVoice}
|
|
1698
|
-
*
|
|
1699
|
-
* @
|
|
1700
|
-
* @private
|
|
1704
|
+
*
|
|
1705
|
+
* @param channel - A voice channel to join
|
|
1701
1706
|
*/
|
|
1702
1707
|
create(channel) {
|
|
1703
1708
|
const existing = this.get(channel.guildId);
|
|
@@ -1709,8 +1714,8 @@ var _DisTubeVoiceManager = class _DisTubeVoiceManager extends GuildIdManager {
|
|
|
1709
1714
|
}
|
|
1710
1715
|
/**
|
|
1711
1716
|
* Join a voice channel
|
|
1712
|
-
*
|
|
1713
|
-
* @
|
|
1717
|
+
*
|
|
1718
|
+
* @param channel - A voice channel to join
|
|
1714
1719
|
*/
|
|
1715
1720
|
join(channel) {
|
|
1716
1721
|
const existing = this.get(channel.guildId);
|
|
@@ -1720,7 +1725,8 @@ var _DisTubeVoiceManager = class _DisTubeVoiceManager extends GuildIdManager {
|
|
|
1720
1725
|
}
|
|
1721
1726
|
/**
|
|
1722
1727
|
* Leave the connected voice channel in a guild
|
|
1723
|
-
*
|
|
1728
|
+
*
|
|
1729
|
+
* @param guild - Queue Resolvable
|
|
1724
1730
|
*/
|
|
1725
1731
|
leave(guild) {
|
|
1726
1732
|
const voice = this.get(guild);
|
|
@@ -1747,17 +1753,15 @@ var _FilterManager = class _FilterManager extends BaseManager {
|
|
|
1747
1753
|
__privateAdd(this, _removeFn);
|
|
1748
1754
|
/**
|
|
1749
1755
|
* Collection of {@link Filter}.
|
|
1750
|
-
* @name FilterManager#collection
|
|
1751
|
-
* @type {Discord.Collection<string, DisTubeVoice>}
|
|
1752
1756
|
*/
|
|
1753
1757
|
__publicField(this, "queue");
|
|
1754
1758
|
this.queue = queue;
|
|
1755
1759
|
}
|
|
1756
1760
|
/**
|
|
1757
1761
|
* Enable a filter or multiple filters to the manager
|
|
1758
|
-
*
|
|
1759
|
-
* @param
|
|
1760
|
-
* @
|
|
1762
|
+
*
|
|
1763
|
+
* @param filterOrFilters - The filter or filters to enable
|
|
1764
|
+
* @param override - Wether or not override the applied filter with new filter value
|
|
1761
1765
|
*/
|
|
1762
1766
|
add(filterOrFilters, override = false) {
|
|
1763
1767
|
if (Array.isArray(filterOrFilters)) {
|
|
@@ -1776,15 +1780,14 @@ var _FilterManager = class _FilterManager extends BaseManager {
|
|
|
1776
1780
|
}
|
|
1777
1781
|
/**
|
|
1778
1782
|
* Clear enabled filters of the manager
|
|
1779
|
-
* @returns {FilterManager}
|
|
1780
1783
|
*/
|
|
1781
1784
|
clear() {
|
|
1782
1785
|
return this.set([]);
|
|
1783
1786
|
}
|
|
1784
1787
|
/**
|
|
1785
1788
|
* Set the filters applied to the manager
|
|
1786
|
-
*
|
|
1787
|
-
* @
|
|
1789
|
+
*
|
|
1790
|
+
* @param filters - The filters to apply
|
|
1788
1791
|
*/
|
|
1789
1792
|
set(filters) {
|
|
1790
1793
|
if (!Array.isArray(filters))
|
|
@@ -1799,8 +1802,8 @@ var _FilterManager = class _FilterManager extends BaseManager {
|
|
|
1799
1802
|
}
|
|
1800
1803
|
/**
|
|
1801
1804
|
* Disable a filter or multiple filters
|
|
1802
|
-
*
|
|
1803
|
-
* @
|
|
1805
|
+
*
|
|
1806
|
+
* @param filterOrFilters - The filter or filters to disable
|
|
1804
1807
|
*/
|
|
1805
1808
|
remove(filterOrFilters) {
|
|
1806
1809
|
if (Array.isArray(filterOrFilters))
|
|
@@ -1812,30 +1815,26 @@ var _FilterManager = class _FilterManager extends BaseManager {
|
|
|
1812
1815
|
}
|
|
1813
1816
|
/**
|
|
1814
1817
|
* Check whether a filter enabled or not
|
|
1815
|
-
*
|
|
1816
|
-
* @
|
|
1818
|
+
*
|
|
1819
|
+
* @param filter - The filter to check
|
|
1817
1820
|
*/
|
|
1818
1821
|
has(filter) {
|
|
1819
1822
|
return this.collection.has(typeof filter === "string" ? filter : __privateMethod(this, _resolve, resolve_fn).call(this, filter).name);
|
|
1820
1823
|
}
|
|
1821
1824
|
/**
|
|
1822
1825
|
* Array of enabled filter names
|
|
1823
|
-
* @type {Array<string>}
|
|
1824
|
-
* @readonly
|
|
1825
1826
|
*/
|
|
1826
1827
|
get names() {
|
|
1827
1828
|
return [...this.collection.keys()];
|
|
1828
1829
|
}
|
|
1829
1830
|
/**
|
|
1830
1831
|
* Array of enabled filters
|
|
1831
|
-
* @type {Array<Filter>}
|
|
1832
|
-
* @readonly
|
|
1833
1832
|
*/
|
|
1834
1833
|
get values() {
|
|
1835
1834
|
return [...this.collection.values()];
|
|
1836
1835
|
}
|
|
1837
1836
|
get ffmpegArgs() {
|
|
1838
|
-
return this.size ?
|
|
1837
|
+
return this.size ? { af: this.values.map((f) => f.value).join(",") } : {};
|
|
1839
1838
|
}
|
|
1840
1839
|
toString() {
|
|
1841
1840
|
return this.names.toString();
|
|
@@ -1873,51 +1872,46 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1873
1872
|
super(...arguments);
|
|
1874
1873
|
/**
|
|
1875
1874
|
* Get a Queue from this QueueManager.
|
|
1876
|
-
*
|
|
1877
|
-
* @
|
|
1878
|
-
* @param {GuildIdResolvable} guild Resolvable thing from a guild
|
|
1879
|
-
* @returns {Queue?}
|
|
1875
|
+
*
|
|
1876
|
+
* @param guild - Resolvable thing from a guild
|
|
1880
1877
|
*/
|
|
1881
1878
|
/**
|
|
1882
1879
|
* Listen to DisTubeVoice events and handle the Queue
|
|
1883
|
-
*
|
|
1884
|
-
* @param
|
|
1880
|
+
*
|
|
1881
|
+
* @param queue - Queue
|
|
1885
1882
|
*/
|
|
1886
1883
|
__privateAdd(this, _voiceEventHandler);
|
|
1887
1884
|
/**
|
|
1888
1885
|
* Whether or not emit playSong event
|
|
1889
|
-
*
|
|
1890
|
-
* @
|
|
1891
|
-
* @returns {boolean}
|
|
1886
|
+
*
|
|
1887
|
+
* @param queue - Queue
|
|
1892
1888
|
*/
|
|
1893
1889
|
__privateAdd(this, _emitPlaySong);
|
|
1894
1890
|
/**
|
|
1895
1891
|
* Handle the queue when a Song finish
|
|
1896
|
-
*
|
|
1897
|
-
* @param
|
|
1898
|
-
* @returns {Promise<void>}
|
|
1892
|
+
*
|
|
1893
|
+
* @param queue - queue
|
|
1899
1894
|
*/
|
|
1900
1895
|
__privateAdd(this, _handleSongFinish);
|
|
1901
1896
|
/**
|
|
1902
1897
|
* Handle error while playing
|
|
1903
|
-
*
|
|
1904
|
-
* @param
|
|
1905
|
-
* @param
|
|
1898
|
+
*
|
|
1899
|
+
* @param queue - queue
|
|
1900
|
+
* @param error - error
|
|
1906
1901
|
*/
|
|
1907
1902
|
__privateAdd(this, _handlePlayingError);
|
|
1908
1903
|
}
|
|
1909
1904
|
/**
|
|
1910
1905
|
* Collection of {@link Queue}.
|
|
1911
|
-
* @name QueueManager#collection
|
|
1912
|
-
* @type {Discord.Collection<string, Queue>}
|
|
1913
1906
|
*/
|
|
1914
1907
|
/**
|
|
1915
1908
|
* Create a {@link Queue}
|
|
1916
|
-
*
|
|
1917
|
-
* @param
|
|
1918
|
-
* @param
|
|
1919
|
-
* @param
|
|
1920
|
-
*
|
|
1909
|
+
*
|
|
1910
|
+
* @param channel - A voice channel
|
|
1911
|
+
* @param song - First song
|
|
1912
|
+
* @param textChannel - Default text channel
|
|
1913
|
+
*
|
|
1914
|
+
* @returns Returns `true` if encounter an error
|
|
1921
1915
|
*/
|
|
1922
1916
|
async create(channel, song, textChannel) {
|
|
1923
1917
|
if (this.has(channel.guildId))
|
|
@@ -1929,7 +1923,7 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1929
1923
|
await voice.join();
|
|
1930
1924
|
__privateMethod(this, _voiceEventHandler, voiceEventHandler_fn).call(this, queue);
|
|
1931
1925
|
this.add(queue.id, queue);
|
|
1932
|
-
this.emit("initQueue"
|
|
1926
|
+
this.emit("initQueue" /* INIT_QUEUE */, queue);
|
|
1933
1927
|
const err = await this.playSong(queue);
|
|
1934
1928
|
return err || queue;
|
|
1935
1929
|
} finally {
|
|
@@ -1938,14 +1932,20 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1938
1932
|
}
|
|
1939
1933
|
/**
|
|
1940
1934
|
* Create a ytdl stream
|
|
1941
|
-
*
|
|
1942
|
-
* @
|
|
1935
|
+
*
|
|
1936
|
+
* @param queue - Queue
|
|
1943
1937
|
*/
|
|
1944
1938
|
createStream(queue) {
|
|
1945
1939
|
const song = queue.songs[0];
|
|
1946
1940
|
const { duration, source, streamURL } = song;
|
|
1947
1941
|
const streamOptions = {
|
|
1948
|
-
|
|
1942
|
+
ffmpeg: {
|
|
1943
|
+
path: this.options.ffmpegPath,
|
|
1944
|
+
args: {
|
|
1945
|
+
...this.options.ffmpegDefaultArgs,
|
|
1946
|
+
...queue.filters.ffmpegArgs
|
|
1947
|
+
}
|
|
1948
|
+
},
|
|
1949
1949
|
seek: duration ? queue.beginTime : void 0,
|
|
1950
1950
|
type: this.options.streamType
|
|
1951
1951
|
};
|
|
@@ -1955,9 +1955,10 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1955
1955
|
}
|
|
1956
1956
|
/**
|
|
1957
1957
|
* Play a song on voice connection
|
|
1958
|
-
*
|
|
1959
|
-
* @param
|
|
1960
|
-
*
|
|
1958
|
+
*
|
|
1959
|
+
* @param queue - The guild queue
|
|
1960
|
+
*
|
|
1961
|
+
* @returns error?
|
|
1961
1962
|
*/
|
|
1962
1963
|
async playSong(queue) {
|
|
1963
1964
|
if (!queue)
|
|
@@ -1974,6 +1975,7 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1974
1975
|
return true;
|
|
1975
1976
|
}
|
|
1976
1977
|
const stream = this.createStream(queue);
|
|
1978
|
+
stream.on("debug", (data) => this.emit("ffmpegDebug" /* FFMPEG_DEBUG */, `[${queue.id}]: ${data}`));
|
|
1977
1979
|
queue.voice.play(stream);
|
|
1978
1980
|
song.streamURL = stream.url;
|
|
1979
1981
|
return false;
|
|
@@ -1988,7 +1990,7 @@ voiceEventHandler_fn = /* @__PURE__ */ __name(function(queue) {
|
|
|
1988
1990
|
queue._listeners = {
|
|
1989
1991
|
disconnect: (error) => {
|
|
1990
1992
|
queue.remove();
|
|
1991
|
-
this.emit("disconnect"
|
|
1993
|
+
this.emit("disconnect" /* DISCONNECT */, queue);
|
|
1992
1994
|
if (error)
|
|
1993
1995
|
this.emitError(error, queue.textChannel);
|
|
1994
1996
|
},
|
|
@@ -2005,7 +2007,7 @@ emitPlaySong_fn = /* @__PURE__ */ __name(function(queue) {
|
|
|
2005
2007
|
}, "#emitPlaySong");
|
|
2006
2008
|
_handleSongFinish = new WeakSet();
|
|
2007
2009
|
handleSongFinish_fn = /* @__PURE__ */ __name(async function(queue) {
|
|
2008
|
-
this.emit("finishSong"
|
|
2010
|
+
this.emit("finishSong" /* FINISH_SONG */, queue, queue.songs[0]);
|
|
2009
2011
|
await queue._taskQueue.queuing();
|
|
2010
2012
|
try {
|
|
2011
2013
|
if (queue.stopped)
|
|
@@ -2023,14 +2025,14 @@ handleSongFinish_fn = /* @__PURE__ */ __name(async function(queue) {
|
|
|
2023
2025
|
try {
|
|
2024
2026
|
await queue.addRelatedSong();
|
|
2025
2027
|
} catch {
|
|
2026
|
-
this.emit("noRelated"
|
|
2028
|
+
this.emit("noRelated" /* NO_RELATED */, queue);
|
|
2027
2029
|
}
|
|
2028
2030
|
}
|
|
2029
2031
|
if (queue.songs.length <= 1) {
|
|
2030
2032
|
if (this.options.leaveOnFinish)
|
|
2031
2033
|
queue.voice.leave();
|
|
2032
2034
|
if (!queue.autoplay)
|
|
2033
|
-
this.emit("finish"
|
|
2035
|
+
this.emit("finish" /* FINISH */, queue);
|
|
2034
2036
|
queue.remove();
|
|
2035
2037
|
return;
|
|
2036
2038
|
}
|
|
@@ -2049,7 +2051,7 @@ handleSongFinish_fn = /* @__PURE__ */ __name(async function(queue) {
|
|
|
2049
2051
|
queue.beginTime = 0;
|
|
2050
2052
|
const err = await this.playSong(queue);
|
|
2051
2053
|
if (!err && emitPlaySong)
|
|
2052
|
-
this.emit("playSong"
|
|
2054
|
+
this.emit("playSong" /* PLAY_SONG */, queue, queue.songs[0]);
|
|
2053
2055
|
} finally {
|
|
2054
2056
|
queue._taskQueue.resolve();
|
|
2055
2057
|
}
|
|
@@ -2070,7 +2072,7 @@ Name: ${song.name}`;
|
|
|
2070
2072
|
queue.beginTime = 0;
|
|
2071
2073
|
this.playSong(queue).then((e) => {
|
|
2072
2074
|
if (!e)
|
|
2073
|
-
this.emit("playSong"
|
|
2075
|
+
this.emit("playSong" /* PLAY_SONG */, queue, queue.songs[0]);
|
|
2074
2076
|
});
|
|
2075
2077
|
} else {
|
|
2076
2078
|
queue.stop();
|
|
@@ -2084,10 +2086,11 @@ var _filters;
|
|
|
2084
2086
|
var _Queue = class _Queue extends DisTubeBase {
|
|
2085
2087
|
/**
|
|
2086
2088
|
* Create a queue for the guild
|
|
2087
|
-
*
|
|
2088
|
-
* @param
|
|
2089
|
-
* @param
|
|
2090
|
-
* @param
|
|
2089
|
+
*
|
|
2090
|
+
* @param distube - DisTube
|
|
2091
|
+
* @param voice - Voice connection
|
|
2092
|
+
* @param song - First song(s)
|
|
2093
|
+
* @param textChannel - Default text channel
|
|
2091
2094
|
*/
|
|
2092
2095
|
constructor(distube, voice, song, textChannel) {
|
|
2093
2096
|
super(distube);
|
|
@@ -2129,55 +2132,42 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2129
2132
|
}
|
|
2130
2133
|
/**
|
|
2131
2134
|
* The client user as a `GuildMember` of this queue's guild
|
|
2132
|
-
* @type {Discord.GuildMember?}
|
|
2133
2135
|
*/
|
|
2134
2136
|
get clientMember() {
|
|
2135
2137
|
return this.voice.channel.guild.members.me ?? void 0;
|
|
2136
2138
|
}
|
|
2137
2139
|
/**
|
|
2138
2140
|
* The filter manager of the queue
|
|
2139
|
-
* @type {FilterManager}
|
|
2140
|
-
* @readonly
|
|
2141
2141
|
*/
|
|
2142
2142
|
get filters() {
|
|
2143
2143
|
return __privateGet(this, _filters);
|
|
2144
2144
|
}
|
|
2145
2145
|
/**
|
|
2146
2146
|
* Formatted duration string.
|
|
2147
|
-
* @type {string}
|
|
2148
|
-
* @readonly
|
|
2149
2147
|
*/
|
|
2150
2148
|
get formattedDuration() {
|
|
2151
2149
|
return formatDuration(this.duration);
|
|
2152
2150
|
}
|
|
2153
2151
|
/**
|
|
2154
2152
|
* Queue's duration.
|
|
2155
|
-
* @type {number}
|
|
2156
|
-
* @readonly
|
|
2157
2153
|
*/
|
|
2158
2154
|
get duration() {
|
|
2159
2155
|
return this.songs.length ? this.songs.reduce((prev, next) => prev + next.duration, 0) : 0;
|
|
2160
2156
|
}
|
|
2161
2157
|
/**
|
|
2162
2158
|
* What time in the song is playing (in seconds).
|
|
2163
|
-
* @type {number}
|
|
2164
|
-
* @readonly
|
|
2165
2159
|
*/
|
|
2166
2160
|
get currentTime() {
|
|
2167
2161
|
return this.voice.playbackDuration + this.beginTime;
|
|
2168
2162
|
}
|
|
2169
2163
|
/**
|
|
2170
2164
|
* Formatted {@link Queue#currentTime} string.
|
|
2171
|
-
* @type {string}
|
|
2172
|
-
* @readonly
|
|
2173
2165
|
*/
|
|
2174
2166
|
get formattedCurrentTime() {
|
|
2175
2167
|
return formatDuration(this.currentTime);
|
|
2176
2168
|
}
|
|
2177
2169
|
/**
|
|
2178
2170
|
* The voice channel playing in.
|
|
2179
|
-
* @type {Discord.VoiceChannel|Discord.StageChannel|null}
|
|
2180
|
-
* @readonly
|
|
2181
2171
|
*/
|
|
2182
2172
|
get voiceChannel() {
|
|
2183
2173
|
return this.clientMember?.voice?.channel ?? null;
|
|
@@ -2189,12 +2179,12 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2189
2179
|
this.voice.volume = value;
|
|
2190
2180
|
}
|
|
2191
2181
|
/**
|
|
2192
|
-
* @
|
|
2193
|
-
*
|
|
2194
|
-
* @param
|
|
2195
|
-
* @param
|
|
2196
|
-
*
|
|
2197
|
-
* @returns
|
|
2182
|
+
* @throws {DisTubeError}
|
|
2183
|
+
*
|
|
2184
|
+
* @param song - Song to add
|
|
2185
|
+
* @param position - Position to add, \<= 0 to add to the end of the queue
|
|
2186
|
+
*
|
|
2187
|
+
* @returns The guild queue
|
|
2198
2188
|
*/
|
|
2199
2189
|
addToQueue(song, position = 0) {
|
|
2200
2190
|
if (!song || Array.isArray(song) && !song.length) {
|
|
@@ -2221,7 +2211,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2221
2211
|
}
|
|
2222
2212
|
/**
|
|
2223
2213
|
* Pause the guild stream
|
|
2224
|
-
*
|
|
2214
|
+
*
|
|
2215
|
+
* @returns The guild queue
|
|
2225
2216
|
*/
|
|
2226
2217
|
pause() {
|
|
2227
2218
|
if (this.paused)
|
|
@@ -2233,7 +2224,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2233
2224
|
}
|
|
2234
2225
|
/**
|
|
2235
2226
|
* Resume the guild stream
|
|
2236
|
-
*
|
|
2227
|
+
*
|
|
2228
|
+
* @returns The guild queue
|
|
2237
2229
|
*/
|
|
2238
2230
|
resume() {
|
|
2239
2231
|
if (this.playing)
|
|
@@ -2245,19 +2237,21 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2245
2237
|
}
|
|
2246
2238
|
/**
|
|
2247
2239
|
* Set the guild stream's volume
|
|
2248
|
-
*
|
|
2249
|
-
* @
|
|
2240
|
+
*
|
|
2241
|
+
* @param percent - The percentage of volume you want to set
|
|
2242
|
+
*
|
|
2243
|
+
* @returns The guild queue
|
|
2250
2244
|
*/
|
|
2251
2245
|
setVolume(percent) {
|
|
2252
2246
|
this.volume = percent;
|
|
2253
2247
|
return this;
|
|
2254
2248
|
}
|
|
2255
2249
|
/**
|
|
2256
|
-
* Skip the playing song if there is a next song in the queue.
|
|
2257
|
-
*
|
|
2258
|
-
*
|
|
2259
|
-
*
|
|
2260
|
-
* @
|
|
2250
|
+
* Skip the playing song if there is a next song in the queue. <info>If {@link
|
|
2251
|
+
* Queue#autoplay} is `true` and there is no up next song, DisTube will add and
|
|
2252
|
+
* play a related song.</info>
|
|
2253
|
+
*
|
|
2254
|
+
* @returns The song will skip to
|
|
2261
2255
|
*/
|
|
2262
2256
|
async skip() {
|
|
2263
2257
|
await this._taskQueue.queuing();
|
|
@@ -2278,8 +2272,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2278
2272
|
}
|
|
2279
2273
|
/**
|
|
2280
2274
|
* Play the previous song if exists
|
|
2281
|
-
*
|
|
2282
|
-
* @
|
|
2275
|
+
*
|
|
2276
|
+
* @returns The guild queue
|
|
2283
2277
|
*/
|
|
2284
2278
|
async previous() {
|
|
2285
2279
|
await this._taskQueue.queuing();
|
|
@@ -2299,7 +2293,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2299
2293
|
}
|
|
2300
2294
|
/**
|
|
2301
2295
|
* Shuffle the queue's songs
|
|
2302
|
-
*
|
|
2296
|
+
*
|
|
2297
|
+
* @returns The guild queue
|
|
2303
2298
|
*/
|
|
2304
2299
|
async shuffle() {
|
|
2305
2300
|
await this._taskQueue.queuing();
|
|
@@ -2318,12 +2313,13 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2318
2313
|
}
|
|
2319
2314
|
}
|
|
2320
2315
|
/**
|
|
2321
|
-
* Jump to the song position in the queue.
|
|
2322
|
-
*
|
|
2323
|
-
*
|
|
2324
|
-
*
|
|
2325
|
-
* @
|
|
2326
|
-
*
|
|
2316
|
+
* Jump to the song position in the queue. The next one is 1, 2,... The previous
|
|
2317
|
+
* one is -1, -2,...
|
|
2318
|
+
* if `num` is invalid number
|
|
2319
|
+
*
|
|
2320
|
+
* @param position - The song position to play
|
|
2321
|
+
*
|
|
2322
|
+
* @returns The new Song will be played
|
|
2327
2323
|
*/
|
|
2328
2324
|
async jump(position) {
|
|
2329
2325
|
await this._taskQueue.queuing();
|
|
@@ -2359,10 +2355,12 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2359
2355
|
}
|
|
2360
2356
|
}
|
|
2361
2357
|
/**
|
|
2362
|
-
* Set the repeat mode of the guild queue
|
|
2358
|
+
* Set the repeat mode of the guild queue.
|
|
2363
2359
|
* Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`
|
|
2364
|
-
*
|
|
2365
|
-
* @
|
|
2360
|
+
*
|
|
2361
|
+
* @param mode - The repeat modes (toggle if `undefined`)
|
|
2362
|
+
*
|
|
2363
|
+
* @returns The new repeat mode
|
|
2366
2364
|
*/
|
|
2367
2365
|
setRepeatMode(mode) {
|
|
2368
2366
|
if (mode !== void 0 && !Object.values(RepeatMode).includes(mode)) {
|
|
@@ -2378,8 +2376,10 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2378
2376
|
}
|
|
2379
2377
|
/**
|
|
2380
2378
|
* Set the playing time to another position
|
|
2381
|
-
*
|
|
2382
|
-
* @
|
|
2379
|
+
*
|
|
2380
|
+
* @param time - Time in seconds
|
|
2381
|
+
*
|
|
2382
|
+
* @returns The guild queue
|
|
2383
2383
|
*/
|
|
2384
2384
|
seek(time) {
|
|
2385
2385
|
if (typeof time !== "number")
|
|
@@ -2392,8 +2392,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2392
2392
|
}
|
|
2393
2393
|
/**
|
|
2394
2394
|
* Add a related song of the playing song to the queue
|
|
2395
|
-
*
|
|
2396
|
-
* @
|
|
2395
|
+
*
|
|
2396
|
+
* @returns The added song
|
|
2397
2397
|
*/
|
|
2398
2398
|
async addRelatedSong() {
|
|
2399
2399
|
if (!this.songs?.[0])
|
|
@@ -2426,9 +2426,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2426
2426
|
}
|
|
2427
2427
|
}
|
|
2428
2428
|
/**
|
|
2429
|
-
* Remove the queue from the manager
|
|
2430
|
-
*
|
|
2431
|
-
* @private
|
|
2429
|
+
* Remove the queue from the manager (This does not leave the voice channel even if
|
|
2430
|
+
* {@link DisTubeOptions | DisTubeOptions.leaveOnStop} is enabled)
|
|
2432
2431
|
*/
|
|
2433
2432
|
remove() {
|
|
2434
2433
|
this.stopped = true;
|
|
@@ -2440,11 +2439,12 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2440
2439
|
}
|
|
2441
2440
|
}
|
|
2442
2441
|
this.queues.remove(this.id);
|
|
2443
|
-
this.emit("deleteQueue"
|
|
2442
|
+
this.emit("deleteQueue" /* DELETE_QUEUE */, this);
|
|
2444
2443
|
}
|
|
2445
2444
|
/**
|
|
2446
2445
|
* Toggle autoplay mode
|
|
2447
|
-
*
|
|
2446
|
+
*
|
|
2447
|
+
* @returns Autoplay mode state
|
|
2448
2448
|
*/
|
|
2449
2449
|
toggleAutoplay() {
|
|
2450
2450
|
this.autoplay = !this.autoplay;
|
|
@@ -2465,70 +2465,59 @@ var _Plugin = class _Plugin {
|
|
|
2465
2465
|
}
|
|
2466
2466
|
/**
|
|
2467
2467
|
* Type of the plugin
|
|
2468
|
-
* @name Plugin#type
|
|
2469
|
-
* @type {PluginType}
|
|
2470
2468
|
*/
|
|
2471
2469
|
/**
|
|
2472
2470
|
* Emit an event to the {@link DisTube} class
|
|
2473
|
-
*
|
|
2474
|
-
* @param
|
|
2475
|
-
* @
|
|
2471
|
+
*
|
|
2472
|
+
* @param eventName - Event name
|
|
2473
|
+
* @param args - arguments
|
|
2476
2474
|
*/
|
|
2477
2475
|
emit(eventName, ...args) {
|
|
2478
2476
|
return this.distube.emit(eventName, ...args);
|
|
2479
2477
|
}
|
|
2480
2478
|
/**
|
|
2481
2479
|
* Emit error event to the {@link DisTube} class
|
|
2482
|
-
*
|
|
2483
|
-
* @param
|
|
2480
|
+
*
|
|
2481
|
+
* @param error - error
|
|
2482
|
+
* @param channel - Text channel where the error is encountered.
|
|
2484
2483
|
*/
|
|
2485
2484
|
emitError(error, channel) {
|
|
2486
2485
|
this.distube.emitError(error, channel);
|
|
2487
2486
|
}
|
|
2488
2487
|
/**
|
|
2489
2488
|
* The queue manager
|
|
2490
|
-
* @type {QueueManager}
|
|
2491
|
-
* @readonly
|
|
2492
2489
|
*/
|
|
2493
2490
|
get queues() {
|
|
2494
2491
|
return this.distube.queues;
|
|
2495
2492
|
}
|
|
2496
2493
|
/**
|
|
2497
2494
|
* The voice manager
|
|
2498
|
-
* @type {DisTubeVoiceManager}
|
|
2499
|
-
* @readonly
|
|
2500
2495
|
*/
|
|
2501
2496
|
get voices() {
|
|
2502
2497
|
return this.distube.voices;
|
|
2503
2498
|
}
|
|
2504
2499
|
/**
|
|
2505
2500
|
* Discord.js client
|
|
2506
|
-
* @type {Discord.Client}
|
|
2507
|
-
* @readonly
|
|
2508
2501
|
*/
|
|
2509
2502
|
get client() {
|
|
2510
2503
|
return this.distube.client;
|
|
2511
2504
|
}
|
|
2512
2505
|
/**
|
|
2513
2506
|
* DisTube options
|
|
2514
|
-
* @type {DisTubeOptions}
|
|
2515
|
-
* @readonly
|
|
2516
2507
|
*/
|
|
2517
2508
|
get options() {
|
|
2518
2509
|
return this.distube.options;
|
|
2519
2510
|
}
|
|
2520
2511
|
/**
|
|
2521
2512
|
* DisTube handler
|
|
2522
|
-
* @type {DisTubeHandler}
|
|
2523
|
-
* @readonly
|
|
2524
2513
|
*/
|
|
2525
2514
|
get handler() {
|
|
2526
2515
|
return this.distube.handler;
|
|
2527
2516
|
}
|
|
2528
2517
|
/**
|
|
2529
2518
|
* Check if the string is working with this plugin
|
|
2530
|
-
*
|
|
2531
|
-
* @
|
|
2519
|
+
*
|
|
2520
|
+
* @param _string - Input string
|
|
2532
2521
|
*/
|
|
2533
2522
|
validate(_string) {
|
|
2534
2523
|
return false;
|
|
@@ -2536,17 +2525,18 @@ var _Plugin = class _Plugin {
|
|
|
2536
2525
|
/**
|
|
2537
2526
|
* Get the stream url from {@link Song#url}. Returns {@link Song#url} by default.
|
|
2538
2527
|
* Not needed if the plugin plays song from YouTube.
|
|
2539
|
-
*
|
|
2540
|
-
* @
|
|
2528
|
+
*
|
|
2529
|
+
* @param url - Input url
|
|
2541
2530
|
*/
|
|
2542
2531
|
getStreamURL(url) {
|
|
2543
2532
|
return url;
|
|
2544
2533
|
}
|
|
2545
2534
|
/**
|
|
2546
|
-
* Get related songs from a supported url. {@link Song#member} should be
|
|
2547
|
-
* Not needed to add {@link Song#related} because it will be added
|
|
2548
|
-
*
|
|
2549
|
-
*
|
|
2535
|
+
* Get related songs from a supported url. {@link Song#member} should be
|
|
2536
|
+
* `undefined`. Not needed to add {@link Song#related} because it will be added
|
|
2537
|
+
* with this function later.
|
|
2538
|
+
*
|
|
2539
|
+
* @param _url - Input url
|
|
2550
2540
|
*/
|
|
2551
2541
|
getRelatedSongs(_url) {
|
|
2552
2542
|
return [];
|
|
@@ -2763,10 +2753,10 @@ var DirectLinkPlugin = _DirectLinkPlugin;
|
|
|
2763
2753
|
|
|
2764
2754
|
// src/DisTube.ts
|
|
2765
2755
|
var import_ytsr = __toESM(require("@distube/ytsr"));
|
|
2766
|
-
var
|
|
2756
|
+
var import_tiny_typed_emitter3 = require("tiny-typed-emitter");
|
|
2767
2757
|
var { version } = require_package();
|
|
2768
2758
|
var _getQueue, getQueue_fn;
|
|
2769
|
-
var _DisTube = class _DisTube extends
|
|
2759
|
+
var _DisTube = class _DisTube extends import_tiny_typed_emitter3.TypedEmitter {
|
|
2770
2760
|
constructor(client, otp = {}) {
|
|
2771
2761
|
super();
|
|
2772
2762
|
__privateAdd(this, _getQueue);
|
|
@@ -2799,21 +2789,16 @@ var _DisTube = class _DisTube extends import_tiny_typed_emitter2.TypedEmitter {
|
|
|
2799
2789
|
}
|
|
2800
2790
|
/**
|
|
2801
2791
|
* DisTube version
|
|
2802
|
-
* @type {string}
|
|
2803
2792
|
*/
|
|
2804
2793
|
get version() {
|
|
2805
2794
|
return version;
|
|
2806
2795
|
}
|
|
2807
2796
|
/**
|
|
2808
|
-
* Play / add a song or playlist from url. Search and play a song if it is not a
|
|
2797
|
+
* Play / add a song or playlist from url. Search and play a song if it is not a
|
|
2798
|
+
* valid url.
|
|
2809
2799
|
*
|
|
2810
|
-
* @param {Discord.BaseGuildVoiceChannel} voiceChannel The channel will be joined if the bot isn't in any channels,
|
|
2811
|
-
* the bot will be moved to this channel if {@link DisTubeOptions}.joinNewVoiceChannel is `true`
|
|
2812
|
-
* @param {string|Song|SearchResult|Playlist} song URL | Search string |
|
|
2813
|
-
* {@link Song} | {@link SearchResult} | {@link Playlist}
|
|
2814
|
-
* @param {PlayOptions} [options] Optional options
|
|
2815
|
-
* @throws {DisTubeError}
|
|
2816
2800
|
* @example
|
|
2801
|
+
* ```ts
|
|
2817
2802
|
* client.on('message', (message) => {
|
|
2818
2803
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
2819
2804
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -2825,7 +2810,14 @@ var _DisTube = class _DisTube extends import_tiny_typed_emitter2.TypedEmitter {
|
|
|
2825
2810
|
* message
|
|
2826
2811
|
* });
|
|
2827
2812
|
* });
|
|
2828
|
-
*
|
|
2813
|
+
* ```ts
|
|
2814
|
+
*
|
|
2815
|
+
* @throws {@link DisTubeError}
|
|
2816
|
+
*
|
|
2817
|
+
* @param voiceChannel - The channel will be joined if the bot isn't in any channels, the bot will be
|
|
2818
|
+
* moved to this channel if {@link DisTubeOptions}.joinNewVoiceChannel is `true`
|
|
2819
|
+
* @param song - URL | Search string | {@link Song} | {@link SearchResult} | {@link Playlist}
|
|
2820
|
+
* @param options - Optional options
|
|
2829
2821
|
*/
|
|
2830
2822
|
async play(voiceChannel, song, options = {}) {
|
|
2831
2823
|
if (!isSupportedVoiceChannel(voiceChannel)) {
|
|
@@ -2895,10 +2887,9 @@ ${e.message}`;
|
|
|
2895
2887
|
}
|
|
2896
2888
|
/**
|
|
2897
2889
|
* Create a custom playlist
|
|
2898
|
-
*
|
|
2899
|
-
* @param {Array<string|Song|SearchResult>} songs Array of url, Song or SearchResult
|
|
2900
|
-
* @param {CustomPlaylistOptions} [options] Optional options
|
|
2890
|
+
*
|
|
2901
2891
|
* @example
|
|
2892
|
+
* ```ts
|
|
2902
2893
|
* const songs = ["https://www.youtube.com/watch?v=xxx", "https://www.youtube.com/watch?v=yyy"];
|
|
2903
2894
|
* const playlist = await distube.createCustomPlaylist(songs, {
|
|
2904
2895
|
* member: message.member,
|
|
@@ -2906,6 +2897,10 @@ ${e.message}`;
|
|
|
2906
2897
|
* parallel: true
|
|
2907
2898
|
* });
|
|
2908
2899
|
* distube.play(voiceChannel, playlist, { ... });
|
|
2900
|
+
* ```ts
|
|
2901
|
+
*
|
|
2902
|
+
* @param songs - Array of url, Song or SearchResult
|
|
2903
|
+
* @param options - Optional options
|
|
2909
2904
|
*/
|
|
2910
2905
|
async createCustomPlaylist(songs, options = {}) {
|
|
2911
2906
|
const { member, properties, parallel, metadata } = { parallel: true, ...options };
|
|
@@ -2926,13 +2921,14 @@ ${e.message}`;
|
|
|
2926
2921
|
const promises = filteredSongs.map(
|
|
2927
2922
|
(song) => this.handler.resolve(song, { member, metadata }).catch(() => void 0)
|
|
2928
2923
|
);
|
|
2929
|
-
resolvedSongs = (await Promise.all(promises)).filter((s) =>
|
|
2924
|
+
resolvedSongs = (await Promise.all(promises)).filter((s) => s instanceof Song);
|
|
2930
2925
|
} else {
|
|
2931
|
-
|
|
2926
|
+
resolvedSongs = [];
|
|
2932
2927
|
for (const song of filteredSongs) {
|
|
2933
|
-
resolved
|
|
2928
|
+
const resolved = await this.handler.resolve(song, { member, metadata }).catch(() => void 0);
|
|
2929
|
+
if (resolved instanceof Song)
|
|
2930
|
+
resolvedSongs.push(resolved);
|
|
2934
2931
|
}
|
|
2935
|
-
resolvedSongs = resolved.filter((s) => Boolean(s));
|
|
2936
2932
|
}
|
|
2937
2933
|
return new Playlist(resolvedSongs, { member, properties, metadata });
|
|
2938
2934
|
}
|
|
@@ -2940,13 +2936,13 @@ ${e.message}`;
|
|
|
2940
2936
|
* Search for a song. You can customize how user answers instead of send a number.
|
|
2941
2937
|
* Then use {@link DisTube#play} to play it.
|
|
2942
2938
|
*
|
|
2943
|
-
* @param
|
|
2944
|
-
* @param
|
|
2945
|
-
* @param
|
|
2946
|
-
* @param
|
|
2947
|
-
* @param
|
|
2948
|
-
*
|
|
2949
|
-
* @returns
|
|
2939
|
+
* @param string - The string search for
|
|
2940
|
+
* @param options - Search options
|
|
2941
|
+
* @param options.limit - Limit the results
|
|
2942
|
+
* @param options.type - Type of results (`video` or `playlist`).
|
|
2943
|
+
* @param options.safeSearch - Whether or not use safe search (YouTube restricted mode)
|
|
2944
|
+
*
|
|
2945
|
+
* @returns Array of results
|
|
2950
2946
|
*/
|
|
2951
2947
|
async search(string, options = {}) {
|
|
2952
2948
|
const opts = { type: "video" /* VIDEO */, limit: 10, safeSearch: false, ...options };
|
|
@@ -2979,10 +2975,9 @@ ${e.message}`;
|
|
|
2979
2975
|
}
|
|
2980
2976
|
/**
|
|
2981
2977
|
* Get the guild queue
|
|
2982
|
-
*
|
|
2983
|
-
* @returns {Queue?}
|
|
2984
|
-
* @throws {Error}
|
|
2978
|
+
*
|
|
2985
2979
|
* @example
|
|
2980
|
+
* ```ts
|
|
2986
2981
|
* client.on('message', (message) => {
|
|
2987
2982
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
2988
2983
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -2994,34 +2989,38 @@ ${e.message}`;
|
|
|
2994
2989
|
* ).join("\n"));
|
|
2995
2990
|
* }
|
|
2996
2991
|
* });
|
|
2992
|
+
* ```ts
|
|
2993
|
+
*
|
|
2994
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
2997
2995
|
*/
|
|
2998
2996
|
getQueue(guild) {
|
|
2999
2997
|
return this.queues.get(guild);
|
|
3000
2998
|
}
|
|
3001
2999
|
/**
|
|
3002
3000
|
* Pause the guild stream
|
|
3003
|
-
*
|
|
3004
|
-
* @
|
|
3005
|
-
*
|
|
3001
|
+
*
|
|
3002
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3003
|
+
*
|
|
3004
|
+
* @returns The guild queue
|
|
3006
3005
|
*/
|
|
3007
3006
|
pause(guild) {
|
|
3008
3007
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).pause();
|
|
3009
3008
|
}
|
|
3010
3009
|
/**
|
|
3011
3010
|
* Resume the guild stream
|
|
3012
|
-
*
|
|
3013
|
-
* @
|
|
3014
|
-
*
|
|
3011
|
+
*
|
|
3012
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3013
|
+
*
|
|
3014
|
+
* @returns The guild queue
|
|
3015
3015
|
*/
|
|
3016
3016
|
resume(guild) {
|
|
3017
3017
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).resume();
|
|
3018
3018
|
}
|
|
3019
3019
|
/**
|
|
3020
3020
|
* Stop the guild stream
|
|
3021
|
-
*
|
|
3022
|
-
* @returns {Promise<void>}
|
|
3023
|
-
* @throws {Error}
|
|
3021
|
+
*
|
|
3024
3022
|
* @example
|
|
3023
|
+
* ```ts
|
|
3025
3024
|
* client.on('message', (message) => {
|
|
3026
3025
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3027
3026
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3031,17 +3030,18 @@ ${e.message}`;
|
|
|
3031
3030
|
* message.channel.send("Stopped the queue!");
|
|
3032
3031
|
* }
|
|
3033
3032
|
* });
|
|
3033
|
+
* ```ts
|
|
3034
|
+
*
|
|
3035
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3034
3036
|
*/
|
|
3035
3037
|
stop(guild) {
|
|
3036
3038
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).stop();
|
|
3037
3039
|
}
|
|
3038
3040
|
/**
|
|
3039
3041
|
* Set the guild stream's volume
|
|
3040
|
-
*
|
|
3041
|
-
* @param {number} percent The percentage of volume you want to set
|
|
3042
|
-
* @returns {Queue} The guild queue
|
|
3043
|
-
* @throws {Error}
|
|
3042
|
+
*
|
|
3044
3043
|
* @example
|
|
3044
|
+
* ```ts
|
|
3045
3045
|
* client.on('message', (message) => {
|
|
3046
3046
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3047
3047
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3049,18 +3049,23 @@ ${e.message}`;
|
|
|
3049
3049
|
* if (command == "volume")
|
|
3050
3050
|
* distube.setVolume(message, Number(args[0]));
|
|
3051
3051
|
* });
|
|
3052
|
+
* ```ts
|
|
3053
|
+
*
|
|
3054
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3055
|
+
* @param percent - The percentage of volume you want to set
|
|
3056
|
+
*
|
|
3057
|
+
* @returns The guild queue
|
|
3052
3058
|
*/
|
|
3053
3059
|
setVolume(guild, percent) {
|
|
3054
3060
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).setVolume(percent);
|
|
3055
3061
|
}
|
|
3056
3062
|
/**
|
|
3057
|
-
* Skip the playing song if there is a next song in the queue.
|
|
3058
|
-
*
|
|
3059
|
-
*
|
|
3060
|
-
*
|
|
3061
|
-
* @returns {Promise<Song>} The new Song will be played
|
|
3062
|
-
* @throws {Error}
|
|
3063
|
+
* Skip the playing song if there is a next song in the queue. <info>If {@link
|
|
3064
|
+
* Queue#autoplay} is `true` and there is no up next song, DisTube will add and
|
|
3065
|
+
* play a related song.</info>
|
|
3066
|
+
*
|
|
3063
3067
|
* @example
|
|
3068
|
+
* ```ts
|
|
3064
3069
|
* client.on('message', (message) => {
|
|
3065
3070
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3066
3071
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3068,16 +3073,20 @@ ${e.message}`;
|
|
|
3068
3073
|
* if (command == "skip")
|
|
3069
3074
|
* distube.skip(message);
|
|
3070
3075
|
* });
|
|
3076
|
+
* ```ts
|
|
3077
|
+
*
|
|
3078
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3079
|
+
*
|
|
3080
|
+
* @returns The new Song will be played
|
|
3071
3081
|
*/
|
|
3072
3082
|
skip(guild) {
|
|
3073
3083
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).skip();
|
|
3074
3084
|
}
|
|
3075
3085
|
/**
|
|
3076
3086
|
* Play the previous song
|
|
3077
|
-
*
|
|
3078
|
-
* @returns {Promise<Song>} The new Song will be played
|
|
3079
|
-
* @throws {Error}
|
|
3087
|
+
*
|
|
3080
3088
|
* @example
|
|
3089
|
+
* ```ts
|
|
3081
3090
|
* client.on('message', (message) => {
|
|
3082
3091
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3083
3092
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3085,15 +3094,20 @@ ${e.message}`;
|
|
|
3085
3094
|
* if (command == "previous")
|
|
3086
3095
|
* distube.previous(message);
|
|
3087
3096
|
* });
|
|
3097
|
+
* ```ts
|
|
3098
|
+
*
|
|
3099
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3100
|
+
*
|
|
3101
|
+
* @returns The new Song will be played
|
|
3088
3102
|
*/
|
|
3089
3103
|
previous(guild) {
|
|
3090
3104
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).previous();
|
|
3091
3105
|
}
|
|
3092
3106
|
/**
|
|
3093
3107
|
* Shuffle the guild queue songs
|
|
3094
|
-
*
|
|
3095
|
-
* @returns {Promise<Queue>} The guild queue
|
|
3108
|
+
*
|
|
3096
3109
|
* @example
|
|
3110
|
+
* ```ts
|
|
3097
3111
|
* client.on('message', (message) => {
|
|
3098
3112
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3099
3113
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3101,19 +3115,21 @@ ${e.message}`;
|
|
|
3101
3115
|
* if (command == "shuffle")
|
|
3102
3116
|
* distube.shuffle(message);
|
|
3103
3117
|
* });
|
|
3118
|
+
* ```ts
|
|
3119
|
+
*
|
|
3120
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3121
|
+
*
|
|
3122
|
+
* @returns The guild queue
|
|
3104
3123
|
*/
|
|
3105
3124
|
shuffle(guild) {
|
|
3106
3125
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).shuffle();
|
|
3107
3126
|
}
|
|
3108
3127
|
/**
|
|
3109
|
-
* Jump to the song number in the queue.
|
|
3110
|
-
*
|
|
3111
|
-
*
|
|
3112
|
-
* @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}
|
|
3113
|
-
* @param {number} num The song number to play
|
|
3114
|
-
* @returns {Promise<Song>} The new Song will be played
|
|
3115
|
-
* @throws {Error} if `num` is invalid number (0 < num < {@link Queue#songs}.length)
|
|
3128
|
+
* Jump to the song number in the queue. The next one is 1, 2,... The previous one
|
|
3129
|
+
* is -1, -2,...
|
|
3130
|
+
*
|
|
3116
3131
|
* @example
|
|
3132
|
+
* ```ts
|
|
3117
3133
|
* client.on('message', (message) => {
|
|
3118
3134
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3119
3135
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3122,17 +3138,22 @@ ${e.message}`;
|
|
|
3122
3138
|
* distube.jump(message, parseInt(args[0]))
|
|
3123
3139
|
* .catch(err => message.channel.send("Invalid song number."));
|
|
3124
3140
|
* });
|
|
3141
|
+
* ```ts
|
|
3142
|
+
*
|
|
3143
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3144
|
+
* @param num - The song number to play
|
|
3145
|
+
*
|
|
3146
|
+
* @returns The new Song will be played
|
|
3125
3147
|
*/
|
|
3126
3148
|
jump(guild, num) {
|
|
3127
3149
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).jump(num);
|
|
3128
3150
|
}
|
|
3129
3151
|
/**
|
|
3130
|
-
* Set the repeat mode of the guild queue
|
|
3152
|
+
* Set the repeat mode of the guild queue.
|
|
3131
3153
|
* Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`
|
|
3132
|
-
*
|
|
3133
|
-
* @param {RepeatMode?} [mode] The repeat modes (toggle if `undefined`)
|
|
3134
|
-
* @returns {RepeatMode} The new repeat mode
|
|
3154
|
+
*
|
|
3135
3155
|
* @example
|
|
3156
|
+
* ```ts
|
|
3136
3157
|
* client.on('message', (message) => {
|
|
3137
3158
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3138
3159
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3143,7 +3164,9 @@ ${e.message}`;
|
|
|
3143
3164
|
* message.channel.send("Set repeat mode to `" + mode + "`");
|
|
3144
3165
|
* }
|
|
3145
3166
|
* });
|
|
3167
|
+
* ```ts
|
|
3146
3168
|
* @example
|
|
3169
|
+
* ```ts
|
|
3147
3170
|
* const { RepeatMode } = require("distube");
|
|
3148
3171
|
* let mode;
|
|
3149
3172
|
* switch(distube.setRepeatMode(message, parseInt(args[0]))) {
|
|
@@ -3158,16 +3181,21 @@ ${e.message}`;
|
|
|
3158
3181
|
* break;
|
|
3159
3182
|
* }
|
|
3160
3183
|
* message.channel.send("Set repeat mode to `" + mode + "`");
|
|
3184
|
+
* ```ts
|
|
3185
|
+
*
|
|
3186
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3187
|
+
* @param mode - The repeat modes (toggle if `undefined`)
|
|
3188
|
+
*
|
|
3189
|
+
* @returns The new repeat mode
|
|
3161
3190
|
*/
|
|
3162
3191
|
setRepeatMode(guild, mode) {
|
|
3163
3192
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).setRepeatMode(mode);
|
|
3164
3193
|
}
|
|
3165
3194
|
/**
|
|
3166
3195
|
* Toggle autoplay mode
|
|
3167
|
-
*
|
|
3168
|
-
* @returns {boolean} Autoplay mode state
|
|
3169
|
-
* @throws {Error}
|
|
3196
|
+
*
|
|
3170
3197
|
* @example
|
|
3198
|
+
* ```ts
|
|
3171
3199
|
* client.on('message', (message) => {
|
|
3172
3200
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3173
3201
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3177,6 +3205,11 @@ ${e.message}`;
|
|
|
3177
3205
|
* message.channel.send("Set autoplay mode to `" + (mode ? "On" : "Off") + "`");
|
|
3178
3206
|
* }
|
|
3179
3207
|
* });
|
|
3208
|
+
* ```ts
|
|
3209
|
+
*
|
|
3210
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3211
|
+
*
|
|
3212
|
+
* @returns Autoplay mode state
|
|
3180
3213
|
*/
|
|
3181
3214
|
toggleAutoplay(guild) {
|
|
3182
3215
|
const queue = __privateMethod(this, _getQueue, getQueue_fn).call(this, guild);
|
|
@@ -3185,18 +3218,19 @@ ${e.message}`;
|
|
|
3185
3218
|
}
|
|
3186
3219
|
/**
|
|
3187
3220
|
* Add related song to the queue
|
|
3188
|
-
*
|
|
3189
|
-
* @
|
|
3221
|
+
*
|
|
3222
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3223
|
+
*
|
|
3224
|
+
* @returns The guild queue
|
|
3190
3225
|
*/
|
|
3191
3226
|
addRelatedSong(guild) {
|
|
3192
3227
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).addRelatedSong();
|
|
3193
3228
|
}
|
|
3194
3229
|
/**
|
|
3195
3230
|
* Set the playing time to another position
|
|
3196
|
-
*
|
|
3197
|
-
* @param {number} time Time in seconds
|
|
3198
|
-
* @returns {Queue} Seeked queue
|
|
3231
|
+
*
|
|
3199
3232
|
* @example
|
|
3233
|
+
* ```ts
|
|
3200
3234
|
* client.on('message', message => {
|
|
3201
3235
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3202
3236
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3204,19 +3238,25 @@ ${e.message}`;
|
|
|
3204
3238
|
* if (command = 'seek')
|
|
3205
3239
|
* distube.seek(message, Number(args[0]));
|
|
3206
3240
|
* });
|
|
3241
|
+
* ```ts
|
|
3242
|
+
*
|
|
3243
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3244
|
+
* @param time - Time in seconds
|
|
3245
|
+
*
|
|
3246
|
+
* @returns Seeked queue
|
|
3207
3247
|
*/
|
|
3208
3248
|
seek(guild, time) {
|
|
3209
3249
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).seek(time);
|
|
3210
3250
|
}
|
|
3211
3251
|
/**
|
|
3212
3252
|
* Emit error event
|
|
3213
|
-
*
|
|
3214
|
-
* @param
|
|
3215
|
-
* @
|
|
3253
|
+
*
|
|
3254
|
+
* @param error - error
|
|
3255
|
+
* @param channel - Text channel where the error is encountered.
|
|
3216
3256
|
*/
|
|
3217
3257
|
emitError(error, channel) {
|
|
3218
|
-
if (this.listeners("error").length) {
|
|
3219
|
-
this.emit("error"
|
|
3258
|
+
if (this.listeners("error" /* ERROR */).length) {
|
|
3259
|
+
this.emit("error" /* ERROR */, channel, error);
|
|
3220
3260
|
} else {
|
|
3221
3261
|
console.error(error);
|
|
3222
3262
|
console.warn("Unhandled 'error' event.");
|