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