distube 4.1.0 → 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 +788 -520
- package/dist/index.js +505 -469
- package/dist/index.js.map +1 -1
- package/package.json +44 -68
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.
|
|
128
|
-
"@distube/ytpl": "^1.1
|
|
129
|
-
"@distube/ytsr": "^
|
|
130
|
-
"prism-media": "npm:@distube/prism-media@latest",
|
|
118
|
+
"@distube/ytdl-core": "^4.13.3",
|
|
119
|
+
"@distube/ytpl": "^1.2.1",
|
|
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/
|
|
149
|
-
"@
|
|
150
|
-
"@typescript-eslint/
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
|
|
154
|
-
eslint: "^
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
"eslint-plugin-deprecation": "^1.5.0",
|
|
158
|
-
"eslint-plugin-jsdoc": "^46.5.1",
|
|
159
|
-
husky: "^8.0.3",
|
|
160
|
-
jest: "^29.6.4",
|
|
161
|
-
"jsdoc-babel": "^0.5.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",
|
|
138
|
+
"@types/tough-cookie": "^4.0.5",
|
|
139
|
+
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
|
140
|
+
"@typescript-eslint/parser": "^7.7.0",
|
|
141
|
+
"babel-jest": "^29.7.0",
|
|
142
|
+
"discord.js": "^14.14.1",
|
|
143
|
+
eslint: "^8.57.0",
|
|
144
|
+
"eslint-config-distube": "^1.7.0",
|
|
145
|
+
husky: "^9.0.11",
|
|
146
|
+
jest: "^29.7.0",
|
|
162
147
|
"nano-staged": "^0.8.0",
|
|
163
|
-
"npm-check-updates": "^16.13.2",
|
|
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,90 +1080,119 @@ __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
|
-
var chooseBestVideoFormat = /* @__PURE__ */ __name((formats, isLive
|
|
1120
|
-
|
|
1121
|
-
if (isLive)
|
|
1122
|
-
filter = /* @__PURE__ */ __name((format) => format.hasAudio && format.isHLS, "filter");
|
|
1123
|
-
formats = formats.filter(filter).sort((a, b) => Number(b.audioBitrate) - Number(a.audioBitrate) || Number(a.bitrate) - Number(b.bitrate));
|
|
1124
|
-
return formats.find((format) => !format.hasVideo) || formats.sort((a, b) => Number(a.bitrate) - Number(b.bitrate))[0];
|
|
1125
|
-
}, "chooseBestVideoFormat");
|
|
1126
|
-
var _DisTubeStream = class _DisTubeStream {
|
|
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");
|
|
1088
|
+
var _DisTubeStream = class _DisTubeStream extends import_tiny_typed_emitter2.TypedEmitter {
|
|
1127
1089
|
/**
|
|
1128
1090
|
* Create a DisTubeStream to play with {@link DisTubeVoice}
|
|
1129
|
-
*
|
|
1130
|
-
* @param
|
|
1131
|
-
* @
|
|
1091
|
+
*
|
|
1092
|
+
* @param url - Stream URL
|
|
1093
|
+
* @param options - Stream options
|
|
1132
1094
|
*/
|
|
1133
|
-
constructor(url,
|
|
1134
|
-
|
|
1095
|
+
constructor(url, { ffmpeg, seek, type }) {
|
|
1096
|
+
super();
|
|
1097
|
+
__publicField(this, "killed", false);
|
|
1098
|
+
__publicField(this, "process");
|
|
1135
1099
|
__publicField(this, "stream");
|
|
1100
|
+
__publicField(this, "type");
|
|
1136
1101
|
__publicField(this, "url");
|
|
1137
1102
|
this.url = url;
|
|
1138
|
-
this.type = !
|
|
1139
|
-
const
|
|
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
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
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
|
+
if (song.source !== "youtube")
|
|
1172
|
+
throw new DisTubeError("INVALID_TYPE", "youtube", song.source, "Song#source");
|
|
1173
|
+
if (!song.formats?.length)
|
|
1178
1174
|
throw new DisTubeError("UNAVAILABLE_VIDEO");
|
|
1179
1175
|
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
1180
1176
|
throw new DisTubeError("INVALID_TYPE", "object", options, "options");
|
|
1181
1177
|
}
|
|
1182
|
-
const bestFormat = chooseBestVideoFormat(
|
|
1178
|
+
const bestFormat = chooseBestVideoFormat(song);
|
|
1183
1179
|
if (!bestFormat)
|
|
1184
1180
|
throw new DisTubeError("UNPLAYABLE_FORMATS");
|
|
1185
1181
|
return new _DisTubeStream(bestFormat.url, options);
|
|
1186
1182
|
}
|
|
1187
1183
|
/**
|
|
1188
1184
|
* Create a stream from a stream url
|
|
1189
|
-
*
|
|
1190
|
-
* @param
|
|
1191
|
-
* @
|
|
1192
|
-
* @private
|
|
1185
|
+
*
|
|
1186
|
+
* @param url - stream url
|
|
1187
|
+
* @param options - options
|
|
1193
1188
|
*/
|
|
1194
|
-
static DirectLink(url, options
|
|
1195
|
-
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
1196
|
-
throw new DisTubeError("INVALID_TYPE", "object", options, "options");
|
|
1197
|
-
}
|
|
1189
|
+
static DirectLink(url, options) {
|
|
1198
1190
|
if (typeof url !== "string" || !isURL(url)) {
|
|
1199
1191
|
throw new DisTubeError("INVALID_TYPE", "an URL", url);
|
|
1200
1192
|
}
|
|
1193
|
+
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
1194
|
+
throw new DisTubeError("INVALID_TYPE", "object", options, "options");
|
|
1195
|
+
}
|
|
1201
1196
|
return new _DisTubeStream(url, options);
|
|
1202
1197
|
}
|
|
1203
1198
|
};
|
|
@@ -1237,7 +1232,7 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1237
1232
|
delete queue._emptyTimeout;
|
|
1238
1233
|
if (isVoiceChannelEmpty(oldState)) {
|
|
1239
1234
|
queue.voice.leave();
|
|
1240
|
-
this.emit("empty"
|
|
1235
|
+
this.emit("empty" /* EMPTY */, queue);
|
|
1241
1236
|
if (queue.stopped)
|
|
1242
1237
|
queue.remove();
|
|
1243
1238
|
}
|
|
@@ -1271,9 +1266,8 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1271
1266
|
return jar.getCookieStringSync("https://www.youtube.com");
|
|
1272
1267
|
}
|
|
1273
1268
|
/**
|
|
1274
|
-
* @param
|
|
1275
|
-
* @param
|
|
1276
|
-
* @returns {Promise<ytdl.videoInfo>}
|
|
1269
|
+
* @param url - url
|
|
1270
|
+
* @param basic - getBasicInfo?
|
|
1277
1271
|
*/
|
|
1278
1272
|
getYouTubeInfo(url, basic = false) {
|
|
1279
1273
|
if (basic)
|
|
@@ -1282,10 +1276,13 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1282
1276
|
}
|
|
1283
1277
|
/**
|
|
1284
1278
|
* Resolve a url or a supported object to a {@link Song} or {@link Playlist}
|
|
1285
|
-
*
|
|
1286
|
-
* @
|
|
1287
|
-
*
|
|
1288
|
-
* @
|
|
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
|
|
1289
1286
|
*/
|
|
1290
1287
|
async resolve(song, options = {}) {
|
|
1291
1288
|
if (song instanceof Song || song instanceof Playlist) {
|
|
@@ -1319,9 +1316,9 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1319
1316
|
}
|
|
1320
1317
|
/**
|
|
1321
1318
|
* Resolve Song[] or YouTube playlist url to a Playlist
|
|
1322
|
-
*
|
|
1323
|
-
* @param
|
|
1324
|
-
* @
|
|
1319
|
+
*
|
|
1320
|
+
* @param playlist - Resolvable playlist
|
|
1321
|
+
* @param options - Optional options
|
|
1325
1322
|
*/
|
|
1326
1323
|
async resolvePlaylist(playlist, options = {}) {
|
|
1327
1324
|
const { member, source, metadata } = { source: "youtube", ...options };
|
|
@@ -1350,11 +1347,14 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1350
1347
|
return new Playlist(playlist, { member, properties: { source }, metadata });
|
|
1351
1348
|
}
|
|
1352
1349
|
/**
|
|
1353
|
-
* Search for a song, fire {@link DisTube#
|
|
1354
|
-
*
|
|
1355
|
-
* @
|
|
1356
|
-
*
|
|
1357
|
-
* @
|
|
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
|
|
1358
1358
|
*/
|
|
1359
1359
|
async searchSong(message, query) {
|
|
1360
1360
|
if (!isMessageInstance(message))
|
|
@@ -1368,7 +1368,7 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1368
1368
|
limit,
|
|
1369
1369
|
safeSearch: this.options.nsfw ? false : !isNsfwChannel(message.channel)
|
|
1370
1370
|
}).catch(() => {
|
|
1371
|
-
if (!this.emit("searchNoResult"
|
|
1371
|
+
if (!this.emit("searchNoResult" /* SEARCH_NO_RESULT */, message, query)) {
|
|
1372
1372
|
console.warn("searchNoResult event does not have any listeners! Emits `error` event instead.");
|
|
1373
1373
|
throw new DisTubeError("NO_RESULT");
|
|
1374
1374
|
}
|
|
@@ -1380,13 +1380,16 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1380
1380
|
/**
|
|
1381
1381
|
* Create a message collector for selecting search results.
|
|
1382
1382
|
*
|
|
1383
|
-
* Needed events: {@link DisTube#
|
|
1384
|
-
* {@link DisTube#
|
|
1385
|
-
*
|
|
1386
|
-
* @
|
|
1387
|
-
*
|
|
1388
|
-
* @
|
|
1389
|
-
* @
|
|
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
|
|
1390
1393
|
*/
|
|
1391
1394
|
async createSearchMessageCollector(message, results, query) {
|
|
1392
1395
|
if (!isMessageInstance(message))
|
|
@@ -1396,11 +1399,11 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1396
1399
|
}
|
|
1397
1400
|
if (this.options.searchSongs > 1) {
|
|
1398
1401
|
const searchEvents = [
|
|
1399
|
-
"searchNoResult"
|
|
1400
|
-
"searchResult"
|
|
1401
|
-
"searchCancel"
|
|
1402
|
-
"searchInvalidAnswer"
|
|
1403
|
-
"searchDone"
|
|
1402
|
+
"searchNoResult" /* SEARCH_NO_RESULT */,
|
|
1403
|
+
"searchResult" /* SEARCH_RESULT */,
|
|
1404
|
+
"searchCancel" /* SEARCH_CANCEL */,
|
|
1405
|
+
"searchInvalidAnswer" /* SEARCH_INVALID_ANSWER */,
|
|
1406
|
+
"searchDone" /* SEARCH_DONE */
|
|
1404
1407
|
];
|
|
1405
1408
|
for (const evn of searchEvents) {
|
|
1406
1409
|
if (this.distube.listenerCount(evn) === 0) {
|
|
@@ -1417,7 +1420,7 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1417
1420
|
let result = results[0];
|
|
1418
1421
|
if (limit > 1) {
|
|
1419
1422
|
results.splice(limit);
|
|
1420
|
-
this.emit("searchResult"
|
|
1423
|
+
this.emit("searchResult" /* SEARCH_RESULT */, message, results, query);
|
|
1421
1424
|
const answers = await message.channel.awaitMessages({
|
|
1422
1425
|
filter: (m) => m.author.id === message.author.id,
|
|
1423
1426
|
max: 1,
|
|
@@ -1426,26 +1429,27 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1426
1429
|
}).catch(() => void 0);
|
|
1427
1430
|
const ans = answers?.first();
|
|
1428
1431
|
if (!ans) {
|
|
1429
|
-
this.emit("searchCancel"
|
|
1432
|
+
this.emit("searchCancel" /* SEARCH_CANCEL */, message, query);
|
|
1430
1433
|
return null;
|
|
1431
1434
|
}
|
|
1432
1435
|
const index = parseInt(ans.content, 10);
|
|
1433
1436
|
if (isNaN(index) || index > results.length || index < 1) {
|
|
1434
|
-
this.emit("searchInvalidAnswer"
|
|
1437
|
+
this.emit("searchInvalidAnswer" /* SEARCH_INVALID_ANSWER */, message, ans, query);
|
|
1435
1438
|
return null;
|
|
1436
1439
|
}
|
|
1437
|
-
this.emit("searchDone"
|
|
1440
|
+
this.emit("searchDone" /* SEARCH_DONE */, message, ans, query);
|
|
1438
1441
|
result = results[index - 1];
|
|
1439
1442
|
}
|
|
1440
1443
|
return result;
|
|
1441
1444
|
}
|
|
1442
1445
|
/**
|
|
1443
1446
|
* Play or add a {@link Playlist} to the queue.
|
|
1444
|
-
*
|
|
1445
|
-
* @
|
|
1446
|
-
*
|
|
1447
|
-
* @
|
|
1448
|
-
* @
|
|
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
|
|
1449
1453
|
*/
|
|
1450
1454
|
async playPlaylist(voiceChannel, playlist, options = {}) {
|
|
1451
1455
|
const { textChannel, skip } = { skip: false, ...options };
|
|
@@ -1468,23 +1472,24 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1468
1472
|
if (skip)
|
|
1469
1473
|
queue.skip();
|
|
1470
1474
|
else
|
|
1471
|
-
this.emit("addList"
|
|
1475
|
+
this.emit("addList" /* ADD_LIST */, queue, playlist);
|
|
1472
1476
|
} else {
|
|
1473
1477
|
const newQueue = await this.queues.create(voiceChannel, playlist.songs, textChannel);
|
|
1474
1478
|
if (newQueue instanceof Queue) {
|
|
1475
1479
|
if (this.options.emitAddListWhenCreatingQueue)
|
|
1476
|
-
this.emit("addList"
|
|
1477
|
-
this.emit("playSong"
|
|
1480
|
+
this.emit("addList" /* ADD_LIST */, newQueue, playlist);
|
|
1481
|
+
this.emit("playSong" /* PLAY_SONG */, newQueue, newQueue.songs[0]);
|
|
1478
1482
|
}
|
|
1479
1483
|
}
|
|
1480
1484
|
}
|
|
1481
1485
|
/**
|
|
1482
1486
|
* Play or add a {@link Song} to the queue.
|
|
1483
|
-
*
|
|
1484
|
-
* @
|
|
1485
|
-
*
|
|
1486
|
-
* @
|
|
1487
|
-
* @
|
|
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
|
|
1488
1493
|
*/
|
|
1489
1494
|
async playSong(voiceChannel, song, options = {}) {
|
|
1490
1495
|
if (!(song instanceof Song))
|
|
@@ -1502,27 +1507,26 @@ var _DisTubeHandler = class _DisTubeHandler extends DisTubeBase {
|
|
|
1502
1507
|
if (skip)
|
|
1503
1508
|
queue.skip();
|
|
1504
1509
|
else
|
|
1505
|
-
this.emit("addSong"
|
|
1510
|
+
this.emit("addSong" /* ADD_SONG */, queue, song);
|
|
1506
1511
|
} else {
|
|
1507
1512
|
const newQueue = await this.queues.create(voiceChannel, song, textChannel);
|
|
1508
1513
|
if (newQueue instanceof Queue) {
|
|
1509
1514
|
if (this.options.emitAddSongWhenCreatingQueue)
|
|
1510
|
-
this.emit("addSong"
|
|
1511
|
-
this.emit("playSong"
|
|
1515
|
+
this.emit("addSong" /* ADD_SONG */, newQueue, song);
|
|
1516
|
+
this.emit("playSong" /* PLAY_SONG */, newQueue, song);
|
|
1512
1517
|
}
|
|
1513
1518
|
}
|
|
1514
1519
|
}
|
|
1515
1520
|
/**
|
|
1516
1521
|
* Get {@link Song}'s stream info and attach it to the song.
|
|
1517
|
-
*
|
|
1522
|
+
*
|
|
1523
|
+
* @param song - A Song
|
|
1518
1524
|
*/
|
|
1519
1525
|
async attachStreamInfo(song) {
|
|
1520
|
-
const { url, source
|
|
1526
|
+
const { url, source } = song;
|
|
1521
1527
|
if (source === "youtube") {
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
}
|
|
1525
|
-
} else if (!streamURL) {
|
|
1528
|
+
song._patchYouTube(await this.handler.getYouTubeInfo(url));
|
|
1529
|
+
} else {
|
|
1526
1530
|
for (const plugin of [...this.distube.extractorPlugins, ...this.distube.customPlugins]) {
|
|
1527
1531
|
if (await plugin.validate(url)) {
|
|
1528
1532
|
const info = [plugin.getStreamURL(url), plugin.getRelatedSongs(url)];
|
|
@@ -1562,6 +1566,8 @@ var _Options = class _Options {
|
|
|
1562
1566
|
__publicField(this, "joinNewVoiceChannel");
|
|
1563
1567
|
__publicField(this, "streamType");
|
|
1564
1568
|
__publicField(this, "directLink");
|
|
1569
|
+
__publicField(this, "ffmpegPath");
|
|
1570
|
+
__publicField(this, "ffmpegDefaultArgs");
|
|
1565
1571
|
if (typeof options !== "object" || Array.isArray(options)) {
|
|
1566
1572
|
throw new DisTubeError("INVALID_TYPE", "object", options, "DisTubeOptions");
|
|
1567
1573
|
}
|
|
@@ -1584,6 +1590,8 @@ var _Options = class _Options {
|
|
|
1584
1590
|
this.joinNewVoiceChannel = opts.joinNewVoiceChannel;
|
|
1585
1591
|
this.streamType = opts.streamType;
|
|
1586
1592
|
this.directLink = opts.directLink;
|
|
1593
|
+
this.ffmpegPath = opts.ffmpegPath;
|
|
1594
|
+
this.ffmpegDefaultArgs = opts.ffmpegDefaultArgs;
|
|
1587
1595
|
checkInvalidKey(opts, this, "DisTubeOptions");
|
|
1588
1596
|
__privateMethod(this, _validateOptions, validateOptions_fn).call(this);
|
|
1589
1597
|
}
|
|
@@ -1603,8 +1611,8 @@ validateOptions_fn = /* @__PURE__ */ __name(function(options = this) {
|
|
|
1603
1611
|
"directLink"
|
|
1604
1612
|
]);
|
|
1605
1613
|
const numberOptions = /* @__PURE__ */ new Set(["searchCooldown", "emptyCooldown", "searchSongs"]);
|
|
1606
|
-
const stringOptions = /* @__PURE__ */ new Set();
|
|
1607
|
-
const objectOptions = /* @__PURE__ */ new Set(["customFilters", "ytdlOptions"]);
|
|
1614
|
+
const stringOptions = /* @__PURE__ */ new Set(["ffmpegPath"]);
|
|
1615
|
+
const objectOptions = /* @__PURE__ */ new Set(["customFilters", "ytdlOptions", "ffmpegDefaultArgs"]);
|
|
1608
1616
|
const optionalOptions = /* @__PURE__ */ new Set(["youtubeCookie", "customFilters"]);
|
|
1609
1617
|
for (const [key, value] of Object.entries(options)) {
|
|
1610
1618
|
if (value === void 0 && optionalOptions.has(key))
|
|
@@ -1644,14 +1652,11 @@ var _BaseManager = class _BaseManager extends DisTubeBase {
|
|
|
1644
1652
|
super(...arguments);
|
|
1645
1653
|
/**
|
|
1646
1654
|
* The collection of items for this manager.
|
|
1647
|
-
* @type {Collection}
|
|
1648
|
-
* @name BaseManager#collection
|
|
1649
1655
|
*/
|
|
1650
1656
|
__publicField(this, "collection", new import_discord2.Collection());
|
|
1651
1657
|
}
|
|
1652
1658
|
/**
|
|
1653
1659
|
* The size of the collection.
|
|
1654
|
-
* @type {number}
|
|
1655
1660
|
*/
|
|
1656
1661
|
get size() {
|
|
1657
1662
|
return this.collection.size;
|
|
@@ -1667,7 +1672,8 @@ var _GuildIdManager = class _GuildIdManager extends BaseManager {
|
|
|
1667
1672
|
const existing = this.get(id);
|
|
1668
1673
|
if (existing)
|
|
1669
1674
|
return this;
|
|
1670
|
-
|
|
1675
|
+
this.collection.set(id, data);
|
|
1676
|
+
return this;
|
|
1671
1677
|
}
|
|
1672
1678
|
get(idOrInstance) {
|
|
1673
1679
|
return this.collection.get(resolveGuildId(idOrInstance));
|
|
@@ -1687,21 +1693,16 @@ var import_voice3 = require("@discordjs/voice");
|
|
|
1687
1693
|
var _DisTubeVoiceManager = class _DisTubeVoiceManager extends GuildIdManager {
|
|
1688
1694
|
/**
|
|
1689
1695
|
* Get a {@link DisTubeVoice}.
|
|
1690
|
-
*
|
|
1691
|
-
* @
|
|
1692
|
-
* @param {GuildIdResolvable} guild The queue resolvable to resolve
|
|
1693
|
-
* @returns {DisTubeVoice?}
|
|
1696
|
+
*
|
|
1697
|
+
* @param guild - The queue resolvable to resolve
|
|
1694
1698
|
*/
|
|
1695
1699
|
/**
|
|
1696
1700
|
* Collection of {@link DisTubeVoice}.
|
|
1697
|
-
* @name DisTubeVoiceManager#collection
|
|
1698
|
-
* @type {Discord.Collection<string, DisTubeVoice>}
|
|
1699
1701
|
*/
|
|
1700
1702
|
/**
|
|
1701
1703
|
* Create a {@link DisTubeVoice}
|
|
1702
|
-
*
|
|
1703
|
-
* @
|
|
1704
|
-
* @private
|
|
1704
|
+
*
|
|
1705
|
+
* @param channel - A voice channel to join
|
|
1705
1706
|
*/
|
|
1706
1707
|
create(channel) {
|
|
1707
1708
|
const existing = this.get(channel.guildId);
|
|
@@ -1713,8 +1714,8 @@ var _DisTubeVoiceManager = class _DisTubeVoiceManager extends GuildIdManager {
|
|
|
1713
1714
|
}
|
|
1714
1715
|
/**
|
|
1715
1716
|
* Join a voice channel
|
|
1716
|
-
*
|
|
1717
|
-
* @
|
|
1717
|
+
*
|
|
1718
|
+
* @param channel - A voice channel to join
|
|
1718
1719
|
*/
|
|
1719
1720
|
join(channel) {
|
|
1720
1721
|
const existing = this.get(channel.guildId);
|
|
@@ -1724,7 +1725,8 @@ var _DisTubeVoiceManager = class _DisTubeVoiceManager extends GuildIdManager {
|
|
|
1724
1725
|
}
|
|
1725
1726
|
/**
|
|
1726
1727
|
* Leave the connected voice channel in a guild
|
|
1727
|
-
*
|
|
1728
|
+
*
|
|
1729
|
+
* @param guild - Queue Resolvable
|
|
1728
1730
|
*/
|
|
1729
1731
|
leave(guild) {
|
|
1730
1732
|
const voice = this.get(guild);
|
|
@@ -1751,17 +1753,15 @@ var _FilterManager = class _FilterManager extends BaseManager {
|
|
|
1751
1753
|
__privateAdd(this, _removeFn);
|
|
1752
1754
|
/**
|
|
1753
1755
|
* Collection of {@link Filter}.
|
|
1754
|
-
* @name FilterManager#collection
|
|
1755
|
-
* @type {Discord.Collection<string, DisTubeVoice>}
|
|
1756
1756
|
*/
|
|
1757
1757
|
__publicField(this, "queue");
|
|
1758
1758
|
this.queue = queue;
|
|
1759
1759
|
}
|
|
1760
1760
|
/**
|
|
1761
1761
|
* Enable a filter or multiple filters to the manager
|
|
1762
|
-
*
|
|
1763
|
-
* @param
|
|
1764
|
-
* @
|
|
1762
|
+
*
|
|
1763
|
+
* @param filterOrFilters - The filter or filters to enable
|
|
1764
|
+
* @param override - Wether or not override the applied filter with new filter value
|
|
1765
1765
|
*/
|
|
1766
1766
|
add(filterOrFilters, override = false) {
|
|
1767
1767
|
if (Array.isArray(filterOrFilters)) {
|
|
@@ -1780,15 +1780,14 @@ var _FilterManager = class _FilterManager extends BaseManager {
|
|
|
1780
1780
|
}
|
|
1781
1781
|
/**
|
|
1782
1782
|
* Clear enabled filters of the manager
|
|
1783
|
-
* @returns {FilterManager}
|
|
1784
1783
|
*/
|
|
1785
1784
|
clear() {
|
|
1786
1785
|
return this.set([]);
|
|
1787
1786
|
}
|
|
1788
1787
|
/**
|
|
1789
1788
|
* Set the filters applied to the manager
|
|
1790
|
-
*
|
|
1791
|
-
* @
|
|
1789
|
+
*
|
|
1790
|
+
* @param filters - The filters to apply
|
|
1792
1791
|
*/
|
|
1793
1792
|
set(filters) {
|
|
1794
1793
|
if (!Array.isArray(filters))
|
|
@@ -1803,8 +1802,8 @@ var _FilterManager = class _FilterManager extends BaseManager {
|
|
|
1803
1802
|
}
|
|
1804
1803
|
/**
|
|
1805
1804
|
* Disable a filter or multiple filters
|
|
1806
|
-
*
|
|
1807
|
-
* @
|
|
1805
|
+
*
|
|
1806
|
+
* @param filterOrFilters - The filter or filters to disable
|
|
1808
1807
|
*/
|
|
1809
1808
|
remove(filterOrFilters) {
|
|
1810
1809
|
if (Array.isArray(filterOrFilters))
|
|
@@ -1816,30 +1815,26 @@ var _FilterManager = class _FilterManager extends BaseManager {
|
|
|
1816
1815
|
}
|
|
1817
1816
|
/**
|
|
1818
1817
|
* Check whether a filter enabled or not
|
|
1819
|
-
*
|
|
1820
|
-
* @
|
|
1818
|
+
*
|
|
1819
|
+
* @param filter - The filter to check
|
|
1821
1820
|
*/
|
|
1822
1821
|
has(filter) {
|
|
1823
1822
|
return this.collection.has(typeof filter === "string" ? filter : __privateMethod(this, _resolve, resolve_fn).call(this, filter).name);
|
|
1824
1823
|
}
|
|
1825
1824
|
/**
|
|
1826
1825
|
* Array of enabled filter names
|
|
1827
|
-
* @type {Array<string>}
|
|
1828
|
-
* @readonly
|
|
1829
1826
|
*/
|
|
1830
1827
|
get names() {
|
|
1831
1828
|
return [...this.collection.keys()];
|
|
1832
1829
|
}
|
|
1833
1830
|
/**
|
|
1834
1831
|
* Array of enabled filters
|
|
1835
|
-
* @type {Array<Filter>}
|
|
1836
|
-
* @readonly
|
|
1837
1832
|
*/
|
|
1838
1833
|
get values() {
|
|
1839
1834
|
return [...this.collection.values()];
|
|
1840
1835
|
}
|
|
1841
1836
|
get ffmpegArgs() {
|
|
1842
|
-
return this.size ?
|
|
1837
|
+
return this.size ? { af: this.values.map((f) => f.value).join(",") } : {};
|
|
1843
1838
|
}
|
|
1844
1839
|
toString() {
|
|
1845
1840
|
return this.names.toString();
|
|
@@ -1877,51 +1872,46 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1877
1872
|
super(...arguments);
|
|
1878
1873
|
/**
|
|
1879
1874
|
* Get a Queue from this QueueManager.
|
|
1880
|
-
*
|
|
1881
|
-
* @
|
|
1882
|
-
* @param {GuildIdResolvable} guild Resolvable thing from a guild
|
|
1883
|
-
* @returns {Queue?}
|
|
1875
|
+
*
|
|
1876
|
+
* @param guild - Resolvable thing from a guild
|
|
1884
1877
|
*/
|
|
1885
1878
|
/**
|
|
1886
1879
|
* Listen to DisTubeVoice events and handle the Queue
|
|
1887
|
-
*
|
|
1888
|
-
* @param
|
|
1880
|
+
*
|
|
1881
|
+
* @param queue - Queue
|
|
1889
1882
|
*/
|
|
1890
1883
|
__privateAdd(this, _voiceEventHandler);
|
|
1891
1884
|
/**
|
|
1892
1885
|
* Whether or not emit playSong event
|
|
1893
|
-
*
|
|
1894
|
-
* @
|
|
1895
|
-
* @returns {boolean}
|
|
1886
|
+
*
|
|
1887
|
+
* @param queue - Queue
|
|
1896
1888
|
*/
|
|
1897
1889
|
__privateAdd(this, _emitPlaySong);
|
|
1898
1890
|
/**
|
|
1899
1891
|
* Handle the queue when a Song finish
|
|
1900
|
-
*
|
|
1901
|
-
* @param
|
|
1902
|
-
* @returns {Promise<void>}
|
|
1892
|
+
*
|
|
1893
|
+
* @param queue - queue
|
|
1903
1894
|
*/
|
|
1904
1895
|
__privateAdd(this, _handleSongFinish);
|
|
1905
1896
|
/**
|
|
1906
1897
|
* Handle error while playing
|
|
1907
|
-
*
|
|
1908
|
-
* @param
|
|
1909
|
-
* @param
|
|
1898
|
+
*
|
|
1899
|
+
* @param queue - queue
|
|
1900
|
+
* @param error - error
|
|
1910
1901
|
*/
|
|
1911
1902
|
__privateAdd(this, _handlePlayingError);
|
|
1912
1903
|
}
|
|
1913
1904
|
/**
|
|
1914
1905
|
* Collection of {@link Queue}.
|
|
1915
|
-
* @name QueueManager#collection
|
|
1916
|
-
* @type {Discord.Collection<string, Queue>}
|
|
1917
1906
|
*/
|
|
1918
1907
|
/**
|
|
1919
1908
|
* Create a {@link Queue}
|
|
1920
|
-
*
|
|
1921
|
-
* @param
|
|
1922
|
-
* @param
|
|
1923
|
-
* @param
|
|
1924
|
-
*
|
|
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
|
|
1925
1915
|
*/
|
|
1926
1916
|
async create(channel, song, textChannel) {
|
|
1927
1917
|
if (this.has(channel.guildId))
|
|
@@ -1933,7 +1923,7 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1933
1923
|
await voice.join();
|
|
1934
1924
|
__privateMethod(this, _voiceEventHandler, voiceEventHandler_fn).call(this, queue);
|
|
1935
1925
|
this.add(queue.id, queue);
|
|
1936
|
-
this.emit("initQueue"
|
|
1926
|
+
this.emit("initQueue" /* INIT_QUEUE */, queue);
|
|
1937
1927
|
const err = await this.playSong(queue);
|
|
1938
1928
|
return err || queue;
|
|
1939
1929
|
} finally {
|
|
@@ -1942,26 +1932,33 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1942
1932
|
}
|
|
1943
1933
|
/**
|
|
1944
1934
|
* Create a ytdl stream
|
|
1945
|
-
*
|
|
1946
|
-
* @
|
|
1935
|
+
*
|
|
1936
|
+
* @param queue - Queue
|
|
1947
1937
|
*/
|
|
1948
1938
|
createStream(queue) {
|
|
1949
|
-
const
|
|
1939
|
+
const song = queue.songs[0];
|
|
1940
|
+
const { duration, source, streamURL } = song;
|
|
1950
1941
|
const streamOptions = {
|
|
1951
|
-
|
|
1942
|
+
ffmpeg: {
|
|
1943
|
+
path: this.options.ffmpegPath,
|
|
1944
|
+
args: {
|
|
1945
|
+
...this.options.ffmpegDefaultArgs,
|
|
1946
|
+
...queue.filters.ffmpegArgs
|
|
1947
|
+
}
|
|
1948
|
+
},
|
|
1952
1949
|
seek: duration ? queue.beginTime : void 0,
|
|
1953
|
-
isLive,
|
|
1954
1950
|
type: this.options.streamType
|
|
1955
1951
|
};
|
|
1956
1952
|
if (source === "youtube")
|
|
1957
|
-
return DisTubeStream.YouTube(
|
|
1953
|
+
return DisTubeStream.YouTube(song, streamOptions);
|
|
1958
1954
|
return DisTubeStream.DirectLink(streamURL, streamOptions);
|
|
1959
1955
|
}
|
|
1960
1956
|
/**
|
|
1961
1957
|
* Play a song on voice connection
|
|
1962
|
-
*
|
|
1963
|
-
* @param
|
|
1964
|
-
*
|
|
1958
|
+
*
|
|
1959
|
+
* @param queue - The guild queue
|
|
1960
|
+
*
|
|
1961
|
+
* @returns error?
|
|
1965
1962
|
*/
|
|
1966
1963
|
async playSong(queue) {
|
|
1967
1964
|
if (!queue)
|
|
@@ -1978,6 +1975,7 @@ var _QueueManager = class _QueueManager extends GuildIdManager {
|
|
|
1978
1975
|
return true;
|
|
1979
1976
|
}
|
|
1980
1977
|
const stream = this.createStream(queue);
|
|
1978
|
+
stream.on("debug", (data) => this.emit("ffmpegDebug" /* FFMPEG_DEBUG */, `[${queue.id}]: ${data}`));
|
|
1981
1979
|
queue.voice.play(stream);
|
|
1982
1980
|
song.streamURL = stream.url;
|
|
1983
1981
|
return false;
|
|
@@ -1992,7 +1990,7 @@ voiceEventHandler_fn = /* @__PURE__ */ __name(function(queue) {
|
|
|
1992
1990
|
queue._listeners = {
|
|
1993
1991
|
disconnect: (error) => {
|
|
1994
1992
|
queue.remove();
|
|
1995
|
-
this.emit("disconnect"
|
|
1993
|
+
this.emit("disconnect" /* DISCONNECT */, queue);
|
|
1996
1994
|
if (error)
|
|
1997
1995
|
this.emitError(error, queue.textChannel);
|
|
1998
1996
|
},
|
|
@@ -2009,7 +2007,7 @@ emitPlaySong_fn = /* @__PURE__ */ __name(function(queue) {
|
|
|
2009
2007
|
}, "#emitPlaySong");
|
|
2010
2008
|
_handleSongFinish = new WeakSet();
|
|
2011
2009
|
handleSongFinish_fn = /* @__PURE__ */ __name(async function(queue) {
|
|
2012
|
-
this.emit("finishSong"
|
|
2010
|
+
this.emit("finishSong" /* FINISH_SONG */, queue, queue.songs[0]);
|
|
2013
2011
|
await queue._taskQueue.queuing();
|
|
2014
2012
|
try {
|
|
2015
2013
|
if (queue.stopped)
|
|
@@ -2027,14 +2025,14 @@ handleSongFinish_fn = /* @__PURE__ */ __name(async function(queue) {
|
|
|
2027
2025
|
try {
|
|
2028
2026
|
await queue.addRelatedSong();
|
|
2029
2027
|
} catch {
|
|
2030
|
-
this.emit("noRelated"
|
|
2028
|
+
this.emit("noRelated" /* NO_RELATED */, queue);
|
|
2031
2029
|
}
|
|
2032
2030
|
}
|
|
2033
2031
|
if (queue.songs.length <= 1) {
|
|
2034
2032
|
if (this.options.leaveOnFinish)
|
|
2035
2033
|
queue.voice.leave();
|
|
2036
2034
|
if (!queue.autoplay)
|
|
2037
|
-
this.emit("finish"
|
|
2035
|
+
this.emit("finish" /* FINISH */, queue);
|
|
2038
2036
|
queue.remove();
|
|
2039
2037
|
return;
|
|
2040
2038
|
}
|
|
@@ -2053,7 +2051,7 @@ handleSongFinish_fn = /* @__PURE__ */ __name(async function(queue) {
|
|
|
2053
2051
|
queue.beginTime = 0;
|
|
2054
2052
|
const err = await this.playSong(queue);
|
|
2055
2053
|
if (!err && emitPlaySong)
|
|
2056
|
-
this.emit("playSong"
|
|
2054
|
+
this.emit("playSong" /* PLAY_SONG */, queue, queue.songs[0]);
|
|
2057
2055
|
} finally {
|
|
2058
2056
|
queue._taskQueue.resolve();
|
|
2059
2057
|
}
|
|
@@ -2074,7 +2072,7 @@ Name: ${song.name}`;
|
|
|
2074
2072
|
queue.beginTime = 0;
|
|
2075
2073
|
this.playSong(queue).then((e) => {
|
|
2076
2074
|
if (!e)
|
|
2077
|
-
this.emit("playSong"
|
|
2075
|
+
this.emit("playSong" /* PLAY_SONG */, queue, queue.songs[0]);
|
|
2078
2076
|
});
|
|
2079
2077
|
} else {
|
|
2080
2078
|
queue.stop();
|
|
@@ -2088,10 +2086,11 @@ var _filters;
|
|
|
2088
2086
|
var _Queue = class _Queue extends DisTubeBase {
|
|
2089
2087
|
/**
|
|
2090
2088
|
* Create a queue for the guild
|
|
2091
|
-
*
|
|
2092
|
-
* @param
|
|
2093
|
-
* @param
|
|
2094
|
-
* @param
|
|
2089
|
+
*
|
|
2090
|
+
* @param distube - DisTube
|
|
2091
|
+
* @param voice - Voice connection
|
|
2092
|
+
* @param song - First song(s)
|
|
2093
|
+
* @param textChannel - Default text channel
|
|
2095
2094
|
*/
|
|
2096
2095
|
constructor(distube, voice, song, textChannel) {
|
|
2097
2096
|
super(distube);
|
|
@@ -2133,55 +2132,42 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2133
2132
|
}
|
|
2134
2133
|
/**
|
|
2135
2134
|
* The client user as a `GuildMember` of this queue's guild
|
|
2136
|
-
* @type {Discord.GuildMember?}
|
|
2137
2135
|
*/
|
|
2138
2136
|
get clientMember() {
|
|
2139
2137
|
return this.voice.channel.guild.members.me ?? void 0;
|
|
2140
2138
|
}
|
|
2141
2139
|
/**
|
|
2142
2140
|
* The filter manager of the queue
|
|
2143
|
-
* @type {FilterManager}
|
|
2144
|
-
* @readonly
|
|
2145
2141
|
*/
|
|
2146
2142
|
get filters() {
|
|
2147
2143
|
return __privateGet(this, _filters);
|
|
2148
2144
|
}
|
|
2149
2145
|
/**
|
|
2150
2146
|
* Formatted duration string.
|
|
2151
|
-
* @type {string}
|
|
2152
|
-
* @readonly
|
|
2153
2147
|
*/
|
|
2154
2148
|
get formattedDuration() {
|
|
2155
2149
|
return formatDuration(this.duration);
|
|
2156
2150
|
}
|
|
2157
2151
|
/**
|
|
2158
2152
|
* Queue's duration.
|
|
2159
|
-
* @type {number}
|
|
2160
|
-
* @readonly
|
|
2161
2153
|
*/
|
|
2162
2154
|
get duration() {
|
|
2163
2155
|
return this.songs.length ? this.songs.reduce((prev, next) => prev + next.duration, 0) : 0;
|
|
2164
2156
|
}
|
|
2165
2157
|
/**
|
|
2166
2158
|
* What time in the song is playing (in seconds).
|
|
2167
|
-
* @type {number}
|
|
2168
|
-
* @readonly
|
|
2169
2159
|
*/
|
|
2170
2160
|
get currentTime() {
|
|
2171
2161
|
return this.voice.playbackDuration + this.beginTime;
|
|
2172
2162
|
}
|
|
2173
2163
|
/**
|
|
2174
2164
|
* Formatted {@link Queue#currentTime} string.
|
|
2175
|
-
* @type {string}
|
|
2176
|
-
* @readonly
|
|
2177
2165
|
*/
|
|
2178
2166
|
get formattedCurrentTime() {
|
|
2179
2167
|
return formatDuration(this.currentTime);
|
|
2180
2168
|
}
|
|
2181
2169
|
/**
|
|
2182
2170
|
* The voice channel playing in.
|
|
2183
|
-
* @type {Discord.VoiceChannel|Discord.StageChannel|null}
|
|
2184
|
-
* @readonly
|
|
2185
2171
|
*/
|
|
2186
2172
|
get voiceChannel() {
|
|
2187
2173
|
return this.clientMember?.voice?.channel ?? null;
|
|
@@ -2193,12 +2179,12 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2193
2179
|
this.voice.volume = value;
|
|
2194
2180
|
}
|
|
2195
2181
|
/**
|
|
2196
|
-
* @
|
|
2197
|
-
*
|
|
2198
|
-
* @param
|
|
2199
|
-
* @param
|
|
2200
|
-
*
|
|
2201
|
-
* @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
|
|
2202
2188
|
*/
|
|
2203
2189
|
addToQueue(song, position = 0) {
|
|
2204
2190
|
if (!song || Array.isArray(song) && !song.length) {
|
|
@@ -2225,7 +2211,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2225
2211
|
}
|
|
2226
2212
|
/**
|
|
2227
2213
|
* Pause the guild stream
|
|
2228
|
-
*
|
|
2214
|
+
*
|
|
2215
|
+
* @returns The guild queue
|
|
2229
2216
|
*/
|
|
2230
2217
|
pause() {
|
|
2231
2218
|
if (this.paused)
|
|
@@ -2237,7 +2224,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2237
2224
|
}
|
|
2238
2225
|
/**
|
|
2239
2226
|
* Resume the guild stream
|
|
2240
|
-
*
|
|
2227
|
+
*
|
|
2228
|
+
* @returns The guild queue
|
|
2241
2229
|
*/
|
|
2242
2230
|
resume() {
|
|
2243
2231
|
if (this.playing)
|
|
@@ -2249,19 +2237,21 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2249
2237
|
}
|
|
2250
2238
|
/**
|
|
2251
2239
|
* Set the guild stream's volume
|
|
2252
|
-
*
|
|
2253
|
-
* @
|
|
2240
|
+
*
|
|
2241
|
+
* @param percent - The percentage of volume you want to set
|
|
2242
|
+
*
|
|
2243
|
+
* @returns The guild queue
|
|
2254
2244
|
*/
|
|
2255
2245
|
setVolume(percent) {
|
|
2256
2246
|
this.volume = percent;
|
|
2257
2247
|
return this;
|
|
2258
2248
|
}
|
|
2259
2249
|
/**
|
|
2260
|
-
* Skip the playing song if there is a next song in the queue.
|
|
2261
|
-
*
|
|
2262
|
-
*
|
|
2263
|
-
*
|
|
2264
|
-
* @
|
|
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
|
|
2265
2255
|
*/
|
|
2266
2256
|
async skip() {
|
|
2267
2257
|
await this._taskQueue.queuing();
|
|
@@ -2282,8 +2272,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2282
2272
|
}
|
|
2283
2273
|
/**
|
|
2284
2274
|
* Play the previous song if exists
|
|
2285
|
-
*
|
|
2286
|
-
* @
|
|
2275
|
+
*
|
|
2276
|
+
* @returns The guild queue
|
|
2287
2277
|
*/
|
|
2288
2278
|
async previous() {
|
|
2289
2279
|
await this._taskQueue.queuing();
|
|
@@ -2303,7 +2293,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2303
2293
|
}
|
|
2304
2294
|
/**
|
|
2305
2295
|
* Shuffle the queue's songs
|
|
2306
|
-
*
|
|
2296
|
+
*
|
|
2297
|
+
* @returns The guild queue
|
|
2307
2298
|
*/
|
|
2308
2299
|
async shuffle() {
|
|
2309
2300
|
await this._taskQueue.queuing();
|
|
@@ -2322,12 +2313,13 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2322
2313
|
}
|
|
2323
2314
|
}
|
|
2324
2315
|
/**
|
|
2325
|
-
* Jump to the song position in the queue.
|
|
2326
|
-
*
|
|
2327
|
-
*
|
|
2328
|
-
*
|
|
2329
|
-
* @
|
|
2330
|
-
*
|
|
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
|
|
2331
2323
|
*/
|
|
2332
2324
|
async jump(position) {
|
|
2333
2325
|
await this._taskQueue.queuing();
|
|
@@ -2363,10 +2355,12 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2363
2355
|
}
|
|
2364
2356
|
}
|
|
2365
2357
|
/**
|
|
2366
|
-
* Set the repeat mode of the guild queue
|
|
2358
|
+
* Set the repeat mode of the guild queue.
|
|
2367
2359
|
* Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`
|
|
2368
|
-
*
|
|
2369
|
-
* @
|
|
2360
|
+
*
|
|
2361
|
+
* @param mode - The repeat modes (toggle if `undefined`)
|
|
2362
|
+
*
|
|
2363
|
+
* @returns The new repeat mode
|
|
2370
2364
|
*/
|
|
2371
2365
|
setRepeatMode(mode) {
|
|
2372
2366
|
if (mode !== void 0 && !Object.values(RepeatMode).includes(mode)) {
|
|
@@ -2382,8 +2376,10 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2382
2376
|
}
|
|
2383
2377
|
/**
|
|
2384
2378
|
* Set the playing time to another position
|
|
2385
|
-
*
|
|
2386
|
-
* @
|
|
2379
|
+
*
|
|
2380
|
+
* @param time - Time in seconds
|
|
2381
|
+
*
|
|
2382
|
+
* @returns The guild queue
|
|
2387
2383
|
*/
|
|
2388
2384
|
seek(time) {
|
|
2389
2385
|
if (typeof time !== "number")
|
|
@@ -2396,8 +2392,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2396
2392
|
}
|
|
2397
2393
|
/**
|
|
2398
2394
|
* Add a related song of the playing song to the queue
|
|
2399
|
-
*
|
|
2400
|
-
* @
|
|
2395
|
+
*
|
|
2396
|
+
* @returns The added song
|
|
2401
2397
|
*/
|
|
2402
2398
|
async addRelatedSong() {
|
|
2403
2399
|
if (!this.songs?.[0])
|
|
@@ -2430,9 +2426,8 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2430
2426
|
}
|
|
2431
2427
|
}
|
|
2432
2428
|
/**
|
|
2433
|
-
* Remove the queue from the manager
|
|
2434
|
-
*
|
|
2435
|
-
* @private
|
|
2429
|
+
* Remove the queue from the manager (This does not leave the voice channel even if
|
|
2430
|
+
* {@link DisTubeOptions | DisTubeOptions.leaveOnStop} is enabled)
|
|
2436
2431
|
*/
|
|
2437
2432
|
remove() {
|
|
2438
2433
|
this.stopped = true;
|
|
@@ -2444,11 +2439,12 @@ var _Queue = class _Queue extends DisTubeBase {
|
|
|
2444
2439
|
}
|
|
2445
2440
|
}
|
|
2446
2441
|
this.queues.remove(this.id);
|
|
2447
|
-
this.emit("deleteQueue"
|
|
2442
|
+
this.emit("deleteQueue" /* DELETE_QUEUE */, this);
|
|
2448
2443
|
}
|
|
2449
2444
|
/**
|
|
2450
2445
|
* Toggle autoplay mode
|
|
2451
|
-
*
|
|
2446
|
+
*
|
|
2447
|
+
* @returns Autoplay mode state
|
|
2452
2448
|
*/
|
|
2453
2449
|
toggleAutoplay() {
|
|
2454
2450
|
this.autoplay = !this.autoplay;
|
|
@@ -2469,70 +2465,59 @@ var _Plugin = class _Plugin {
|
|
|
2469
2465
|
}
|
|
2470
2466
|
/**
|
|
2471
2467
|
* Type of the plugin
|
|
2472
|
-
* @name Plugin#type
|
|
2473
|
-
* @type {PluginType}
|
|
2474
2468
|
*/
|
|
2475
2469
|
/**
|
|
2476
2470
|
* Emit an event to the {@link DisTube} class
|
|
2477
|
-
*
|
|
2478
|
-
* @param
|
|
2479
|
-
* @
|
|
2471
|
+
*
|
|
2472
|
+
* @param eventName - Event name
|
|
2473
|
+
* @param args - arguments
|
|
2480
2474
|
*/
|
|
2481
2475
|
emit(eventName, ...args) {
|
|
2482
2476
|
return this.distube.emit(eventName, ...args);
|
|
2483
2477
|
}
|
|
2484
2478
|
/**
|
|
2485
2479
|
* Emit error event to the {@link DisTube} class
|
|
2486
|
-
*
|
|
2487
|
-
* @param
|
|
2480
|
+
*
|
|
2481
|
+
* @param error - error
|
|
2482
|
+
* @param channel - Text channel where the error is encountered.
|
|
2488
2483
|
*/
|
|
2489
2484
|
emitError(error, channel) {
|
|
2490
2485
|
this.distube.emitError(error, channel);
|
|
2491
2486
|
}
|
|
2492
2487
|
/**
|
|
2493
2488
|
* The queue manager
|
|
2494
|
-
* @type {QueueManager}
|
|
2495
|
-
* @readonly
|
|
2496
2489
|
*/
|
|
2497
2490
|
get queues() {
|
|
2498
2491
|
return this.distube.queues;
|
|
2499
2492
|
}
|
|
2500
2493
|
/**
|
|
2501
2494
|
* The voice manager
|
|
2502
|
-
* @type {DisTubeVoiceManager}
|
|
2503
|
-
* @readonly
|
|
2504
2495
|
*/
|
|
2505
2496
|
get voices() {
|
|
2506
2497
|
return this.distube.voices;
|
|
2507
2498
|
}
|
|
2508
2499
|
/**
|
|
2509
2500
|
* Discord.js client
|
|
2510
|
-
* @type {Discord.Client}
|
|
2511
|
-
* @readonly
|
|
2512
2501
|
*/
|
|
2513
2502
|
get client() {
|
|
2514
2503
|
return this.distube.client;
|
|
2515
2504
|
}
|
|
2516
2505
|
/**
|
|
2517
2506
|
* DisTube options
|
|
2518
|
-
* @type {DisTubeOptions}
|
|
2519
|
-
* @readonly
|
|
2520
2507
|
*/
|
|
2521
2508
|
get options() {
|
|
2522
2509
|
return this.distube.options;
|
|
2523
2510
|
}
|
|
2524
2511
|
/**
|
|
2525
2512
|
* DisTube handler
|
|
2526
|
-
* @type {DisTubeHandler}
|
|
2527
|
-
* @readonly
|
|
2528
2513
|
*/
|
|
2529
2514
|
get handler() {
|
|
2530
2515
|
return this.distube.handler;
|
|
2531
2516
|
}
|
|
2532
2517
|
/**
|
|
2533
2518
|
* Check if the string is working with this plugin
|
|
2534
|
-
*
|
|
2535
|
-
* @
|
|
2519
|
+
*
|
|
2520
|
+
* @param _string - Input string
|
|
2536
2521
|
*/
|
|
2537
2522
|
validate(_string) {
|
|
2538
2523
|
return false;
|
|
@@ -2540,17 +2525,18 @@ var _Plugin = class _Plugin {
|
|
|
2540
2525
|
/**
|
|
2541
2526
|
* Get the stream url from {@link Song#url}. Returns {@link Song#url} by default.
|
|
2542
2527
|
* Not needed if the plugin plays song from YouTube.
|
|
2543
|
-
*
|
|
2544
|
-
* @
|
|
2528
|
+
*
|
|
2529
|
+
* @param url - Input url
|
|
2545
2530
|
*/
|
|
2546
2531
|
getStreamURL(url) {
|
|
2547
2532
|
return url;
|
|
2548
2533
|
}
|
|
2549
2534
|
/**
|
|
2550
|
-
* Get related songs from a supported url. {@link Song#member} should be
|
|
2551
|
-
* Not needed to add {@link Song#related} because it will be added
|
|
2552
|
-
*
|
|
2553
|
-
*
|
|
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
|
|
2554
2540
|
*/
|
|
2555
2541
|
getRelatedSongs(_url) {
|
|
2556
2542
|
return [];
|
|
@@ -2767,10 +2753,10 @@ var DirectLinkPlugin = _DirectLinkPlugin;
|
|
|
2767
2753
|
|
|
2768
2754
|
// src/DisTube.ts
|
|
2769
2755
|
var import_ytsr = __toESM(require("@distube/ytsr"));
|
|
2770
|
-
var
|
|
2756
|
+
var import_tiny_typed_emitter3 = require("tiny-typed-emitter");
|
|
2771
2757
|
var { version } = require_package();
|
|
2772
2758
|
var _getQueue, getQueue_fn;
|
|
2773
|
-
var _DisTube = class _DisTube extends
|
|
2759
|
+
var _DisTube = class _DisTube extends import_tiny_typed_emitter3.TypedEmitter {
|
|
2774
2760
|
constructor(client, otp = {}) {
|
|
2775
2761
|
super();
|
|
2776
2762
|
__privateAdd(this, _getQueue);
|
|
@@ -2803,21 +2789,16 @@ var _DisTube = class _DisTube extends import_tiny_typed_emitter2.TypedEmitter {
|
|
|
2803
2789
|
}
|
|
2804
2790
|
/**
|
|
2805
2791
|
* DisTube version
|
|
2806
|
-
* @type {string}
|
|
2807
2792
|
*/
|
|
2808
2793
|
get version() {
|
|
2809
2794
|
return version;
|
|
2810
2795
|
}
|
|
2811
2796
|
/**
|
|
2812
|
-
* 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.
|
|
2813
2799
|
*
|
|
2814
|
-
* @param {Discord.BaseGuildVoiceChannel} voiceChannel The channel will be joined if the bot isn't in any channels,
|
|
2815
|
-
* the bot will be moved to this channel if {@link DisTubeOptions}.joinNewVoiceChannel is `true`
|
|
2816
|
-
* @param {string|Song|SearchResult|Playlist} song URL | Search string |
|
|
2817
|
-
* {@link Song} | {@link SearchResult} | {@link Playlist}
|
|
2818
|
-
* @param {PlayOptions} [options] Optional options
|
|
2819
|
-
* @throws {DisTubeError}
|
|
2820
2800
|
* @example
|
|
2801
|
+
* ```ts
|
|
2821
2802
|
* client.on('message', (message) => {
|
|
2822
2803
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
2823
2804
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -2829,7 +2810,14 @@ var _DisTube = class _DisTube extends import_tiny_typed_emitter2.TypedEmitter {
|
|
|
2829
2810
|
* message
|
|
2830
2811
|
* });
|
|
2831
2812
|
* });
|
|
2832
|
-
*
|
|
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
|
|
2833
2821
|
*/
|
|
2834
2822
|
async play(voiceChannel, song, options = {}) {
|
|
2835
2823
|
if (!isSupportedVoiceChannel(voiceChannel)) {
|
|
@@ -2899,10 +2887,9 @@ ${e.message}`;
|
|
|
2899
2887
|
}
|
|
2900
2888
|
/**
|
|
2901
2889
|
* Create a custom playlist
|
|
2902
|
-
*
|
|
2903
|
-
* @param {Array<string|Song|SearchResult>} songs Array of url, Song or SearchResult
|
|
2904
|
-
* @param {CustomPlaylistOptions} [options] Optional options
|
|
2890
|
+
*
|
|
2905
2891
|
* @example
|
|
2892
|
+
* ```ts
|
|
2906
2893
|
* const songs = ["https://www.youtube.com/watch?v=xxx", "https://www.youtube.com/watch?v=yyy"];
|
|
2907
2894
|
* const playlist = await distube.createCustomPlaylist(songs, {
|
|
2908
2895
|
* member: message.member,
|
|
@@ -2910,6 +2897,10 @@ ${e.message}`;
|
|
|
2910
2897
|
* parallel: true
|
|
2911
2898
|
* });
|
|
2912
2899
|
* distube.play(voiceChannel, playlist, { ... });
|
|
2900
|
+
* ```ts
|
|
2901
|
+
*
|
|
2902
|
+
* @param songs - Array of url, Song or SearchResult
|
|
2903
|
+
* @param options - Optional options
|
|
2913
2904
|
*/
|
|
2914
2905
|
async createCustomPlaylist(songs, options = {}) {
|
|
2915
2906
|
const { member, properties, parallel, metadata } = { parallel: true, ...options };
|
|
@@ -2930,13 +2921,14 @@ ${e.message}`;
|
|
|
2930
2921
|
const promises = filteredSongs.map(
|
|
2931
2922
|
(song) => this.handler.resolve(song, { member, metadata }).catch(() => void 0)
|
|
2932
2923
|
);
|
|
2933
|
-
resolvedSongs = (await Promise.all(promises)).filter((s) =>
|
|
2924
|
+
resolvedSongs = (await Promise.all(promises)).filter((s) => s instanceof Song);
|
|
2934
2925
|
} else {
|
|
2935
|
-
|
|
2926
|
+
resolvedSongs = [];
|
|
2936
2927
|
for (const song of filteredSongs) {
|
|
2937
|
-
resolved
|
|
2928
|
+
const resolved = await this.handler.resolve(song, { member, metadata }).catch(() => void 0);
|
|
2929
|
+
if (resolved instanceof Song)
|
|
2930
|
+
resolvedSongs.push(resolved);
|
|
2938
2931
|
}
|
|
2939
|
-
resolvedSongs = resolved.filter((s) => Boolean(s));
|
|
2940
2932
|
}
|
|
2941
2933
|
return new Playlist(resolvedSongs, { member, properties, metadata });
|
|
2942
2934
|
}
|
|
@@ -2944,13 +2936,13 @@ ${e.message}`;
|
|
|
2944
2936
|
* Search for a song. You can customize how user answers instead of send a number.
|
|
2945
2937
|
* Then use {@link DisTube#play} to play it.
|
|
2946
2938
|
*
|
|
2947
|
-
* @param
|
|
2948
|
-
* @param
|
|
2949
|
-
* @param
|
|
2950
|
-
* @param
|
|
2951
|
-
* @param
|
|
2952
|
-
*
|
|
2953
|
-
* @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
|
|
2954
2946
|
*/
|
|
2955
2947
|
async search(string, options = {}) {
|
|
2956
2948
|
const opts = { type: "video" /* VIDEO */, limit: 10, safeSearch: false, ...options };
|
|
@@ -2983,10 +2975,9 @@ ${e.message}`;
|
|
|
2983
2975
|
}
|
|
2984
2976
|
/**
|
|
2985
2977
|
* Get the guild queue
|
|
2986
|
-
*
|
|
2987
|
-
* @returns {Queue?}
|
|
2988
|
-
* @throws {Error}
|
|
2978
|
+
*
|
|
2989
2979
|
* @example
|
|
2980
|
+
* ```ts
|
|
2990
2981
|
* client.on('message', (message) => {
|
|
2991
2982
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
2992
2983
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -2998,34 +2989,38 @@ ${e.message}`;
|
|
|
2998
2989
|
* ).join("\n"));
|
|
2999
2990
|
* }
|
|
3000
2991
|
* });
|
|
2992
|
+
* ```ts
|
|
2993
|
+
*
|
|
2994
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3001
2995
|
*/
|
|
3002
2996
|
getQueue(guild) {
|
|
3003
2997
|
return this.queues.get(guild);
|
|
3004
2998
|
}
|
|
3005
2999
|
/**
|
|
3006
3000
|
* Pause the guild stream
|
|
3007
|
-
*
|
|
3008
|
-
* @
|
|
3009
|
-
*
|
|
3001
|
+
*
|
|
3002
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3003
|
+
*
|
|
3004
|
+
* @returns The guild queue
|
|
3010
3005
|
*/
|
|
3011
3006
|
pause(guild) {
|
|
3012
3007
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).pause();
|
|
3013
3008
|
}
|
|
3014
3009
|
/**
|
|
3015
3010
|
* Resume the guild stream
|
|
3016
|
-
*
|
|
3017
|
-
* @
|
|
3018
|
-
*
|
|
3011
|
+
*
|
|
3012
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3013
|
+
*
|
|
3014
|
+
* @returns The guild queue
|
|
3019
3015
|
*/
|
|
3020
3016
|
resume(guild) {
|
|
3021
3017
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).resume();
|
|
3022
3018
|
}
|
|
3023
3019
|
/**
|
|
3024
3020
|
* Stop the guild stream
|
|
3025
|
-
*
|
|
3026
|
-
* @returns {Promise<void>}
|
|
3027
|
-
* @throws {Error}
|
|
3021
|
+
*
|
|
3028
3022
|
* @example
|
|
3023
|
+
* ```ts
|
|
3029
3024
|
* client.on('message', (message) => {
|
|
3030
3025
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3031
3026
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3035,17 +3030,18 @@ ${e.message}`;
|
|
|
3035
3030
|
* message.channel.send("Stopped the queue!");
|
|
3036
3031
|
* }
|
|
3037
3032
|
* });
|
|
3033
|
+
* ```ts
|
|
3034
|
+
*
|
|
3035
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3038
3036
|
*/
|
|
3039
3037
|
stop(guild) {
|
|
3040
3038
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).stop();
|
|
3041
3039
|
}
|
|
3042
3040
|
/**
|
|
3043
3041
|
* Set the guild stream's volume
|
|
3044
|
-
*
|
|
3045
|
-
* @param {number} percent The percentage of volume you want to set
|
|
3046
|
-
* @returns {Queue} The guild queue
|
|
3047
|
-
* @throws {Error}
|
|
3042
|
+
*
|
|
3048
3043
|
* @example
|
|
3044
|
+
* ```ts
|
|
3049
3045
|
* client.on('message', (message) => {
|
|
3050
3046
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3051
3047
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3053,18 +3049,23 @@ ${e.message}`;
|
|
|
3053
3049
|
* if (command == "volume")
|
|
3054
3050
|
* distube.setVolume(message, Number(args[0]));
|
|
3055
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
|
|
3056
3058
|
*/
|
|
3057
3059
|
setVolume(guild, percent) {
|
|
3058
3060
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).setVolume(percent);
|
|
3059
3061
|
}
|
|
3060
3062
|
/**
|
|
3061
|
-
* Skip the playing song if there is a next song in the queue.
|
|
3062
|
-
*
|
|
3063
|
-
*
|
|
3064
|
-
*
|
|
3065
|
-
* @returns {Promise<Song>} The new Song will be played
|
|
3066
|
-
* @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
|
+
*
|
|
3067
3067
|
* @example
|
|
3068
|
+
* ```ts
|
|
3068
3069
|
* client.on('message', (message) => {
|
|
3069
3070
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3070
3071
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3072,16 +3073,20 @@ ${e.message}`;
|
|
|
3072
3073
|
* if (command == "skip")
|
|
3073
3074
|
* distube.skip(message);
|
|
3074
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
|
|
3075
3081
|
*/
|
|
3076
3082
|
skip(guild) {
|
|
3077
3083
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).skip();
|
|
3078
3084
|
}
|
|
3079
3085
|
/**
|
|
3080
3086
|
* Play the previous song
|
|
3081
|
-
*
|
|
3082
|
-
* @returns {Promise<Song>} The new Song will be played
|
|
3083
|
-
* @throws {Error}
|
|
3087
|
+
*
|
|
3084
3088
|
* @example
|
|
3089
|
+
* ```ts
|
|
3085
3090
|
* client.on('message', (message) => {
|
|
3086
3091
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3087
3092
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3089,15 +3094,20 @@ ${e.message}`;
|
|
|
3089
3094
|
* if (command == "previous")
|
|
3090
3095
|
* distube.previous(message);
|
|
3091
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
|
|
3092
3102
|
*/
|
|
3093
3103
|
previous(guild) {
|
|
3094
3104
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).previous();
|
|
3095
3105
|
}
|
|
3096
3106
|
/**
|
|
3097
3107
|
* Shuffle the guild queue songs
|
|
3098
|
-
*
|
|
3099
|
-
* @returns {Promise<Queue>} The guild queue
|
|
3108
|
+
*
|
|
3100
3109
|
* @example
|
|
3110
|
+
* ```ts
|
|
3101
3111
|
* client.on('message', (message) => {
|
|
3102
3112
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3103
3113
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3105,19 +3115,21 @@ ${e.message}`;
|
|
|
3105
3115
|
* if (command == "shuffle")
|
|
3106
3116
|
* distube.shuffle(message);
|
|
3107
3117
|
* });
|
|
3118
|
+
* ```ts
|
|
3119
|
+
*
|
|
3120
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3121
|
+
*
|
|
3122
|
+
* @returns The guild queue
|
|
3108
3123
|
*/
|
|
3109
3124
|
shuffle(guild) {
|
|
3110
3125
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).shuffle();
|
|
3111
3126
|
}
|
|
3112
3127
|
/**
|
|
3113
|
-
* Jump to the song number in the queue.
|
|
3114
|
-
*
|
|
3115
|
-
*
|
|
3116
|
-
* @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}
|
|
3117
|
-
* @param {number} num The song number to play
|
|
3118
|
-
* @returns {Promise<Song>} The new Song will be played
|
|
3119
|
-
* @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
|
+
*
|
|
3120
3131
|
* @example
|
|
3132
|
+
* ```ts
|
|
3121
3133
|
* client.on('message', (message) => {
|
|
3122
3134
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3123
3135
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3126,17 +3138,22 @@ ${e.message}`;
|
|
|
3126
3138
|
* distube.jump(message, parseInt(args[0]))
|
|
3127
3139
|
* .catch(err => message.channel.send("Invalid song number."));
|
|
3128
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
|
|
3129
3147
|
*/
|
|
3130
3148
|
jump(guild, num) {
|
|
3131
3149
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).jump(num);
|
|
3132
3150
|
}
|
|
3133
3151
|
/**
|
|
3134
|
-
* Set the repeat mode of the guild queue
|
|
3152
|
+
* Set the repeat mode of the guild queue.
|
|
3135
3153
|
* Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`
|
|
3136
|
-
*
|
|
3137
|
-
* @param {RepeatMode?} [mode] The repeat modes (toggle if `undefined`)
|
|
3138
|
-
* @returns {RepeatMode} The new repeat mode
|
|
3154
|
+
*
|
|
3139
3155
|
* @example
|
|
3156
|
+
* ```ts
|
|
3140
3157
|
* client.on('message', (message) => {
|
|
3141
3158
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3142
3159
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3147,7 +3164,9 @@ ${e.message}`;
|
|
|
3147
3164
|
* message.channel.send("Set repeat mode to `" + mode + "`");
|
|
3148
3165
|
* }
|
|
3149
3166
|
* });
|
|
3167
|
+
* ```ts
|
|
3150
3168
|
* @example
|
|
3169
|
+
* ```ts
|
|
3151
3170
|
* const { RepeatMode } = require("distube");
|
|
3152
3171
|
* let mode;
|
|
3153
3172
|
* switch(distube.setRepeatMode(message, parseInt(args[0]))) {
|
|
@@ -3162,16 +3181,21 @@ ${e.message}`;
|
|
|
3162
3181
|
* break;
|
|
3163
3182
|
* }
|
|
3164
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
|
|
3165
3190
|
*/
|
|
3166
3191
|
setRepeatMode(guild, mode) {
|
|
3167
3192
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).setRepeatMode(mode);
|
|
3168
3193
|
}
|
|
3169
3194
|
/**
|
|
3170
3195
|
* Toggle autoplay mode
|
|
3171
|
-
*
|
|
3172
|
-
* @returns {boolean} Autoplay mode state
|
|
3173
|
-
* @throws {Error}
|
|
3196
|
+
*
|
|
3174
3197
|
* @example
|
|
3198
|
+
* ```ts
|
|
3175
3199
|
* client.on('message', (message) => {
|
|
3176
3200
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3177
3201
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3181,6 +3205,11 @@ ${e.message}`;
|
|
|
3181
3205
|
* message.channel.send("Set autoplay mode to `" + (mode ? "On" : "Off") + "`");
|
|
3182
3206
|
* }
|
|
3183
3207
|
* });
|
|
3208
|
+
* ```ts
|
|
3209
|
+
*
|
|
3210
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3211
|
+
*
|
|
3212
|
+
* @returns Autoplay mode state
|
|
3184
3213
|
*/
|
|
3185
3214
|
toggleAutoplay(guild) {
|
|
3186
3215
|
const queue = __privateMethod(this, _getQueue, getQueue_fn).call(this, guild);
|
|
@@ -3189,18 +3218,19 @@ ${e.message}`;
|
|
|
3189
3218
|
}
|
|
3190
3219
|
/**
|
|
3191
3220
|
* Add related song to the queue
|
|
3192
|
-
*
|
|
3193
|
-
* @
|
|
3221
|
+
*
|
|
3222
|
+
* @param guild - The type can be resolved to give a {@link Queue}
|
|
3223
|
+
*
|
|
3224
|
+
* @returns The guild queue
|
|
3194
3225
|
*/
|
|
3195
3226
|
addRelatedSong(guild) {
|
|
3196
3227
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).addRelatedSong();
|
|
3197
3228
|
}
|
|
3198
3229
|
/**
|
|
3199
3230
|
* Set the playing time to another position
|
|
3200
|
-
*
|
|
3201
|
-
* @param {number} time Time in seconds
|
|
3202
|
-
* @returns {Queue} Seeked queue
|
|
3231
|
+
*
|
|
3203
3232
|
* @example
|
|
3233
|
+
* ```ts
|
|
3204
3234
|
* client.on('message', message => {
|
|
3205
3235
|
* if (!message.content.startsWith(config.prefix)) return;
|
|
3206
3236
|
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
|
|
@@ -3208,19 +3238,25 @@ ${e.message}`;
|
|
|
3208
3238
|
* if (command = 'seek')
|
|
3209
3239
|
* distube.seek(message, Number(args[0]));
|
|
3210
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
|
|
3211
3247
|
*/
|
|
3212
3248
|
seek(guild, time) {
|
|
3213
3249
|
return __privateMethod(this, _getQueue, getQueue_fn).call(this, guild).seek(time);
|
|
3214
3250
|
}
|
|
3215
3251
|
/**
|
|
3216
3252
|
* Emit error event
|
|
3217
|
-
*
|
|
3218
|
-
* @param
|
|
3219
|
-
* @
|
|
3253
|
+
*
|
|
3254
|
+
* @param error - error
|
|
3255
|
+
* @param channel - Text channel where the error is encountered.
|
|
3220
3256
|
*/
|
|
3221
3257
|
emitError(error, channel) {
|
|
3222
|
-
if (this.listeners("error").length) {
|
|
3223
|
-
this.emit("error"
|
|
3258
|
+
if (this.listeners("error" /* ERROR */).length) {
|
|
3259
|
+
this.emit("error" /* ERROR */, channel, error);
|
|
3224
3260
|
} else {
|
|
3225
3261
|
console.error(error);
|
|
3226
3262
|
console.warn("Unhandled 'error' event.");
|