distube 3.0.0-beta.9 → 3.0.3

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.
Files changed (158) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +64 -51
  3. package/dist/DisTube.d.ts +522 -0
  4. package/dist/DisTube.d.ts.map +1 -0
  5. package/dist/DisTube.js +794 -0
  6. package/dist/DisTube.js.map +1 -0
  7. package/dist/constant.d.ts +130 -0
  8. package/dist/constant.d.ts.map +1 -0
  9. package/dist/constant.js +150 -0
  10. package/dist/constant.js.map +1 -0
  11. package/dist/core/DisTubeBase.d.ts +55 -0
  12. package/dist/core/DisTubeBase.d.ts.map +1 -0
  13. package/dist/core/DisTubeBase.js +76 -0
  14. package/dist/core/DisTubeBase.js.map +1 -0
  15. package/dist/core/DisTubeHandler.d.ts +95 -0
  16. package/dist/core/DisTubeHandler.d.ts.map +1 -0
  17. package/dist/core/DisTubeHandler.js +337 -0
  18. package/dist/core/DisTubeHandler.js.map +1 -0
  19. package/dist/core/DisTubeOptions.d.ts +26 -0
  20. package/dist/core/DisTubeOptions.d.ts.map +1 -0
  21. package/dist/core/DisTubeOptions.js +93 -0
  22. package/dist/core/DisTubeOptions.js.map +1 -0
  23. package/dist/core/DisTubeStream.d.ts +52 -0
  24. package/dist/core/DisTubeStream.d.ts.map +1 -0
  25. package/dist/core/DisTubeStream.js +109 -0
  26. package/dist/core/DisTubeStream.js.map +1 -0
  27. package/dist/core/index.d.ts +7 -0
  28. package/dist/core/index.d.ts.map +1 -0
  29. package/dist/core/index.js +19 -0
  30. package/dist/core/index.js.map +1 -0
  31. package/dist/core/manager/BaseManager.d.ts +18 -0
  32. package/dist/core/manager/BaseManager.d.ts.map +1 -0
  33. package/dist/core/manager/BaseManager.js +44 -0
  34. package/dist/core/manager/BaseManager.js.map +1 -0
  35. package/dist/core/manager/QueueManager.d.ts +60 -0
  36. package/dist/core/manager/QueueManager.d.ts.map +1 -0
  37. package/dist/core/manager/QueueManager.js +202 -0
  38. package/dist/core/manager/QueueManager.js.map +1 -0
  39. package/dist/core/manager/index.d.ts +3 -0
  40. package/dist/core/manager/index.d.ts.map +1 -0
  41. package/dist/core/manager/index.js +15 -0
  42. package/dist/core/manager/index.js.map +1 -0
  43. package/dist/core/voice/DJSAdapter.d.ts +4 -0
  44. package/dist/core/voice/DJSAdapter.d.ts.map +1 -0
  45. package/dist/core/voice/DJSAdapter.js +61 -0
  46. package/dist/core/voice/DJSAdapter.js.map +1 -0
  47. package/dist/core/voice/DisTubeVoice.d.ts +85 -0
  48. package/dist/core/voice/DisTubeVoice.d.ts.map +1 -0
  49. package/dist/core/voice/DisTubeVoice.js +246 -0
  50. package/dist/core/voice/DisTubeVoice.js.map +1 -0
  51. package/dist/core/voice/DisTubeVoiceManager.d.ts +41 -0
  52. package/dist/core/voice/DisTubeVoiceManager.d.ts.map +1 -0
  53. package/dist/core/voice/DisTubeVoiceManager.js +67 -0
  54. package/dist/core/voice/DisTubeVoiceManager.js.map +1 -0
  55. package/dist/core/voice/index.d.ts +4 -0
  56. package/dist/core/voice/index.d.ts.map +1 -0
  57. package/dist/core/voice/index.js +16 -0
  58. package/dist/core/voice/index.js.map +1 -0
  59. package/dist/index.d.ts +8 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +23 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/plugin/http.d.ts +8 -0
  64. package/dist/plugin/http.d.ts.map +1 -0
  65. package/dist/plugin/http.js +20 -0
  66. package/dist/plugin/http.js.map +1 -0
  67. package/dist/plugin/https.d.ts +14 -0
  68. package/dist/plugin/https.d.ts.map +1 -0
  69. package/dist/plugin/https.js +50 -0
  70. package/dist/plugin/https.js.map +1 -0
  71. package/dist/plugin/index.d.ts +4 -0
  72. package/dist/plugin/index.d.ts.map +1 -0
  73. package/dist/plugin/index.js +16 -0
  74. package/dist/plugin/index.js.map +1 -0
  75. package/dist/plugin/youtube-dl.d.ts +11 -0
  76. package/dist/plugin/youtube-dl.d.ts.map +1 -0
  77. package/dist/plugin/youtube-dl.js +75 -0
  78. package/dist/plugin/youtube-dl.js.map +1 -0
  79. package/dist/struct/CustomPlugin.d.ts +27 -0
  80. package/dist/struct/CustomPlugin.d.ts.map +1 -0
  81. package/dist/struct/CustomPlugin.js +35 -0
  82. package/dist/struct/CustomPlugin.js.map +1 -0
  83. package/dist/struct/DisTubeError.d.ts +56 -0
  84. package/dist/struct/DisTubeError.d.ts.map +1 -0
  85. package/dist/struct/DisTubeError.js +75 -0
  86. package/dist/struct/DisTubeError.js.map +1 -0
  87. package/dist/struct/ExtractorPlugin.d.ts +29 -0
  88. package/dist/struct/ExtractorPlugin.d.ts.map +1 -0
  89. package/dist/struct/ExtractorPlugin.js +32 -0
  90. package/dist/struct/ExtractorPlugin.js.map +1 -0
  91. package/dist/struct/Playlist.d.ts +42 -0
  92. package/dist/struct/Playlist.d.ts.map +1 -0
  93. package/dist/struct/Playlist.js +104 -0
  94. package/dist/struct/Playlist.js.map +1 -0
  95. package/dist/struct/Plugin.d.ts +82 -0
  96. package/dist/struct/Plugin.d.ts.map +1 -0
  97. package/dist/struct/Plugin.js +108 -0
  98. package/dist/struct/Plugin.js.map +1 -0
  99. package/dist/struct/Queue.d.ts +217 -0
  100. package/dist/struct/Queue.d.ts.map +1 -0
  101. package/dist/struct/Queue.js +481 -0
  102. package/dist/struct/Queue.js.map +1 -0
  103. package/dist/struct/SearchResult.d.ts +28 -0
  104. package/dist/struct/SearchResult.d.ts.map +1 -0
  105. package/dist/struct/SearchResult.js +79 -0
  106. package/dist/struct/SearchResult.js.map +1 -0
  107. package/dist/struct/Song.d.ts +68 -0
  108. package/dist/struct/Song.d.ts.map +1 -0
  109. package/dist/struct/Song.js +229 -0
  110. package/dist/struct/Song.js.map +1 -0
  111. package/dist/struct/TaskQueue.d.ts +33 -0
  112. package/dist/struct/TaskQueue.d.ts.map +1 -0
  113. package/dist/struct/TaskQueue.js +58 -0
  114. package/dist/struct/TaskQueue.js.map +1 -0
  115. package/dist/struct/index.d.ts +10 -0
  116. package/dist/struct/index.d.ts.map +1 -0
  117. package/dist/struct/index.js +22 -0
  118. package/dist/struct/index.js.map +1 -0
  119. package/dist/tsconfig.tsbuildinfo +1 -0
  120. package/dist/type.d.ts +159 -0
  121. package/dist/type.d.ts.map +1 -0
  122. package/dist/type.js +3 -0
  123. package/dist/type.js.map +1 -0
  124. package/dist/util.d.ts +47 -0
  125. package/dist/util.d.ts.map +1 -0
  126. package/dist/util.js +205 -0
  127. package/dist/util.js.map +1 -0
  128. package/package.json +88 -62
  129. package/src/DisTube.js +0 -851
  130. package/src/DisTubeBase.js +0 -39
  131. package/src/DisTubeHandler.js +0 -440
  132. package/src/DisTubeOptions.js +0 -82
  133. package/src/Filter.js +0 -36
  134. package/src/Playlist.js +0 -75
  135. package/src/Plugin/CustomPlugin.js +0 -26
  136. package/src/Plugin/ExtractorPlugin.js +0 -25
  137. package/src/Plugin/Plugin.js +0 -36
  138. package/src/Plugin/http.js +0 -27
  139. package/src/Plugin/https.js +0 -27
  140. package/src/Queue.js +0 -340
  141. package/src/SearchResult.js +0 -57
  142. package/src/Song.js +0 -169
  143. package/src/util.js +0 -65
  144. package/typings/DisTube.d.ts +0 -553
  145. package/typings/DisTubeBase.d.ts +0 -31
  146. package/typings/DisTubeHandler.d.ts +0 -130
  147. package/typings/DisTubeOptions.d.ts +0 -5
  148. package/typings/Filter.d.ts +0 -83
  149. package/typings/Playlist.d.ts +0 -58
  150. package/typings/Plugin/CustomPlugin.d.ts +0 -21
  151. package/typings/Plugin/ExtractorPlugin.d.ts +0 -20
  152. package/typings/Plugin/Plugin.d.ts +0 -31
  153. package/typings/Plugin/http.d.ts +0 -4
  154. package/typings/Plugin/https.d.ts +0 -4
  155. package/typings/Queue.d.ts +0 -227
  156. package/typings/SearchResult.d.ts +0 -51
  157. package/typings/Song.d.ts +0 -153
  158. package/typings/util.d.ts +0 -6
@@ -0,0 +1,794 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DisTube = void 0;
7
+ const ytpl_1 = __importDefault(require("@distube/ytpl"));
8
+ const ytsr_1 = __importDefault(require("@distube/ytsr"));
9
+ const util_1 = require("./util");
10
+ const tiny_typed_emitter_1 = require("tiny-typed-emitter");
11
+ const _1 = require(".");
12
+ /**
13
+ * DisTube class
14
+ * @extends EventEmitter
15
+ */
16
+ class DisTube extends tiny_typed_emitter_1.TypedEmitter {
17
+ /**
18
+ * Create a new DisTube class.
19
+ * @param {Discord.Client} client Discord.JS client
20
+ * @param {DisTubeOptions} [otp] Custom DisTube options
21
+ * @example
22
+ * const Discord = require('discord.js'),
23
+ * DisTube = require('distube'),
24
+ * client = new Discord.Client();
25
+ * // Create a new DisTube
26
+ * const distube = new DisTube.default(client, { searchSongs: 10 });
27
+ * // client.DisTube = distube // make it access easily
28
+ * client.login("Your Discord Bot Token")
29
+ */
30
+ constructor(client, otp = {}) {
31
+ super();
32
+ this.setMaxListeners(1);
33
+ if (!(0, _1.isClientInstance)(client))
34
+ throw new _1.DisTubeError("INVALID_TYPE", "Discord.Client", client, "client");
35
+ /**
36
+ * Discord.JS client
37
+ * @type {Discord.Client}
38
+ */
39
+ this.client = client;
40
+ (0, util_1.checkIntents)(client.options);
41
+ /**
42
+ * DisTube options
43
+ * @type {DisTubeOptions}
44
+ */
45
+ this.options = new _1.Options(otp);
46
+ /**
47
+ * Voice connections manager
48
+ * @type {DisTubeVoiceManager}
49
+ */
50
+ this.voices = new _1.DisTubeVoiceManager(this);
51
+ /**
52
+ * DisTube's Handler
53
+ * @type {DisTubeHandler}
54
+ * @private
55
+ */
56
+ this.handler = new _1.DisTubeHandler(this);
57
+ /**
58
+ * Queues manager
59
+ * @type {QueueManager}
60
+ */
61
+ this.queues = new _1.QueueManager(this);
62
+ /**
63
+ * DisTube filters
64
+ * @type {Filters}
65
+ */
66
+ this.filters = _1.defaultFilters;
67
+ Object.assign(this.filters, this.options.customFilters);
68
+ // Default plugin
69
+ this.options.plugins.push(new _1.HTTPPlugin(), new _1.HTTPSPlugin());
70
+ if (this.options.youtubeDL)
71
+ this.options.plugins.push(new _1.YouTubeDLPlugin(this.options.updateYouTubeDL));
72
+ this.options.plugins.map(p => p.init(this));
73
+ /**
74
+ * Extractor Plugins
75
+ * @type {ExtractorPlugin[]}
76
+ * @private
77
+ */
78
+ this.extractorPlugins = this.options.plugins.filter((p) => p.type === "extractor");
79
+ /**
80
+ * Custom Plugins
81
+ * @type {CustomPlugin[]}
82
+ * @private
83
+ */
84
+ this.customPlugins = this.options.plugins.filter((p) => p.type === "custom");
85
+ }
86
+ /**
87
+ * Shorthand method for {@link DisTube#playVoiceChannel}
88
+ * @returns {Promise<void>}
89
+ * @param {Discord.Message} message A message from guild channel
90
+ * @param {string|Song|SearchResult|Playlist} song URL | Search string |
91
+ * {@link Song} | {@link SearchResult} | {@link Playlist}
92
+ * @param {Object} [options] Optional options
93
+ * @param {boolean} [options.skip=false] Skip the playing song (if exists) and play the added song/playlist instantly
94
+ * @param {boolean} [options.unshift=false] Add the song/playlist to the beginning of the queue
95
+ * (after the playing song if exists)
96
+ * @example
97
+ * client.on('message', (message) => {
98
+ * if (!message.content.startsWith(config.prefix)) return;
99
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
100
+ * const command = args.shift();
101
+ * if (command == "play")
102
+ * distube.play(message, args.join(" "));
103
+ * });
104
+ */
105
+ async play(message, song, options = {}) {
106
+ if (!song)
107
+ throw new _1.DisTubeError("INVALID_TYPE", ["string", "Song", "SearchResult", "Playlist"], song, "song");
108
+ if (!(0, _1.isMessageInstance)(message))
109
+ throw new _1.DisTubeError("INVALID_TYPE", "Discord.Message", message, "message");
110
+ if (typeof options !== "object" || Array.isArray(options)) {
111
+ throw new _1.DisTubeError("INVALID_TYPE", "object", options, "options");
112
+ }
113
+ const textChannel = message.channel;
114
+ const { skip, unshift } = Object.assign({ skip: false, unshift: false }, options);
115
+ const member = message.member;
116
+ const voiceChannel = member.voice.channel;
117
+ if (!voiceChannel)
118
+ throw new _1.DisTubeError("NOT_IN_VOICE");
119
+ await this.playVoiceChannel(voiceChannel, song, {
120
+ member,
121
+ textChannel,
122
+ skip,
123
+ message,
124
+ unshift,
125
+ });
126
+ }
127
+ /**
128
+ * Play / add a song or playlist from url. Search and play a song if it is not a valid url.
129
+ * Emit {@link DisTube#addList}, {@link DisTube#addSong} or {@link DisTube#playSong} after executing
130
+ * @returns {Promise<void>}
131
+ * @param {Discord.VoiceChannel|Discord.StageChannel} voiceChannel The voice channel will be joined
132
+ * @param {string|Song|SearchResult|Playlist} song URL | Search string |
133
+ * {@link Song} | {@link SearchResult} | {@link Playlist}
134
+ * @param {Object} [options] Optional options
135
+ * @param {boolean} [options.skip=false] Skip the playing song (if exists) and play the added song/playlist instantly
136
+ * @param {boolean} [options.unshift=false] Add the song/playlist to the beginning of the queue
137
+ * (after the playing song if exists)
138
+ * @param {Discord.GuildMember} [options.member] Requested user (default is your bot)
139
+ * @param {Discord.TextChannel} [options.textChannel] Default {@link Queue#textChannel} (if the queue wasn't created)
140
+ * @param {Discord.Message} [options.message] Called message (For built-in search events. If this is a {@link https://developer.mozilla.org/en-US/docs/Glossary/Falsy|falsy value}, it will play the first result instead)
141
+ */
142
+ async playVoiceChannel(voiceChannel, song, options = {}) {
143
+ var _a;
144
+ if (!(0, _1.isSupportedVoiceChannel)(voiceChannel))
145
+ throw new _1.DisTubeError("NOT_SUPPORTED_VOICE");
146
+ if (typeof options !== "object" || Array.isArray(options)) {
147
+ throw new _1.DisTubeError("INVALID_TYPE", "object", options, "options");
148
+ }
149
+ const { textChannel, member, skip, message, unshift } = Object.assign({
150
+ member: voiceChannel.guild.me,
151
+ skip: false,
152
+ unshift: false,
153
+ }, options);
154
+ if (message && !(0, _1.isMessageInstance)(message)) {
155
+ throw new _1.DisTubeError("INVALID_TYPE", ["Discord.Message", "a falsy value"], message, "options.message");
156
+ }
157
+ try {
158
+ if (typeof song === "string") {
159
+ for (const plugin of this.customPlugins) {
160
+ if (await plugin.validate(song)) {
161
+ return plugin.play(voiceChannel, song, member, textChannel, skip, unshift);
162
+ }
163
+ }
164
+ }
165
+ let queue = this.getQueue(voiceChannel);
166
+ const queuing = queue && !queue.taskQueue.hasResolveTask;
167
+ if (queuing)
168
+ await (queue === null || queue === void 0 ? void 0 : queue.taskQueue.queuing(true));
169
+ try {
170
+ if (song instanceof _1.SearchResult && song.type === "playlist")
171
+ song = song.url;
172
+ if (typeof song === "string" && ytpl_1.default.validateID(song))
173
+ song = await this.handler.resolvePlaylist(member, song);
174
+ if (typeof song === "string" && !(0, util_1.isURL)(song)) {
175
+ if (!message)
176
+ song = (await this.search(song, { limit: 1 }))[0];
177
+ else
178
+ song = await this.handler.searchSong(message, song);
179
+ }
180
+ song = await this.handler.resolveSong(member, song);
181
+ if (!song)
182
+ return;
183
+ if (song instanceof _1.Playlist) {
184
+ await this.handler.handlePlaylist(voiceChannel, song, textChannel, skip, unshift);
185
+ }
186
+ else if (!this.options.nsfw && song.age_restricted && !(textChannel === null || textChannel === void 0 ? void 0 : textChannel.nsfw)) {
187
+ throw new _1.DisTubeError("NON_NSFW");
188
+ }
189
+ else {
190
+ queue = this.getQueue(voiceChannel);
191
+ if (queue) {
192
+ queue.addToQueue(song, skip || unshift ? 1 : -1);
193
+ if (skip)
194
+ queue.skip();
195
+ else
196
+ this.emit("addSong", queue, song);
197
+ }
198
+ else {
199
+ const newQueue = await this.handler.createQueue(voiceChannel, song, textChannel);
200
+ if (newQueue instanceof _1.Queue) {
201
+ if (this.options.emitAddSongWhenCreatingQueue)
202
+ this.emit("addSong", newQueue, song);
203
+ this.emit("playSong", newQueue, song);
204
+ }
205
+ }
206
+ }
207
+ }
208
+ finally {
209
+ if (queuing)
210
+ queue === null || queue === void 0 ? void 0 : queue.taskQueue.resolve();
211
+ }
212
+ }
213
+ catch (e) {
214
+ if (!(e instanceof _1.DisTubeError)) {
215
+ try {
216
+ e.name = "PlayError";
217
+ e.message = `${((_a = song) === null || _a === void 0 ? void 0 : _a.url) || song}\n${e.message}`;
218
+ }
219
+ catch { }
220
+ }
221
+ this.emitError(e, textChannel);
222
+ }
223
+ }
224
+ /**
225
+ * <info>Shorthand method of {@link DisTubeHandler#createCustomPlaylist} and {@link DisTube#playVoiceChannel}
226
+ *
227
+ * If you doesn't have a user message (interaction,...),
228
+ * see {@link DisTubeHandler#createCustomPlaylist} example</info>
229
+ *
230
+ * Play or add array of video urls.
231
+ * {@link DisTube#event:playSong} or {@link DisTube#event:addList} will be emitted
232
+ * with `playlist`'s properties include `properties` parameter's properties such as
233
+ * `user`, `songs`, `duration`, `formattedDuration`, `thumbnail` like {@link Playlist}
234
+ * @returns {Promise<void>}
235
+ * @param {Discord.Message} message A message from guild channel
236
+ * @param {Array<string|Song|SearchResult>} songs Array of url, Song or SearchResult
237
+ * @param {Object} [properties={}] Additional properties such as `name`
238
+ * @param {Object} [options] Optional options
239
+ * @param {boolean} [options.skip=false] Skip the playing song (if exists) and play the added song/playlist instantly
240
+ * @param {boolean} [options.unshift=false] Add the song/playlist to the beginning of the queue
241
+ * (after the playing song if exists)
242
+ * @param {boolean} [options.parallel=true] Whether or not fetch the songs in parallel
243
+ * @example
244
+ * const songs = ["https://www.youtube.com/watch?v=xxx", "https://www.youtube.com/watch?v=yyy"];
245
+ * distube.playCustomPlaylist(message, songs, { name: "My playlist name" });
246
+ * // Fetching custom playlist sequentially (reduce lag for low specs)
247
+ * distube.playCustomPlaylist(message, songs, { name: "My playlist name" }, false, false);
248
+ */
249
+ async playCustomPlaylist(message, songs, properties = {}, options = {}) {
250
+ try {
251
+ if (typeof options !== "object" || Array.isArray(options)) {
252
+ throw new _1.DisTubeError("INVALID_TYPE", "object", options, "options");
253
+ }
254
+ const { skip, unshift, parallel } = Object.assign({
255
+ skip: false,
256
+ unshift: false,
257
+ parallel: true,
258
+ }, options);
259
+ const queue = this.getQueue(message);
260
+ const queuing = queue && !queue.taskQueue.hasResolveTask;
261
+ if (queuing)
262
+ await (queue === null || queue === void 0 ? void 0 : queue.taskQueue.queuing(true));
263
+ try {
264
+ const playlist = await this.handler.createCustomPlaylist(message, songs, properties, parallel);
265
+ await this.handler.handlePlaylist(message, playlist, message.channel, skip, unshift);
266
+ }
267
+ finally {
268
+ if (queuing)
269
+ queue === null || queue === void 0 ? void 0 : queue.taskQueue.resolve();
270
+ }
271
+ }
272
+ catch (e) {
273
+ this.emitError(e, message.channel);
274
+ }
275
+ }
276
+ /**
277
+ * Search for a song.
278
+ * You can customize how user answers instead of send a number.
279
+ * Then use {@link DisTube#play} or {@link DisTube#playVoiceChannel} to play it.
280
+ * @param {string} string The string search for
281
+ * @param {Object} options Search options
282
+ * @param {number} [options.limit=10] Limit the results
283
+ * @param {'video'|'playlist'} [options.type='video'] Type of results (`video` or `playlist`).
284
+ * @param {boolean} [options.safeSearch=false] Whether or not use safe search (YouTube restricted mode)
285
+ * @throws {Error}
286
+ * @returns {Promise<Array<SearchResult>>} Array of results
287
+ */
288
+ async search(string, options = {}) {
289
+ const opts = Object.assign({ type: "video", limit: 10, safeSearch: false }, options);
290
+ if (typeof opts.type !== "string" || !["video", "playlist"].includes(opts.type)) {
291
+ throw new _1.DisTubeError("INVALID_TYPE", ["video", "playlist"], opts.type, "options.type");
292
+ }
293
+ if (typeof opts.limit !== "number")
294
+ throw new _1.DisTubeError("INVALID_TYPE", "number", opts.limit, "options.limit");
295
+ if (opts.limit < 1)
296
+ throw new _1.DisTubeError("NUMBER_COMPARE", "option.limit", "bigger or equal to", 1);
297
+ if (typeof opts.safeSearch !== "boolean") {
298
+ throw new _1.DisTubeError("INVALID_TYPE", "boolean", opts.safeSearch, "options.safeSearch");
299
+ }
300
+ try {
301
+ const search = await (0, ytsr_1.default)(string, opts);
302
+ const results = search.items.map(i => new _1.SearchResult(i));
303
+ if (results.length === 0)
304
+ throw new _1.DisTubeError("NO_RESULT");
305
+ return results;
306
+ }
307
+ catch (e) {
308
+ if (options.retried)
309
+ throw e;
310
+ options.retried = true;
311
+ return this.search(string, options);
312
+ }
313
+ }
314
+ /**
315
+ * Get the guild queue
316
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
317
+ * @returns {Queue?}
318
+ * @throws {Error}
319
+ * @example
320
+ * client.on('message', (message) => {
321
+ * if (!message.content.startsWith(config.prefix)) return;
322
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
323
+ * const command = args.shift();
324
+ * if (command == "queue") {
325
+ * const queue = distube.getQueue(message);
326
+ * message.channel.send('Current queue:\n' + queue.songs.map((song, id) =>
327
+ * `**${id+1}**. [${song.name}](${song.url}) - \`${song.formattedDuration}\``
328
+ * ).join("\n"));
329
+ * }
330
+ * });
331
+ */
332
+ getQueue(queue) {
333
+ return this.queues.get(queue);
334
+ }
335
+ /**
336
+ * Pause the guild stream
337
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
338
+ * @returns {Queue} The guild queue
339
+ * @throws {Error}
340
+ */
341
+ pause(queue) {
342
+ const q = this.getQueue(queue);
343
+ if (!q)
344
+ throw new _1.DisTubeError("NO_QUEUE");
345
+ return q.pause();
346
+ }
347
+ /**
348
+ * Resume the guild stream
349
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
350
+ * @returns {Queue} The guild queue
351
+ * @throws {Error}
352
+ */
353
+ resume(queue) {
354
+ const q = this.getQueue(queue);
355
+ if (!q)
356
+ throw new _1.DisTubeError("NO_QUEUE");
357
+ return q.resume();
358
+ }
359
+ /**
360
+ * Stop the guild stream
361
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
362
+ * @returns {Promise<void>}
363
+ * @throws {Error}
364
+ * @example
365
+ * client.on('message', (message) => {
366
+ * if (!message.content.startsWith(config.prefix)) return;
367
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
368
+ * const command = args.shift();
369
+ * if (command == "stop") {
370
+ * distube.stop(message);
371
+ * message.channel.send("Stopped the queue!");
372
+ * }
373
+ * });
374
+ */
375
+ stop(queue) {
376
+ const q = this.getQueue(queue);
377
+ if (!q)
378
+ throw new _1.DisTubeError("NO_QUEUE");
379
+ return q.stop();
380
+ }
381
+ /**
382
+ * Set the guild stream's volume
383
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
384
+ * @param {number} percent The percentage of volume you want to set
385
+ * @returns {Queue} The guild queue
386
+ * @throws {Error}
387
+ * @example
388
+ * client.on('message', (message) => {
389
+ * if (!message.content.startsWith(config.prefix)) return;
390
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
391
+ * const command = args.shift();
392
+ * if (command == "volume")
393
+ * distube.setVolume(message, Number(args[0]));
394
+ * });
395
+ */
396
+ setVolume(queue, percent) {
397
+ const q = this.getQueue(queue);
398
+ if (!q)
399
+ throw new _1.DisTubeError("NO_QUEUE");
400
+ return q.setVolume(percent);
401
+ }
402
+ /**
403
+ * Skip the playing song if there is a next song in the queue.
404
+ * <info>If {@link Queue#autoplay} is `true` and there is no up next song,
405
+ * DisTube will add and play a related song.</info>
406
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
407
+ * @returns {Promise<Song>} The new Song will be played
408
+ * @throws {Error}
409
+ * @example
410
+ * client.on('message', (message) => {
411
+ * if (!message.content.startsWith(config.prefix)) return;
412
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
413
+ * const command = args.shift();
414
+ * if (command == "skip")
415
+ * distube.skip(message);
416
+ * });
417
+ */
418
+ skip(queue) {
419
+ const q = this.getQueue(queue);
420
+ if (!q)
421
+ throw new _1.DisTubeError("NO_QUEUE");
422
+ return q.skip();
423
+ }
424
+ /**
425
+ * Play the previous song
426
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
427
+ * @returns {Promise<Song>} The new Song will be played
428
+ * @throws {Error}
429
+ * @example
430
+ * client.on('message', (message) => {
431
+ * if (!message.content.startsWith(config.prefix)) return;
432
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
433
+ * const command = args.shift();
434
+ * if (command == "previous")
435
+ * distube.previous(message);
436
+ * });
437
+ */
438
+ previous(queue) {
439
+ const q = this.getQueue(queue);
440
+ if (!q)
441
+ throw new _1.DisTubeError("NO_QUEUE");
442
+ return q.previous();
443
+ }
444
+ /**
445
+ * Shuffle the guild queue songs
446
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
447
+ * @returns {Promise<Queue>} The guild queue
448
+ * @example
449
+ * client.on('message', (message) => {
450
+ * if (!message.content.startsWith(config.prefix)) return;
451
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
452
+ * const command = args.shift();
453
+ * if (command == "shuffle")
454
+ * distube.shuffle(message);
455
+ * });
456
+ */
457
+ shuffle(queue) {
458
+ const q = this.getQueue(queue);
459
+ if (!q)
460
+ throw new _1.DisTubeError("NO_QUEUE");
461
+ return q.shuffle();
462
+ }
463
+ /**
464
+ * Jump to the song number in the queue.
465
+ * The next one is 1, 2,...
466
+ * The previous one is -1, -2,...
467
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
468
+ * @param {number} num The song number to play
469
+ * @returns {Promise<Queue>} The guild queue
470
+ * @throws {Error} if `num` is invalid number (0 < num < {@link Queue#songs}.length)
471
+ * @example
472
+ * client.on('message', (message) => {
473
+ * if (!message.content.startsWith(config.prefix)) return;
474
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
475
+ * const command = args.shift();
476
+ * if (command == "jump")
477
+ * distube.jump(message, parseInt(args[0]))
478
+ * .catch(err => message.channel.send("Invalid song number."));
479
+ * });
480
+ */
481
+ jump(queue, num) {
482
+ const q = this.getQueue(queue);
483
+ if (!q)
484
+ throw new _1.DisTubeError("NO_QUEUE");
485
+ return q.jump(num);
486
+ }
487
+ /**
488
+ * Set the repeat mode of the guild queue.\
489
+ * Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`
490
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
491
+ * @param {RepeatMode?} [mode] The repeat modes (toggle if `undefined`)
492
+ * @returns {RepeatMode} The new repeat mode
493
+ * @example
494
+ * client.on('message', (message) => {
495
+ * if (!message.content.startsWith(config.prefix)) return;
496
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
497
+ * const command = args.shift();
498
+ * if (command == "repeat") {
499
+ * let mode = distube.setRepeatMode(message, parseInt(args[0]));
500
+ * mode = mode ? mode == 2 ? "Repeat queue" : "Repeat song" : "Off";
501
+ * message.channel.send("Set repeat mode to `" + mode + "`");
502
+ * }
503
+ * });
504
+ * @example
505
+ * const { RepeatMode } = require("distube");
506
+ * let mode;
507
+ * switch(distube.setRepeatMode(message, parseInt(args[0]))) {
508
+ * case RepeatMode.DISABLED:
509
+ * mode = "Off";
510
+ * break;
511
+ * case RepeatMode.SONG:
512
+ * mode = "Repeat a song";
513
+ * break;
514
+ * case RepeatMode.QUEUE:
515
+ * mode = "Repeat all queue";
516
+ * break;
517
+ * }
518
+ * message.channel.send("Set repeat mode to `" + mode + "`");
519
+ */
520
+ setRepeatMode(queue, mode) {
521
+ const q = this.getQueue(queue);
522
+ if (!q)
523
+ throw new _1.DisTubeError("NO_QUEUE");
524
+ return q.setRepeatMode(mode);
525
+ }
526
+ /**
527
+ * Toggle autoplay mode
528
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
529
+ * @returns {boolean} Autoplay mode state
530
+ * @throws {Error}
531
+ * @example
532
+ * client.on('message', (message) => {
533
+ * if (!message.content.startsWith(config.prefix)) return;
534
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
535
+ * const command = args.shift();
536
+ * if (command == "autoplay") {
537
+ * const mode = distube.toggleAutoplay(message);
538
+ * message.channel.send("Set autoplay mode to `" + (mode ? "On" : "Off") + "`");
539
+ * }
540
+ * });
541
+ */
542
+ toggleAutoplay(queue) {
543
+ const q = this.getQueue(queue);
544
+ if (!q)
545
+ throw new _1.DisTubeError("NO_QUEUE");
546
+ q.autoplay = !q.autoplay;
547
+ return q.autoplay;
548
+ }
549
+ /**
550
+ * Add related song to the queue
551
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
552
+ * @returns {Promise<Song>} The guild queue
553
+ */
554
+ addRelatedSong(queue) {
555
+ const q = this.getQueue(queue);
556
+ if (!q)
557
+ throw new _1.DisTubeError("NO_QUEUE");
558
+ return q.addRelatedSong();
559
+ }
560
+ /**
561
+ * Enable or disable filter(s) of the queue.
562
+ * Available filters: {@link Filters}
563
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
564
+ * @param {string|false} filter A filter name, `false` to clear all the filters
565
+ * @param {boolean} [force=false] Force enable the input filter(s) even if it's enabled
566
+ * @returns {Array<string>} Enabled filters.
567
+ * @example
568
+ * client.on('message', (message) => {
569
+ * if (!message.content.startsWith(config.prefix)) return;
570
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
571
+ * const command = args.shift();
572
+ * if ([`3d`, `bassboost`, `echo`, `karaoke`, `nightcore`, `vaporwave`].includes(command)) {
573
+ * const filter = distube.setFilter(message, command);
574
+ * message.channel.send("Current queue filter: " + (filter.join(", ") || "Off"));
575
+ * }
576
+ * });
577
+ */
578
+ setFilter(queue, filter, force = false) {
579
+ const q = this.getQueue(queue);
580
+ if (!q)
581
+ throw new _1.DisTubeError("NO_QUEUE");
582
+ return q.setFilter(filter, force);
583
+ }
584
+ /**
585
+ * Set the playing time to another position
586
+ * @param {GuildIDResolvable} queue The type can be resolved to give a {@link Queue}
587
+ * @param {number} time Time in seconds
588
+ * @returns {Queue} Seeked queue
589
+ * @example
590
+ * client.on('message', message => {
591
+ * if (!message.content.startsWith(config.prefix)) return;
592
+ * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
593
+ * const command = args.shift();
594
+ * if (command = 'seek')
595
+ * distube.seek(message, Number(args[0]));
596
+ * });
597
+ */
598
+ seek(queue, time) {
599
+ const q = this.getQueue(queue);
600
+ if (!q)
601
+ throw new _1.DisTubeError("NO_QUEUE");
602
+ return q.seek(time);
603
+ }
604
+ /* eslint-disable no-console */
605
+ /**
606
+ * Emit error event
607
+ * @param {Error} error error
608
+ * @param {Discord.TextChannel?} channel Text channel where the error is encountered.
609
+ * @private
610
+ */
611
+ emitError(error, channel) {
612
+ if (!channel || !(0, _1.isTextChannelInstance)(channel)) {
613
+ console.error(error);
614
+ console.warn("This is logged because <Queue>.textChannel is undefined");
615
+ }
616
+ else if (this.listeners("error").length) {
617
+ this.emit("error", channel, error);
618
+ }
619
+ else {
620
+ console.error(error);
621
+ console.warn("Unhandled 'error' event.");
622
+ console.warn("See: https://distube.js.org/#/docs/DisTube/stable/class/DisTube?scrollTo=e-error and https://nodejs.org/api/events.html#events_error_events");
623
+ }
624
+ }
625
+ }
626
+ exports.DisTube = DisTube;
627
+ exports.default = DisTube;
628
+ /**
629
+ * Emitted after DisTube add a new playlist to the playing {@link Queue}.
630
+ *
631
+ * @event DisTube#addList
632
+ * @param {Queue} queue The guild queue
633
+ * @param {Playlist} playlist Playlist info
634
+ * @example
635
+ * distube.on("addList", (queue, playlist) => queue.textChannel.send(
636
+ * `Added \`${playlist.name}\` playlist (${playlist.songs.length} songs) to the queue!`
637
+ * ));
638
+ */
639
+ /**
640
+ * Emitted after DisTube add a new song to the playing {@link Queue}.
641
+ *
642
+ * @event DisTube#addSong
643
+ * @param {Queue} queue The guild queue
644
+ * @param {Song} song Added song
645
+ * @example
646
+ * distube.on("addSong", (queue, song) => queue.textChannel.send(
647
+ * `Added ${song.name} - \`${song.formattedDuration}\` to the queue by ${song.user}.`
648
+ * ));
649
+ */
650
+ /**
651
+ * Emitted when there is no user in the voice channel,
652
+ * {@link DisTubeOptions}.leaveOnEmpty is `true` and there is a playing queue.
653
+ *
654
+ * If there is no playing queue (stopped and {@link DisTubeOptions}.leaveOnStop is `false`),
655
+ * it will leave the channel without emitting this event.
656
+ * @event DisTube#empty
657
+ * @param {Queue} queue The guild queue
658
+ * @example
659
+ * distube.on("empty", queue => queue.textChannel.send("Channel is empty. Leaving the channel"))
660
+ */
661
+ /**
662
+ * Emitted when DisTube encounters an error.
663
+ *
664
+ * @event DisTube#error
665
+ * @param {Discord.TextChannel} channel Text channel where the error is encountered.
666
+ * @param {Error} error The error encountered
667
+ * @example
668
+ * distube.on("error", (channel, error) => channel.send(
669
+ * "An error encountered: " + error
670
+ * ));
671
+ */
672
+ /**
673
+ * Emitted when there is no more song in the queue and {@link Queue#autoplay} is `false`.
674
+ * DisTube will leave voice channel if {@link DisTubeOptions}.leaveOnFinish is `true`.
675
+ *
676
+ * @event DisTube#finish
677
+ * @param {Queue} queue The guild queue
678
+ * @example
679
+ * distube.on("finish", queue => queue.textChannel.send("No more song in queue"));
680
+ */
681
+ /**
682
+ * Emitted when DisTube initialize a queue to change queue default properties.
683
+ *
684
+ * @event DisTube#initQueue
685
+ * @param {Queue} queue The guild queue
686
+ * @example
687
+ * distube.on("initQueue", queue => {
688
+ * queue.autoplay = false;
689
+ * queue.volume = 100;
690
+ * });
691
+ */
692
+ /**
693
+ * Emitted when {@link Queue#autoplay} is `true`, {@link Queue#songs} is empty,
694
+ * and DisTube cannot find related songs to play.
695
+ *
696
+ * @event DisTube#noRelated
697
+ * @param {Queue} queue The guild queue
698
+ * @example
699
+ * distube.on("noRelated", queue => queue.textChannel.send("Can't find related video to play."));
700
+ */
701
+ /**
702
+ * Emitted when DisTube play a song.
703
+ *
704
+ * If {@link DisTubeOptions}.emitNewSongOnly is `true`,
705
+ * this event is not emitted when looping a song or next song is the previous one.
706
+ *
707
+ * @event DisTube#playSong
708
+ * @param {Queue} queue The guild queue
709
+ * @param {Song} song Playing song
710
+ * @example
711
+ * distube.on("playSong", (queue, song) => queue.textChannel.send(
712
+ * `Playing \`${song.name}\` - \`${song.formattedDuration}\`\nRequested by: ${song.user}`
713
+ * ));
714
+ */
715
+ /**
716
+ * Emitted when DisTube cannot find any results for the query.
717
+ *
718
+ * @event DisTube#searchNoResult
719
+ * @param {Discord.Message} message The user message called play method
720
+ * @param {string} query The search query
721
+ * @example
722
+ * distube.on("searchNoResult", (message, query) => message.channel.send(`No result found for ${query}!`));
723
+ */
724
+ /**
725
+ * Emitted when {@link DisTubeOptions|DisTubeOptions.searchSongs} bigger than 0,
726
+ * and song param of {@link DisTube#playVoiceChannel} is invalid url.
727
+ * DisTube will wait for user's next message to choose a song manually.
728
+ * <info>{@link https://support.google.com/youtube/answer/7354993|Safe search} is enabled
729
+ * if {@link DisTubeOptions}.nsfw is disabled and the message's channel is not a nsfw channel.</info>
730
+ *
731
+ * @event DisTube#searchResult
732
+ * @param {Discord.Message} message The user message called play method
733
+ * @param {Array<SearchResult>} results Searched results
734
+ * @param {string} query The search query
735
+ * @example
736
+ * // DisTubeOptions.searchSongs > 0
737
+ * distube.on("searchResult", (message, results) => {
738
+ * message.channel.send(`**Choose an option from below**\n${
739
+ * results.map((song, i) => `**${i + 1}**. ${song.name} - \`${song.formattedDuration}\``).join("\n")
740
+ * }\n*Enter anything else or wait 60 seconds to cancel*`);
741
+ * });
742
+ */
743
+ /**
744
+ * Emitted when {@link DisTubeOptions|DisTubeOptions.searchSongs} bigger than 0,
745
+ * and the search canceled due to {@link DisTubeOptions|DisTubeOptions.searchTimeout}.
746
+ *
747
+ * @event DisTube#searchCancel
748
+ * @param {Discord.Message} message The user message called play method
749
+ * @param {string} query The search query
750
+ * @example
751
+ * // DisTubeOptions.searchSongs > 0
752
+ * distube.on("searchCancel", (message) => message.channel.send(`Searching canceled`));
753
+ */
754
+ /**
755
+ * Emitted when {@link DisTubeOptions|DisTubeOptions.searchSongs} bigger than 0,
756
+ * and the search canceled due to user's next message is not a number or out of results range.
757
+ *
758
+ * @event DisTube#searchInvalidAnswer
759
+ * @param {Discord.Message} message The user message called play method
760
+ * @param {Discord.Message} answer The answered message of user
761
+ * @param {string} query The search query
762
+ * @example
763
+ * // DisTubeOptions.searchSongs > 0
764
+ * distube.on("searchInvalidAnswer", (message) => message.channel.send(`You answered an invalid number!`));
765
+ */
766
+ /**
767
+ * Emitted when {@link DisTubeOptions|DisTubeOptions.searchSongs} bigger than 0,
768
+ * and after the user chose a search result to play.
769
+ *
770
+ * @event DisTube#searchDone
771
+ * @param {Discord.Message} message The user message called play method
772
+ * @param {Discord.Message} answer The answered message of user
773
+ * @param {string} query The search query
774
+ */
775
+ /**
776
+ * Emitted when the bot is disconnected to a voice channel.
777
+ *
778
+ * @event DisTube#disconnect
779
+ * @param {Queue} queue The guild queue
780
+ */
781
+ /**
782
+ * Emitted when a {@link Queue} is deleted with any reasons.
783
+ *
784
+ * @event DisTube#deleteQueue
785
+ * @param {Queue} queue The guild queue
786
+ */
787
+ /**
788
+ * Emitted when DisTube finished a song.
789
+ *
790
+ * @event DisTube#finishSong
791
+ * @param {Queue} queue The guild queue
792
+ * @param {Song} song Finished song
793
+ */
794
+ //# sourceMappingURL=DisTube.js.map