· 5 years ago · Jul 03, 2020, 05:42 AM
1const ytdl = require('ytdl-core-discord');
2const { YTSearcher } = require('ytsearcher');
3const ytpl = require('ytpl');
4const Discord = require('discord.js');
5let fetch = require("node-fetch")
6const PACKAGE = require('./package.json');
7
8exports.start = (client, options) => {
9 try {
10 if (process.version.slice(1).split('.')[0] < 8) console.error(new Error(`[MusicBot] Error`));
11
12 function moduleAvailable(name) {
13 try {
14 require.resolve(name);
15 return true;
16 } catch (e) {}
17 return false;
18 };
19 if (moduleAvailable("ffmpeg-binaries")) console.error(new Error("[MUSIC] ffmpeg-binaries was found, this will likely cause problems"));
20 if (!moduleAvailable("ytdl-core-discord") || !moduleAvailable("ytpl") || !moduleAvailable("ytsearcher")) console.error(new Error("[MUSIC] one or more youtube specific modules not found, this module will not work"));
21
22 class Music {
23 constructor(client, options) {
24 // Data Objects
25 this.commands = new Map();
26 this.commandsArray = [];
27 this.aliases = new Map();
28 this.queues = new Map();
29 this.client = client;
30
31 // Play Command options
32 this.play = {
33 enabled: (options.play == undefined ? true : (options.play && typeof options.play.enabled !== 'undefined' ? options.play && options.play.enabled : true)),
34 run: "playFunction",
35 alt: (options && options.play && options.play.alt) || [],
36 help: (options && options.play && options.play.help) || "Play a song. Enter the URL or name.",
37 name: (options && options.play && options.play.name) || "play",
38 usage: (options && options.play && options.play.usage) || null,
39 exclude: Boolean((options && options.play && options.play.exclude)),
40 masked: "play"
41 };
42
43 // MusicHelp Command options
44 this.musichelp = {
45 enabled: (options.musichelp == undefined ? true : (options.musichelp && typeof options.musichelp.enabled !== 'undefined' ? options.musichelp && options.musichelp.enabled : true)),
46 run: "helpFunction",
47 alt: (options && options.musichelp && options.musichelp.alt) || [],
48 help: (options && options.musichelp && options.musichelp.musichelp) || "To view information on existing commands.",
49 name: (options && options.musichelp && options.musichelp.name) || "musichelp",
50 usage: (options && options.musichelp && options.musichelp.usage) || null,
51 exclude: Boolean((options && options.musichelp && options.musichelp.exclude)),
52 masked: "musichelp"
53 };
54
55 // Pause Command options
56 this.pause = {
57 enabled: (options.pause == undefined ? true : (options.pause && typeof options.pause.enabled !== 'undefined' ? options.pause && options.pause.enabled : true)),
58 run: "pauseFunction",
59 alt: (options && options.pause && options.pause.alt) || [],
60 help: (options && options.pause && options.pause.help) || "Pause the song.",
61 name: (options && options.pause && options.pause.name) || "pause",
62 usage: (options && options.pause && options.pause.usage) || null,
63 exclude: Boolean((options && options.pause && options.pause.exclude)),
64 masked: "pause"
65 };
66
67 // Resume Command options
68 this.resume = {
69 enabled: (options.resume == undefined ? true : (options.resume && typeof options.resume.enabled !== 'undefined' ? options.resume && options.resume.enabled : true)),
70 run: "resumeFunction",
71 alt: (options && options.resume && options.resume.alt) || [],
72 help: (options && options.resume && options.resume.help) || "Resume a slow song.",
73 name: (options && options.resume && options.resume.name) || "resume",
74 usage: (options && options.resume && options.resume.usage) || null,
75 exclude: Boolean((options && options.resume && options.resume.exclude)),
76 masked: "resume"
77 };
78
79 // Leave Command options
80 this.leave = {
81 enabled: (options.leave == undefined ? true : (options.leave && typeof options.leave.enabled !== 'undefined' ? options.leave && options.leave.enabled : true)),
82 run: "leaveFunction",
83 alt: (options && options.leave && options.leave.alt) || [],
84 help: (options && options.leave && options.leave.help) || "Disconnect the bot from the voice channel.",
85 name: (options && options.leave && options.leave.name) || "leave",
86 usage: (options && options.leave && options.leave.usage) || null,
87 exclude: Boolean((options && options.leave && options.leave.exclude)),
88 masked: "leave"
89 };
90
91 // Queue Command options
92 this.queue = {
93 enabled: (options.queue == undefined ? true : (options.queue && typeof options.queue.enabled !== 'undefined' ? options.queue && options.queue.enabled : true)),
94 run: "queueFunction",
95 alt: (options && options.queue && options.queue.alt) || [],
96 help: (options && options.queue && options.queue.help) || "see the list of songs.",
97 name: (options && options.queue && options.queue.name) || "queue",
98 usage: (options && options.queue && options.queue.usage) || null,
99 exclude: Boolean((options && options.queue && options.queue.exclude)),
100 masked: "queue"
101 };
102
103 // Nowplaying Command options
104 this.np = {
105 enabled: (options.np == undefined ? true : (options.np && typeof options.np.enabled !== 'undefined' ? options.np && options.np.enabled : true)),
106 run: "npFunction",
107 alt: (options && options.np && options.np.alt) || [],
108 help: (options && options.np && options.np.help) || "Show the song that is playing.",
109 name: (options && options.np && options.np.name) || "np",
110 usage: (options && options.np && options.np.usage) || null,
111 exclude: Boolean((options && options.np && options.np.exclude)),
112 masked: "np"
113 };
114
115 // Loop Command options
116 this.loop = {
117 enabled: (options.loop == undefined ? true : (options.loop && typeof options.loop.enabled !== 'undefined' ? options.loop && options.loop.enabled : true)),
118 run: "loopFunction",
119 alt: (options && options.loop && options.loop.alt) || [],
120 help: (options && options.loop && options.loop.help) || "Sets a loop state for the queue.",
121 name: (options && options.loop && options.loop.name) || "loop",
122 usage: (options && options.loop && options.loop.usage) || null,
123 exclude: Boolean((options && options.loop && options.loop.exclude)),
124 masked: "loop"
125 };
126
127 // Search Command options
128 this.search = {
129 enabled: (options.search == undefined ? true : (options.search && typeof options.search.enabled !== 'undefined' ? options.search && options.search.enabled : true)),
130 run: "searchFunction",
131 alt: (options && options.search && options.search.alt) || [],
132 help: (options && options.search && options.search.help) || "Search up to 10 songs on YouTube.",
133 name: (options && options.search && options.search.name) || "search",
134 usage: (options && options.search && options.search.usage) || null,
135 exclude: Boolean((options && options.search && options.search.exclude)),
136 masked: "search"
137 };
138
139 // Clear Command options
140 this.clearqueue = {
141 enabled: (options.clearqueue == undefined ? true : (options.clearqueue && typeof options.clearqueue.enabled !== 'undefined' ? options.clearqueue && options.clearqueue.enabled : true)),
142 run: "clearFunction",
143 alt: (options && options.clear && options.clear.alt) || [],
144 help: (options && options.clear && options.clear.help) || "Delete the entire queue.",
145 name: (options && options.clear && options.clear.name) || "clear",
146 usage: (options && options.clear && options.clear.usage) || null,
147 exclude: Boolean((options && options.clearqueue && options.clearqueue.exclude)),
148 masked: "clearqueue"
149 };
150
151 // Volume Command options
152 this.volume = {
153 enabled: (options.volume == undefined ? true : (options.volume && typeof options.volume.enabled !== 'undefined' ? options.volume && options.volume.enabled : true)),
154 run: "volumeFunction",
155 alt: (options && options.volume && options.volume.alt) || [],
156 help: (options && options.volume && options.volume.help) || "Change the bot's output volume.",
157 name: (options && options.volume && options.volume.name) || "volume",
158 usage: (options && options.volume && options.volume.usage) || null,
159 exclude: Boolean((options && options.volume && options.volume.exclude)),
160 masked: "volume"
161 };
162
163 this.remove = {
164 enabled: (options.remove == undefined ? true : (options.remove && typeof options.remove.enabled !== 'undefined' ? options.remove && options.remove.enabled : true)),
165 run: "removeFunction",
166 alt: (options && options.remove && options.remove.alt) || [],
167 help: (options && options.remove && options.remove.help) || "Delete a song from the queue by position.",
168 name: (options && options.remove && options.remove.name) || "remove",
169 usage: (options && options.remove && options.remove.usage) || "{{prefix}}remove [position]",
170 exclude: Boolean((options && options.remove && options.remove.exclude)),
171 masked: "remove"
172 };
173
174 // Skip Command options
175 this.skip = {
176 enabled: (options.skip == undefined ? true : (options.skip && typeof options.skip.enabled !== 'undefined' ? options.skip && options.skip.enabled : true)),
177 run: "skipFunction",
178 alt: (options && options.skip && options.skip.alt) || [],
179 help: (options && options.skip && options.skip.help) || "Skip a song or songs with `skip [Number]`",
180 name: (options && options.skip && options.skip.name) || "skip",
181 usage: (options && options.skip && options.skip.usage) || null,
182 exclude: Boolean((options && options.skip && options.skip.exclude)),
183 masked: "skip"
184 };
185 this.shuffle = {
186 enabled: (options.shuffle == undefined ? true : (options.shuffle && typeof options.shuffle.enabled !== 'undefined' ? options.shuffle && options.shuffle.enabled : true)),
187 run: "shuffleFunction",
188 alt: (options && options.shuffle && options.shuffle.alt) || [],
189 help: (options && options.shuffle && options.shuffle.help) || "Shuffle the tail",
190 name: (options && options.shuffle && options.shuffle.name) || "shuffle",
191 usage: (options && options.shuffle && options.shuffle.usage) || null,
192 exclude: Boolean((options && options.shuffle && options.shuffle.exclude)),
193 masked: "shuffle"
194 };
195 this.deleteQueue = {
196 enabled: (options.deleteQueue == undefined ? true : (options.deleteQueue && typeof options.deleteQueue.enabled !== 'undefined' ? options.deleteQueue && options.deleteQueue.enabled : true)),
197 run: "deleteQueueFunction",
198 alt: (options && options.deleteQueue && options.deleteQueue.alt) || [],
199 help: (options && options.deleteQueue && options.deleteQueue.help) || "Delete and re-queue in progress",
200 name: (options && options.deleteQueue && options.deleteQueue.name) || "deletequeue",
201 usage: (options && options.deleteQueue && options.deleteQueue.usage) || null,
202 exclude: Boolean((options && options.deleteQueue && options.deleteQueue.exclude)),
203 masked: "deletequeue"
204 };
205
206 this.embedColor = (options && options.embedColor) || 6950317;
207 this.anyoneCanSkip = (options && typeof options.anyoneCanSkip !== 'undefined' ? options && options.anyoneCanSkip : false);
208 this.anyoneCanLeave = (options && typeof options.anyoneCanLeave !== 'undefined' ? options && options.anyoneCanLeave : false);
209 this.djRole = (options && options.djRole) || "DJ";
210 this.anyoneCanPause = (options && typeof options.anyoneCanPause !== 'undefined' ? options && options.anyoneCanPause : false);
211 this.anyoneCanAdjust = (options && typeof options.anyoneCanAdjust !== 'undefined' ? options && options.anyoneCanAdjust : false);
212 this.youtubeKey = (options && options.youtubeKey);
213 this.botPrefix = (options && options.botPrefix) || "!";
214 this.defVolume = (options && options.defVolume) || 50;
215 if (options.maxQueueSize === 0) {
216 this.maxQueueSize = 0;
217 } else {
218 this.maxQueueSize = (options && options.maxQueueSize) || 50;
219 }
220 this.ownerOverMember = (options && typeof options.ownerOverMember !== 'undefined' ? options && options.ownerOverMember : false);
221 this.botAdmins = (options && options.botAdmins) || [];
222 this.ownerID = (options && options.ownerID);
223 this.logging = (options && typeof options.logging !== 'undefined' ? options && options.logging : true);
224 this.requesterName = (options && typeof options.requesterName !== 'undefined' ? options && options.requesterName : true);
225 this.inlineEmbeds = (options && typeof options.inlineEmbeds !== 'undefined' ? options && options.inlineEmbeds : false);
226 this.clearOnLeave = (options && typeof options.clearOnLeave !== 'undefined' ? options && options.clearOnLeave : true);
227 this.messageHelp = (options && typeof options.messageHelp !== 'undefined' ? options && options.messageHelp : false);
228 this.dateLocal = (options && options.dateLocal) || 'en-US';
229 this.bigPicture = (options && typeof options.bigPicture !== 'undefined' ? options && options.bigPicture : false);
230 this.messageNewSong = (options && typeof options.messageNewSong !== 'undefined' ? options && options.messageNewSong : true);
231 this.insertMusic = (options && typeof options.insertMusic !== 'undefined' ? options && options.insertMusic : false);
232 this.defaultPrefix = (options && options.defaultPrefix) || "!";
233 this.channelWhitelist = (options && options.channelWhitelist) || [];
234 this.channelBlacklist = (options && options.channelBlacklist) || [];
235 this.minShuffle = (options && options.shuffle) || 3;
236 this.bitRate = (options && options.bitRate) || "120000";
237 this.userSearching = new Map();
238
239 // Cooldown Settings
240 this.cooldown = {
241 enabled: (options && options.cooldown ? options && options.cooldown.enabled : true),
242 timer: parseInt((options && options.cooldown && options.cooldown.timer) || 10000),
243 exclude: (options && options.cooldown && options.cooldown.exclude) || ["volume", "queue", "pause", "resume", "np"]
244 };
245
246 this.musicPresence = options.musicPresence || false;
247 this.clearPresence = options.clearPresence || false;
248 this.nextPresence = (options && options.nextPresence) || null;
249 this.recentTalk = new Set();
250 }
251
252 checkVoice(mem, bot) {
253 return new Promise((resolve, reject) => {
254 if (!mem || !bot) reject("invalid args");
255 if (!mem.voice.channel) reject("You're not in a voice channel!");
256 if (bot.voice.channel) {
257 if (bot.voice.channel.id == mem.voice.channel.id) resolve(mem.voice.channel)
258 else reject("You're in a different voice channel!")
259 } else {
260 resolve(mem.voice.channel);
261 };
262 });
263 };
264
265 async updatePositions(obj, server) {
266 return new Promise((resolve, reject) => {
267 if (!server) reject("stage 0: no server passed for @updatePositions");
268 if (!obj) resolve(this.getQueue(server));
269 if (obj.working == true) reject("The queue is already performing a task!");
270 if (server != "000000") {
271 obj.working = true;
272 this.queues.set(server, obj);
273 }
274 try {
275 var songs = typeof obj == "object" ? Array.from(obj.songs) : [];
276 } catch (e) {
277 console.log("aidjbasiubd");
278 };
279 try {
280 if (!songs || songs.length <= 0 || typeof obj.songs != "object") {
281 if (this.debug) console.log("[MUSICBOT] @updatePositions: songs object was invalid, reseting queue for " + obj.id);
282 this.queues.set(obj.id, { songs: [], last: obj.last ? obj.last : null, loop: obj.loop ? obj.loop : "none", id: obj.id, volume: this.defVolume, oldSongs: [], working: false, needsRefresh: false })
283 resolve([])
284 }
285 let mm = 0;
286 var newsongs = [];
287 songs.forEach(s => {
288 try {
289 // console.log(s);
290 if (!s) return;
291 if (s.position !== mm) s.position = mm;
292 newsongs.push(s);
293 mm++;
294 } catch (e) {
295 console.log(e);
296 };
297 });
298 } catch (e) {
299 console.log(e);
300 if (server != "000000") {
301 obj.working = false;
302 this.queues.set(server, obj);
303 }
304 reject("stage 1: @updatePositions " + e)
305 };
306 obj.songs = newsongs;
307 obj.last.position = 0;
308 if (server != "000000") {
309 obj.working = false;
310 this.queues.set(server, obj);
311 }
312 setTimeout(() => {
313 resolve(obj);
314 }, 2000)
315 });
316 };
317
318 isAdmin(member) {
319 if (member.roles.cache.find(r => r.name == this.djRole)) return true;
320 if (this.ownerOverMember && member.id === this.botOwner) return true;
321 if (this.botAdmins.includes(member.id)) return true;
322 return member.hasPermission("ADMINISTRATOR");
323 };
324
325 canSkip(member, queue) {
326 if (this.anyoneCanSkip) return true;
327 else if (this.botAdmins.includes(member.id)) return true;
328 else if (this.ownerOverMember && member.id === this.botOwner) return true;
329 else if (queue.last.requester === member.id) return true;
330 else if (this.isAdmin(member)) return true;
331 else return false;
332 };
333
334 canAdjust(member, queue) {
335 if (this.anyoneCanAdjust) return true;
336 else if (this.botAdmins.includes(member.id)) return true;
337 else if (this.ownerOverMember && member.id === this.botOwner) return true;
338 else if (queue.last.requester === member.id) return true;
339 else if (this.isAdmin(member)) return true;
340 else return false;
341 };
342
343 getQueue(server) {
344 if (!this.queues.has(server)) {
345 this.queues.set(server, { songs: [], last: null, loop: "none", id: server, volume: this.defVolume, oldSongs: [], working: false, needsRefresh: false });
346 };
347 return this.queues.get(server);
348 };
349
350 setLast(server, last) {
351 return new Promise((resolve, reject) => {
352 if (this.queues.has(server)) {
353 let q = this.queues.get(server);
354 q.last = last;
355 this.queues.set(server, q);
356 resolve(this.queues.get(server));
357 } else {
358 reject("no server queue");
359 };
360 });
361 };
362
363 emptyQueue(server) {
364 return new Promise((resolve, reject) => {
365 if (!server || typeof server != "string") reject("no server id passed or passed obj was no a string @emptyQueue")
366 this.queues.set(server, { songs: [], last: null, loop: "none", id: server, volume: this.defVolume, oldSongs: [], working: false, needsRefresh: false });
367 resolve(this.queues.get(server));
368 });
369 };
370
371 async updatePresence(queue, client, clear) {
372 return new Promise((resolve, reject) => {
373 if (this.nextPresence !== null) clear = false;
374 if (!queue || !client) reject("invalid arguments");
375 if (queue.songs.length > 0 && queue.last) {
376 client.user.setPresence({
377 activity: {
378 name: "? | " + queue.last.title,
379 type: 'LISTENING'
380 }
381 });
382 resolve(client.user.presence);
383 } else {
384 if (clear) {
385 client.user.setPresence({ activity: { name: null } });
386 resolve(client.user.presence);
387 } else {
388 if (this.nextPresence !== null) {
389 let props;
390 if (this.nextPresence.status && ["online", "dnd", "idle", "invisible"].includes(this.nextPresence.status)) props.status = this.nextPresence.status;
391 if (this.nextPresence.afk && typeof this.nextPresence.afk == "boolean") props.afk = this.nextPresence.afk;
392 if (this.nextPresence.game && typeof this.nextPresence.game == "string") props.game = { name: this.nextPresence.game }
393 else if (this.nextPresence.game && typeof this.nextPresence.game == "object") props.game = this.nextPresence.game;
394 client.user.setPresence(props).catch((res) => {
395 console.error("[MUSICBOT] Could not update presence\n" + res);
396 client.user.setPresence({ activity: { name: null } });
397 resolve(client.user.presence);
398 }).then((res) => {
399 resolve(res);
400 });
401 } else {
402 // client.user.setPresence({
403 // activity: {
404 // name: "| m/help ?",
405 // type: 'LISTENING'
406 // }
407 // });
408 }
409 resolve(client.user.presence);
410 };
411 };
412 });
413 };
414
415 updatePrefix(server, prefix) {
416 if (typeof prefix == undefined) prefix = this.defaultPrefix;
417 if (typeof this.botPrefix != "object") this.botPrefix = new Map();
418 this.botPrefix.set(server, { prefix: prefix });
419 };
420 };
421
422 var musicbot = new Music(client, options);
423 if (musicbot.insertMusic == true) client.music = musicbot;
424 else exports.bot = musicbot;
425
426 musicbot.searcher = new YTSearcher(musicbot.youtubeKey);
427 musicbot.changeKey = (key) => {
428 return new Promise((resolve, reject) => {
429 if (!key || typeof key !== "string") reject("key must be a string");
430 musicbot.youtubeKey = key;
431 musicbot.searcher.key = key;
432 resolve(musicbot);
433 });
434 };
435
436 client.on("ready", () => {
437 console.log(`> Node.js Version: ${process.version}`);
438 if (musicbot.cooldown.exclude.includes("skip")) console.warn(`[MUSIC] Excluding SKIP CMD from cooldowns can cause issues.`);
439 if (musicbot.cooldown.exclude.includes("remove")) console.warn(`[MUSIC] Excluding REMOVE CMD from cooldowns can cause issues.`);
440 setTimeout(() => { if (musicbot.musicPresence == true && musicbot.client.guilds.length > 1) console.warn(`[MUSIC] MusicPresence is enabled with more than one server!`); }, 2000);
441 });
442
443 client.on("message", (msg) => {
444 if (msg.author.bot || musicbot.channelBlacklist.includes(msg.channel.id)) return;
445 if (musicbot.channelWhitelist.length > 0 && !musicbot.channelWhitelist.includes(msg.channel.id)) return;
446 const message = msg.content.trim();
447 const prefix = typeof musicbot.botPrefix == "object" ? (musicbot.botPrefix.has(msg.guild.id) ? musicbot.botPrefix.get(msg.guild.id).prefix : musicbot.defaultPrefix) : musicbot.botPrefix;
448 const command = message.substring(prefix.length).split(/[ \n]/)[0].trim();
449 const suffix = message.substring(prefix.length + command.length).trim();
450 const args = message.slice(prefix.length + command.length).trim().split(/ +/g);
451
452 if (message.startsWith(prefix) && msg.channel.type == "text") {
453 if (musicbot.commands.has(command)) {
454 let tCmd = musicbot.commands.get(command);
455 if (tCmd.enabled) {
456 if (!musicbot.cooldown.enabled == true && !musicbot.cooldown.exclude.includes(tCmd.masked)) {
457 if (musicbot.recentTalk.has(msg.author.id)) {
458 if (musicbot.cooldown.enabled == true && !musicbot.cooldown.exclude.includes(tCmd.masked)) return msg.channel.send(musicbot.note("fail", "You must wait to use music commands again."));
459 }
460 musicbot.recentTalk.add(msg.author.id);
461 setTimeout(() => { musicbot.recentTalk.delete(msg.author.id) }, musicbot.cooldown.timer);
462 }
463 return musicbot[tCmd.run](msg, suffix, args);
464 }
465 } else if (musicbot.aliases.has(command)) {
466 let aCmd = musicbot.aliases.get(command);
467 if (aCmd.enabled) {
468 if (!musicbot.cooldown.enabled == true && !musicbot.cooldown.exclude.includes(aCmd.masked)) {
469 if (musicbot.recentTalk.has(msg.author.id)) {
470 if (musicbot.cooldown.enabled == true && !musicbot.cooldown.exclude.includes(aCmd.masked)) return msg.channel.send(musicbot.note("fail", "You must wait to use music commands again."));
471 }
472 musicbot.recentTalk.add(msg.author.id);
473 setTimeout(() => { musicbot.recentTalk.delete(msg.author.id) }, musicbot.cooldown.timer);
474 }
475 return musicbot[aCmd.run](msg, suffix, args);
476 }
477 };
478 };
479 });
480
481 musicbot.playFunction = (msg, suffix, args, ignore) => {
482 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `You are not in a voice channel.`));
483 if (!suffix) return msg.channel.send(musicbot.note('fail', 'There is no video specified!'));
484 let q = musicbot.getQueue(msg.guild.id);
485
486 let vc = client.voice.connections.find(val => val.channel.guild.id == msg.member.guild.id)
487 if (vc && vc.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
488 if (q.songs.length >= musicbot.maxQueueSize && musicbot.maxQueueSize !== 0) return msg.channel.send(musicbot.note('fail', 'The song queue is full!'));
489 var searchstring = suffix.trim();
490 if (searchstring.includes("https://youtu.be/") || searchstring.includes("https://www.youtube.com/") && searchstring.includes("&")) searchstring = searchstring.split("&")[0];
491
492
493 if (searchstring.startsWith('http') && searchstring.includes("list=")) {
494 msg.channel.send(musicbot.note("search", `Searching playlist items~`));
495 var playid = searchstring.toString()
496 .split('list=')[1];
497 if (playid.toString()
498 .includes('?')) playid = playid.split('?')[0];
499 if (playid.toString()
500 .includes('&t=')) playid = playid.split('&t=')[0];
501
502 ytpl(playid, { limit: musicbot.maxQueueSize }, function(err, playlist) {
503 if (err) return msg.channel.send(musicbot.note('fail', `Something went wrong fetching that playlist!`));
504 if (playlist.items.length <= 0) return msg.channel.send(musicbot.note('fail', `Couldn't get any videos from that playlist.`));
505 if (playlist.total_items >= musicbot.maxQueueSize && musicbot.maxQueueSize != 0) return msg.channel.send(musicbot.note('fail', `Too many videos to queue. A maximum of ` + musicbot.maxQueueSize + ` is allowed.`));
506 var index = 0;
507 var ran = 0;
508 var queue = musicbot.getQueue(msg.guild.id);
509
510 playlist.items.forEach(async(video) => {
511 ran++;
512 if (queue.songs.length == (musicbot.maxQueueSize + 1) && musicbot.maxQueueSize !== 0 || !video) return;
513 video.url = video.url_simple ? video.url_simple : `https://www.youtube.com/watch?v=` + video.id;
514 musicbot.playFunction(msg, video.url, [], true);
515 index++;
516
517 if (ran >= playlist.items.length) {
518 if (queue.songs.length >= 1) musicbot.executeQueue(msg, queue);
519 if (index == 0) msg.channel.send(musicbot.note('fail', `Coudln't get any songs from that playlist!`))
520 else if (index == 1) msg.channel.send(musicbot.note('note', `Queued one song.`));
521 else if (index > 1) msg.channel.send(musicbot.note('note', `Queued ${index} songs.`));
522 }
523 });
524 });
525 } else {
526 if (!ignore) msg.channel.send(musicbot.note("search", `\`Playing ${searchstring}\``));
527 new Promise(async(resolve, reject) => {
528 let result = await musicbot.searcher.search(searchstring, { type: 'video' }).catch((err) => {
529 var errorMsg = err.message;
530 if (errorMsg.includes('\"reason\": \"dailyLimitExceeded\",')) {
531 errorMsg = errorMsg.slice(errorMsg.indexOf('Daily Limit Exceeded. '));
532 errorMsg = errorMsg.slice(0, errorMsg.indexOf('\",'));
533 if (!ignore) msg.channel.send(musicbot.note("fail", "**Unable to complete playback:**\n" + errorMsg));
534 return;
535 } else if (errorMsg.includes('\"reason\": \"quotaExceeded\",')) {
536 if (!ignore) msg.channel.send(musicbot.note("fail", "Unable to complete playback! Google API quota exceeded!"));
537 return;
538 } else {
539 if (!ignore) msg.channel.send(musicbot.note("fail", "There was an error! Try to put more details."));
540 return console.log(err);
541 }
542 });
543 if (result === undefined) return;
544 resolve(result.first)
545 }).then(async(res) => {
546
547 if (!res) return msg.channel.send(musicbot.note("fail", "Something went wrong. Try again!"));
548 res.requester = msg.author.id;
549 if (searchstring.startsWith("https://www.youtube.com/") || searchstring.startsWith("https://youtu.be/")) res.url = searchstring;
550 res.channelURL = `https://www.youtube.com/channel/${res.channelId}`;
551 res.queuedOn = new Date().toLocaleDateString(musicbot.dateLocal, { weekday: 'long', hour: 'numeric' });
552 if (musicbot.requesterName) res.requesterAvatarURL = msg.author.displayAvatarURL();
553 const queue = musicbot.getQueue(msg.guild.id)
554 res.position = queue.songs.length ? queue.songs.length : 0;
555 queue.songs.push(res);
556 let time = await fetch(`https://tao-is-developing.online/api/search/?q=${res.id}`).then(asd => asd.json())
557 if (!ignore) {
558 if (msg.channel.permissionsFor(msg.guild.me).has('EMBED_LINKS')) {
559 const embed = new Discord.MessageEmbed();
560 try {
561 embed.setTitle("Added a song:",
562 embed.setAuthor(`${client.user.username} ┇ Music`), client.user.avatarURL());
563 var songTitle = res.title.replace(/\\/g, '\\\\')
564 .replace(/\`/g, '\\`')
565 .replace(/\*/g, '\\*')
566 .replace(/_/g, '\\_')
567 .replace(/~/g, '\\~')
568 .replace(/`/g, '\\`');
569 embed.setColor(musicbot.embedColor);
570 embed.addField("Author:", res.channelTitle);
571 embed.addField("Títle:", `[${songTitle}](${res.url})`, musicbot.inlineEmbeds);
572 if (!musicbot.bigPicture) embed.setThumbnail(`https://img.youtube.com/vi/${res.id}/maxresdefault.jpg`);
573 if (musicbot.bigPicture) embed.setImage(`https://img.youtube.com/vi/${res.id}/maxresdefault.jpg`);
574 const resMem = client.users.cache.get(res.requester);
575 if (musicbot.requesterName && resMem) embed.setFooter(`Song added by: ${client.users.cache.get(res.requester).username}`, res.requesterAvatarURL);
576 if (musicbot.requesterName && !resMem) embed.setFooter(`Song added by: \`UnknownUser (ID: ${res.requester})\``, res.requesterAvatarURL);
577 msg.channel.send({
578 embed
579 });
580 } catch (e) {
581 console.error(`[${msg.guild.name}] [playCmd] ` + e.stack);
582 };
583 } else {
584 try {
585 var songTitle = res.title.replace(/\\/g, '\\\\')
586 .replace(/\`/g, '\\`')
587 .replace(/\*/g, '\\*')
588 .replace(/_/g, '\\_')
589 .replace(/~/g, '\\~')
590 .replace(/`/g, '\\`');
591 msg.channel.send(`Now Playing: **${songTitle}**\nSong added by: ${client.users.cache.get(res.requester).username}\nQueued On: ${res.queuedOn}\nTime: ${time.results[0].video.duration}`)
592 } catch (e) {
593 console.error(`[${msg.guild.name}] [npCmd] ` + e.stack);
594 };
595 };
596 };
597 if (queue.songs.length === 1 || !client.voice.connections.find(val => val.channel.guild.id == msg.guild.id)) musicbot.executeQueue(msg, queue);
598 }).catch((res) => {
599 console.log(new Error(res));
600 });
601 };
602 };
603
604 musicbot.helpFunction = (msg, suffix, args) => {
605 const prefix = typeof musicbot.botPrefix == "object" ? (musicbot.botPrefix.has(msg.guild.id) ? musicbot.botPrefix.get(msg.guild.id).prefix : musicbot.defaultPrefix) : musicbot.botPrefix;
606 let command = suffix.trim();
607 if (!suffix) {
608 if (msg.channel.permissionsFor(msg.guild.me)
609 .has('EMBED_LINKS')) {
610 const embed = new Discord.MessageEmbed();
611 embed.setAuthor(`Music Commands`, client.user.avatarURL());
612 embed.setDescription(`Use \`${prefix}${musicbot.musichelp.name} (Name command),\` for more information.`);
613 // embed.addField(musicbot.helpCmd, musicbot.helpHelp);
614 const newCmds = Array.from(musicbot.commands);
615 let index = 0;
616 let max = musicbot.commandsArray.length;
617 embed.setColor(musicbot.embedColor);
618 for (var i = 0; i < musicbot.commandsArray.length; i++) {
619 if (!musicbot.commandsArray[i].exclude) embed.addField(musicbot.commandsArray[i].name, musicbot.commandsArray[i].help);
620 index++;
621 if (index == max) {
622 if (musicbot.messageHelp) {
623 let sent = false;
624 msg.author.send({
625 embed
626 })
627 .then(() => {
628 sent = true;
629 });
630 setTimeout(() => {
631 if (!sent) return msg.channel.send({
632 embed
633 });
634 }, 1200);
635 } else {
636 return msg.channel.send({
637 embed
638 });
639 };
640 }
641 };
642 } else {
643 var cmdmsg = `= Music Commands =\nUse ${prefix}${musicbot.help.name} [command] for help on a command. Anyone with a role named \`${musicbot.djRole}\` can use any command.\n`;
644 let index = 0;
645 let max = musicbot.commandsArray.length;
646 for (var i = 0; i < musicbot.commandsArray.length; i++) {
647 if (!musicbot.commandsArray[i].disabled || !musicbot.commandsArray[i].exclude) {
648 cmdmsg = cmdmsg + `\n• ${musicbot.commandsArray[i].name}: ${musicbot.commandsArray[i].help}`;
649 index++;
650 if (index == musicbot.commandsArray.length) {
651 if (musicbot.messageHelp) {
652 let sent = false;
653 msg.author.send(cmdmsg, {
654 code: 'asciidoc'
655 })
656 .then(() => {
657 sent = true;
658 });
659 setTimeout(() => {
660 if (!sent) return msg.channel.send(cmdmsg, {
661 code: 'asciidoc'
662 });
663 }, 500);
664 } else {
665 return msg.channel.send(cmdmsg, {
666 code: 'asciidoc'
667 });
668 };
669 }
670 };
671 };
672 };
673 } else if (musicbot.commands.has(command) || musicbot.aliases.has(command)) {
674 if (msg.channel.permissionsFor(msg.guild.me)
675 .has('EMBED_LINKS')) {
676 const embed = new Discord.MessageEmbed();
677 command = musicbot.commands.get(command) || musicbot.aliases.get(command);
678 if (command.exclude) return msg.channel.send(musicbot.note('fail', `${suffix} is not a valid command!`));
679 embed.setAuthor(command.name, msg.client.user.avatarURL());
680 embed.setDescription(command.help);
681 if (command.alt.length > 0) embed.addField(`Aliases`, command.alt.join(", "), musicbot.inlineEmbeds);
682 if (command.usage && typeof command.usage == "string") embed.addField(`Usage`, command.usage.replace(/{{prefix}}/g, prefix), musicbot.inlineEmbeds);
683 embed.setColor(musicbot.embedColor);
684 msg.channel.send({
685 embed
686 });
687 } else {
688 command = musicbot.commands.get(command) || musicbot.aliases.get(command);
689 if (command.exclude) return msg.channel.send(musicbot.note('fail', `${suffix} is not a valid command!`));
690 var cmdhelp = `= ${command.name} =\n`;
691 cmdhelp = cmdhelp + `\n${command.help}`;
692 if (command.usage !== null) cmdhelp = cmdhelp + `\nUsage: ${command.usage.replace(/{{prefix}}/g, prefix)}`;
693 if (command.alt.length > 0) cmdhelp = cmdhelp + `\nAliases: ${command.alt.join(", ")}`;
694 msg.channel.send(cmdhelp, {
695 code: 'asciidoc'
696 });
697 };
698 } else {
699 msg.channel.send(musicbot.note('fail', `${suffix} is not a valid command!`));
700 };
701 };
702
703 musicbot.skipFunction = (msg, suffix, args) => {
704 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `You are not in a voice channel.`));
705 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
706 if (!voiceConnection) return msg.channel.send(musicbot.note('fail', 'No music being played.'));
707 if (voiceConnection && voiceConnection.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
708
709 const queue = musicbot.getQueue(msg.guild.id);
710 if (!musicbot.canSkip(msg.member, queue)) return msg.channel.send(musicbot.note('fail', `You cannot skip this as you didn't queue it.`));
711
712 if (musicbot.queues.get(msg.guild.id).loop == "song") return msg.channel.send(musicbot.note("fail", "Cannot skip while loop is set to single."));
713
714 const dispatcher = voiceConnection.dispatcher;
715 if (!dispatcher || dispatcher === null) {
716 if (musicbot.logging) console.log(new Error(`dispatcher null on skip cmd [${msg.guild.name}] [${msg.author.username}]`));
717 return msg.channel.send(musicbot.note("fail", "Something went wrong by skipping this song."));
718 };
719 if (voiceConnection.paused) dispatcher.end();
720 dispatcher.end();
721 msg.channel.send(musicbot.note("note", "Canción omitida"));
722 };
723
724 musicbot.pauseFunction = (msg, suffix, args) => {
725 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `You are not in a voice channel.`));
726 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
727 if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'No music being played.'));
728 if (voiceConnection && voiceConnection.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
729 if (!musicbot.isAdmin(msg.member) && !musicbot.anyoneCanPause) return msg.channel.send(musicbot.note('fail', 'You cannot pause queues.'));
730
731 const dispatcher = voiceConnection.dispatcher;
732 if (dispatcher.paused) return msg.channel.send(musicbot.note(`fail`, `Music already paused!`))
733 else dispatcher.pause();
734 msg.channel.send(musicbot.note('note', 'Playback paused.'));
735 };
736
737 musicbot.resumeFunction = (msg, suffix, args) => {
738 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `You are not in a voice channel.`));
739 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
740 if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'No music being played.'));
741 if (voiceConnection && voiceConnection.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
742 if (!musicbot.isAdmin(msg.member) && !musicbot.anyoneCanPause) return msg.channel.send(musicbot.note('fail', `You cannot resume queues.`));
743
744 const dispatcher = voiceConnection.dispatcher;
745 if (dispatcher === null) {
746 message.channel.send('Nothing to resume.')
747 return;
748 }
749 if (!dispatcher.paused) return msg.channel.send(musicbot.note('fail', `Music already playing.`))
750 else dispatcher.resume();
751 msg.channel.send(musicbot.note('note', 'Playback resumed.'));
752 };
753
754 musicbot.leaveFunction = (msg, suffix) => {
755 const queue = musicbot.getQueue(msg.guild.id);
756 if (musicbot.isAdmin(msg.member) || musicbot.anyoneCanLeave === true) {
757 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `You are not in a voice channel.`));
758 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
759 if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'I\'m not in a voice channel.'));
760 if (voiceConnection && voiceConnection.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
761 musicbot.emptyQueue(msg.guild.id).then(() => {
762 queue.songs = [];
763 if (voiceConnection.dispatcher) voiceConnection.dispatcher.end();
764 voiceConnection.channel.leave();
765 msg.channel.send(musicbot.note('note', 'Disconnected successfully!'));
766 }).catch((res) => {
767 console.log("[" + msg.guild.id + "] " + res);
768 musicbot.queues.delete(msg.guild.id);
769 musicbot.queues.set(msg.guild.id, { songs: [], last: null, loop: "none", id: msg.guild.id, volume: musicbot.defVolume, oldSongs: [], working: false, needsRefresh: false });
770 })
771
772 } else {
773 const chance = Math.floor((Math.random() * 100) + 1);
774 if (chance <= 10) return msg.channel.send(musicbot.note('fail', `I'm afraid I can't let you do that, ${msg.author.username}.`))
775 else return msg.channel.send(musicbot.note('fail', "Sorry, you don't have permission to do that."));
776 }
777 }
778
779 musicbot.npFunction = (msg, suffix, args) => {
780 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
781 if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'No music is being played.'));
782 const queue = musicbot.getQueue(msg.guild.id, true);
783 const dispatcher = voiceConnection.dispatcher;
784
785 if (musicbot.queues.get(msg.guild.id).songs.length <= 0) return msg.channel.send(musicbot.note('note', 'Queue empty.'));
786
787 if (msg.channel.permissionsFor(msg.guild.me)
788 .has('EMBED_LINKS')) {
789 const embed = new Discord.MessageEmbed();
790 try {
791 embed.setAuthor('Playing now:', client.user.avatarURL());
792 var songTitle = queue.last.title.replace(/\\/g, '\\\\')
793 .replace(/\`/g, '\\`')
794 .replace(/\*/g, '\\*')
795 .replace(/_/g, '\\_')
796 .replace(/~/g, '\\~')
797 .replace(/`/g, '\\`');
798 embed.setColor(musicbot.embedColor);
799 embed.addField(queue.last.channelTitle, `[${songTitle}](${queue.last.url})`, musicbot.inlineEmbeds);
800 embed.addField("Queued On", queue.last.queuedOn, musicbot.inlineEmbeds);
801 if (!musicbot.bigPicture) embed.setThumbnail(`https://img.youtube.com/vi/${queue.last.id}/maxresdefault.jpg`);
802 if (musicbot.bigPicture) embed.setImage(`https://img.youtube.com/vi/${queue.last.id}/maxresdefault.jpg`);
803 const resMem = client.users.cache.get(queue.last.requester);
804 if (musicbot.requesterName && resMem) embed.setFooter(`Song added by: ${client.users.cache.get(queue.last.requester).username}`, queue.last.requesterAvatarURL);
805 if (musicbot.requesterName && !resMem) embed.setFooter(`Song added by: \`UnknownUser (ID: ${queue.last.requester})\``, queue.last.requesterAvatarURL);
806 msg.channel.send({
807 embed
808 });
809 } catch (e) {
810 console.error(`[${msg.guild.name}] [npCmd] ` + e.stack);
811 };
812 } else {
813 try {
814 var songTitle = queue.last.title.replace(/\\/g, '\\\\')
815 .replace(/\`/g, '\\`')
816 .replace(/\*/g, '\\*')
817 .replace(/_/g, '\\_')
818 .replace(/~/g, '\\~')
819 .replace(/`/g, '\\`');
820 msg.channel.send(`Playing now: **${songTitle}**\nSong added by: ${client.users.cache.get(queue.last.requester).username}\nQueued On: ${queue.last.queuedOn}`)
821 } catch (e) {
822 console.error(`[${msg.guild.name}] [npCmd] ` + e.stack);
823 };
824 }
825 };
826
827 musicbot.deleteQueueFunction = async(msg, suffix, args) => {
828 if (!musicbot.isAdmin(msg.member)) return msg.channel.send(musicbot.note("fail", "Only and Admin can do this."));
829 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
830 musicbot.emptyQueue(msg.guild.id).then(() => {
831 if (voiceConnection !== null) {
832 const dispatcher = voiceConnection.dispatcher;
833 dispatcher.destroy()
834 }
835 return msg.channel.send(musicbot.note("note", "The queue should now be emptied."))
836 }).catch(async(res) => {
837 console.log("[" + msg.guild.id + "] " + res);
838 musicbot.queues.delete(msg.guild.id);
839 musicbot.queues.set(msg.guild.id, { songs: [], last: null, loop: "none", id: msg.guild.id, volume: musicbot.defVolume, oldSongs: [], working: false, needsRefresh: false });
840 if (voiceConnection !== null) {
841 const dispatcher = voiceConnection.dispatcher;
842 dispatcher.destroy()
843 }
844 msg.channel.send(musicbot.note("note", "The queue should now be deleted."))
845 })
846 }
847
848 musicbot.queueFunction = (msg, suffix, args) => {
849 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `You are not in a voice channel.`));
850 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
851 if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'No music being played.'));
852 if (voiceConnection && voiceConnection.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
853 if (!musicbot.queues.has(msg.guild.id)) return msg.channel.send(musicbot.note("fail", "Could not find a queue for this server."));
854 else if (musicbot.queues.get(msg.guild.id).songs.length <= 0) return msg.channel.send(musicbot.note("fail", "Queue is empty."));
855 const queue = musicbot.queues.get(msg.guild.id);
856 if (suffix) {
857 let video = queue.songs.find(s => s.position == parseInt(suffix) - 1);
858 if (!video) return msg.channel.send(musicbot.note("fail", "Couldn't find that video."));
859 const embed = new Discord.MessageEmbed()
860 .setAuthor('Queued Song', client.user.avatarURL())
861 .setColor(musicbot.embedColor)
862 .addField(video.channelTitle, `[${video.title.replace(/\\/g, '\\\\').replace(/\`/g, '\\`').replace(/\*/g, '\\*').replace(/_/g, '\\_').replace(/~/g, '\\~').replace(/`/g, '\\`')}](${video.url})`, musicbot.inlineEmbeds)
863 .addField("Queued On", video.queuedOn, musicbot.inlineEmbeds)
864 .addField("Position", video.position + 1, musicbot.inlineEmbeds);
865 if (!musicbot.bigPicture) embed.setThumbnail(`https://img.youtube.com/vi/${video.id}/maxresdefault.jpg`);
866 if (musicbot.bigPicture) embed.setImage(`https://img.youtube.com/vi/${video.id}/maxresdefault.jpg`);
867 const resMem = client.users.cache.get(video.requester);
868 if (musicbot.requesterName && resMem) embed.setFooter(`Song added by: ${client.users.cache.get(video.requester).username}`, video.requesterAvatarURL);
869 if (musicbot.requesterName && !resMem) embed.setFooter(`Song added by: \`UnknownUser (ID: ${video.requester})\``, video.requesterAvatarURL);
870 msg.channel.send({embed});
871 } else {
872 if (queue.songs.length > 11) {
873 let pages = [];
874 let page = 1;
875 const newSongs = queue.songs.musicArraySort(10);
876 newSongs.forEach(s => {
877 var i = s.map((video, index) => (
878 `**${video.position + 1}:** __${video.title.replace(/\\/g, '\\\\').replace(/\`/g, '\\`').replace(/\*/g, '\\*').replace(/_/g, '\\_').replace(/~/g, '\\~').replace(/`/g, '\\`')}__`
879 )).join('\n\n');
880 if (i !== undefined) pages.push(i)
881 });
882
883 const embed = new Discord.MessageEmbed();
884 embed.setAuthor('Queued Songs', client.user.avatarURL());
885 embed.setColor(musicbot.embedColor);
886 embed.setFooter(`Page ${page} of ${pages.length}`);
887 embed.setDescription(pages[page - 1]);
888 msg.channel.send(embed).then(m => {
889 m.react('⏪').then( r => {
890 m.react('⏩')
891 let forwardsFilter = m.createReactionCollector((reaction, user) => reaction.emoji.name === '⏩' && user.id === msg.author.id, { time: 120000 });
892 let backFilter = m.createReactionCollector((reaction, user) => reaction.emoji.name === '⏪' && user.id === msg.author.id, { time: 120000 });
893
894 forwardsFilter.on('collect', r => {
895 if (page === pages.length) return;
896 page++;
897 embed.setDescription(pages[page - 1]);
898 embed.setFooter(`Page ${page} of ${pages.length}`, msg.author.displayAvatarURL());
899 m.edit(embed);
900 })
901 backFilter.on('collect', r => {
902 if (page === 1) return;
903 page--;
904 embed.setDescription(pages[page - 1]);
905 embed.setFooter(`Page ${page} of ${pages.length}`);
906 m.edit(embed);
907 })
908 })
909 })
910 } else {
911 try {
912 var newSongs = musicbot.queues.get(msg.guild.id).songs.map((video, index) => (`**${video.position + 1}:** __${video.title.replace(/\\/g, '\\\\').replace(/\`/g, '\\`').replace(/\*/g, '\\*').replace(/_/g, '\\_').replace(/~/g, '\\~').replace(/`/g, '\\`')}__`)).join('\n\n');
913 const embed = new Discord.MessageEmbed();
914 embed.setAuthor('Queued Songs', client.user.avatarURL());
915 embed.setColor(musicbot.embedColor);
916 embed.setDescription(newSongs);
917 embed.setFooter(`Page 1 of 1`, msg.author.displayAvatarURL());
918 return msg.channel.send(embed);
919 } catch (e) {
920 console.log("["+msg.guild.id+"] " + e);
921 return msg.channel.send(musicbot.note("fail", "Something went wrong mapping out the queue! Please delete the queue if this persists."));
922 };
923 };
924 };
925 };
926
927 musicbot.searchFunction = (msg, suffix, args) => {
928 if (msg.member.voice.channel === undefined) return msg.channel.send(musicbot.note('fail', `No estás en un canal de voz.`));
929 let vc = client.voice.connections.find(val => val.channel.guild.id == msg.member.guild.id)
930 if (vc && vc.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
931 let us = `${msg.guild.id}-${msg.author.id}`;
932 if (musicbot.userSearching.has(us)) return msg.channel.send(musicbot.note("fail", `You already have a search on-going for \`${musicbot.userSearching.get(us).title}\`.\nYou may type \`cancel\` to cancel it.`));
933
934 if (!suffix) return msg.channel.send(musicbot.note('fail', 'No hay video especificado!'));
935 const queue = musicbot.getQueue(msg.guild.id);
936 if (queue.songs.length >= musicbot.maxQueueSize && musicbot.maxQueueSize !== 0) return msg.channel.send(musicbot.note('fail', 'Maximum queue size reached!'));
937 musicbot.userSearching.set(us, {guild: msg.guild.id, user: msg.author.id, title: suffix})
938 let searchstring = suffix.trim();
939 msg.channel.send(musicbot.note('search', `Searching for: \`${searchstring}\``))
940 .then(response => {
941 musicbot.searcher.search(searchstring, {
942 type: 'video'
943 })
944 .then(searchResult => {
945 if (!searchResult.totalResults || searchResult.totalResults === 0) return response.edit(musicbot.note('fail', 'Failed to get search results.'));
946
947 const startTheFun = async (videos, max) => {
948 if (msg.channel.permissionsFor(msg.guild.me).has('EMBED_LINKS')) {
949 const embed = new Discord.MessageEmbed();
950 embed.setTitle(`Choose your song by giving a number.`);
951 embed.setColor(musicbot.embedColor);
952 var index = 0;
953 videos.forEach(function(video) {
954 index++;
955 embed.addField(`${index} (${video.channelTitle})`, `[${musicbot.note('font', video.title)}](${video.url})`, musicbot.inlineEmbeds);
956 });
957 embed.setFooter(`Search by: ${msg.author.username}`, msg.author.displayAvatarURL());
958 msg.channel.send({
959 embed
960 })
961 .then(firstMsg => {
962 var filter = null;
963 if (max === 0) {
964 filter = m => m.author.id === msg.author.id &&
965 m.content.includes('1') ||
966 m.content.trim() === (`cancel`);
967 } else if (max === 1) {
968 filter = m => m.author.id === msg.author.id &&
969 m.content.includes('1') ||
970 m.content.includes('2') ||
971 m.content.trim() === (`cancel`);
972 } else if (max === 2) {
973 filter = m => m.author.id === msg.author.id &&
974 m.content.includes('1') ||
975 m.content.includes('2') ||
976 m.content.includes('3') ||
977 m.content.trim() === (`cancel`);
978 } else if (max === 3) {
979 filter = m => m.author.id === msg.author.id &&
980 m.content.includes('1') ||
981 m.content.includes('2') ||
982 m.content.includes('3') ||
983 m.content.includes('4') ||
984 m.content.trim() === (`cancel`);
985 } else if (max === 4) {
986 filter = m => m.author.id === msg.author.id &&
987 m.content.includes('1') ||
988 m.content.includes('2') ||
989 m.content.includes('3') ||
990 m.content.includes('4') ||
991 m.content.includes('5') ||
992 m.content.trim() === (`cancel`);
993 } else if (max === 5) {
994 filter = m => m.author.id === msg.author.id &&
995 m.content.includes('1') ||
996 m.content.includes('2') ||
997 m.content.includes('3') ||
998 m.content.includes('4') ||
999 m.content.includes('5') ||
1000 m.content.includes('6') ||
1001 m.content.trim() === (`cancel`);
1002 } else if (max === 6) {
1003 filter = m => m.author.id === msg.author.id &&
1004 m.content.includes('1') ||
1005 m.content.includes('2') ||
1006 m.content.includes('3') ||
1007 m.content.includes('4') ||
1008 m.content.includes('5') ||
1009 m.content.includes('6') ||
1010 m.content.includes('7') ||
1011 m.content.trim() === (`cancel`);
1012 } else if (max === 7) {
1013 filter = m => m.author.id === msg.author.id &&
1014 m.content.includes('1') ||
1015 m.content.includes('2') ||
1016 m.content.includes('3') ||
1017 m.content.includes('4') ||
1018 m.content.includes('5') ||
1019 m.content.includes('6') ||
1020 m.content.includes('7') ||
1021 m.content.includes('8') ||
1022 m.content.trim() === (`cancel`);
1023 } else if (max === 8) {
1024 filter = m => m.author.id === msg.author.id &&
1025 m.content.includes('1') ||
1026 m.content.includes('2') ||
1027 m.content.includes('3') ||
1028 m.content.includes('4') ||
1029 m.content.includes('5') ||
1030 m.content.includes('6') ||
1031 m.content.includes('7') ||
1032 m.content.includes('8') ||
1033 m.content.includes('9') ||
1034 m.content.trim() === (`cancel`);
1035 } else if (max === 9) {
1036 filter = m => m.author.id === msg.author.id &&
1037 m.content.includes('1') ||
1038 m.content.includes('2') ||
1039 m.content.includes('3') ||
1040 m.content.includes('4') ||
1041 m.content.includes('5') ||
1042 m.content.includes('6') ||
1043 m.content.includes('7') ||
1044 m.content.includes('8') ||
1045 m.content.includes('9') ||
1046 m.content.includes('10') ||
1047 m.content.trim() === (`cancel`);
1048 }
1049 msg.channel.awaitMessages(filter, {
1050 max: 1,
1051 time: 60000,
1052 errors: ['time']
1053 })
1054 .then(collected => {
1055 const newColl = Array.from(collected);
1056 const mcon = newColl[0][1].content;
1057
1058 if (mcon === "cancel") {
1059 musicbot.userSearching.delete(us);
1060 return firstMsg.edit(musicbot.note('note', 'Searching canceled.'));
1061 };
1062 const song_number = parseInt(mcon) - 1;
1063 if (song_number >= 0) {
1064 musicbot.userSearching.delete(us);
1065 firstMsg.delete();
1066
1067 videos[song_number].requester = msg.author.id;
1068 videos[song_number].position = queue.songs.length ? queue.songs.length : 0;
1069 var embed = new Discord.MessageEmbed();
1070 embed.setTitle("Added a song:",
1071 embed.setAuthor(`${client.user.username} ┇ Music`), client.user.avatarURL());
1072 var songTitle = videos[song_number].title.replace(/\\/g, '\\\\')
1073 .replace(/\`/g, '\\`')
1074 .replace(/\*/g, '\\*')
1075 .replace(/_/g, '\\_')
1076 .replace(/~/g, '\\~')
1077 .replace(/`/g, '\\`');
1078 embed.setColor(musicbot.embedColor);
1079 embed.addField("Author", videos[song_number].channelTitle);
1080 embed.addField("Title:", `[${songTitle}](${videos[song_number].url})`, musicbot.inlineEmbeds);
1081 if (!musicbot.bigPicture) embed.setThumbnail(`https://img.youtube.com/vi/${videos[song_number].id}/maxresdefault.jpg`);
1082 if (musicbot.bigPicture) embed.setImage(`https://img.youtube.com/vi/${videos[song_number].id}/maxresdefault.jpg`);
1083 const resMem = client.users.cache.get(videos[song_number].requester);
1084 if (musicbot.requesterName && resMem) embed.setFooter(`Song added by: ${client.users.cache.get(videos[song_number].requester).username}`, videos[song_number].requesterAvatarURL);
1085 if (musicbot.requesterName && !resMem) embed.setFooter(`Song added by: \`UnknownUser (ID: ${videos[song_number].requester})\``, videos[song_number].requesterAvatarURL);
1086 msg.channel.send({
1087 embed
1088 }).then(() => {
1089 queue.songs.push(videos[song_number]);
1090 if (queue.songs.length === 1 || !client.voice.connections.find(val => val.channel.guild.id == msg.guild.id)) musicbot.executeQueue(msg, queue);
1091 })
1092 .catch(console.log);
1093 };
1094 })
1095 .catch(collected => {
1096 musicbot.userSearching.delete(us);
1097 if (collected.toString().match(/error|Error|TypeError|RangeError|Uncaught/)) return firstMsg.edit(`\`\`\`xl\nSearching canceled. ${collected}\n\`\`\``);
1098 return firstMsg.edit(`\`\`\`xl\nSearching canceled.\n\`\`\``);
1099 });
1100 })
1101 } else {
1102 const vids = videos.map((video, index) => (
1103 `**${index + 1}:** __${video.title.replace(/\\/g, '\\\\').replace(/\`/g, '\\`').replace(/\*/g, '\\*').replace(/_/g, '\\_').replace(/~/g, '\\~').replace(/`/g, '\\`')}__`
1104 )).join('\n\n');
1105 msg.channel.send(`\`\`\`\n= Pick Your Video =\n${vids}\n\n= Say Cancel To Cancel =`).then(firstMsg => {
1106 var filter = null;
1107 if (max === 0) {
1108 filter = m => m.author.id === msg.author.id &&
1109 m.content.includes('1') ||
1110 m.content.trim() === (`cancel`);
1111 } else if (max === 1) {
1112 filter = m => m.author.id === msg.author.id &&
1113 m.content.includes('1') ||
1114 m.content.includes('2') ||
1115 m.content.trim() === (`cancel`);
1116 } else if (max === 2) {
1117 filter = m => m.author.id === msg.author.id &&
1118 m.content.includes('1') ||
1119 m.content.includes('2') ||
1120 m.content.includes('3') ||
1121 m.content.trim() === (`cancel`);
1122 } else if (max === 3) {
1123 filter = m => m.author.id === msg.author.id &&
1124 m.content.includes('1') ||
1125 m.content.includes('2') ||
1126 m.content.includes('3') ||
1127 m.content.includes('4') ||
1128 m.content.trim() === (`cancel`);
1129 } else if (max === 4) {
1130 filter = m => m.author.id === msg.author.id &&
1131 m.content.includes('1') ||
1132 m.content.includes('2') ||
1133 m.content.includes('3') ||
1134 m.content.includes('4') ||
1135 m.content.includes('5') ||
1136 m.content.trim() === (`cancel`);
1137 } else if (max === 5) {
1138 filter = m => m.author.id === msg.author.id &&
1139 m.content.includes('1') ||
1140 m.content.includes('2') ||
1141 m.content.includes('3') ||
1142 m.content.includes('4') ||
1143 m.content.includes('5') ||
1144 m.content.includes('6') ||
1145 m.content.trim() === (`cancel`);
1146 } else if (max === 6) {
1147 filter = m => m.author.id === msg.author.id &&
1148 m.content.includes('1') ||
1149 m.content.includes('2') ||
1150 m.content.includes('3') ||
1151 m.content.includes('4') ||
1152 m.content.includes('5') ||
1153 m.content.includes('6') ||
1154 m.content.includes('7') ||
1155 m.content.trim() === (`cancel`);
1156 } else if (max === 7) {
1157 filter = m => m.author.id === msg.author.id &&
1158 m.content.includes('1') ||
1159 m.content.includes('2') ||
1160 m.content.includes('3') ||
1161 m.content.includes('4') ||
1162 m.content.includes('5') ||
1163 m.content.includes('6') ||
1164 m.content.includes('7') ||
1165 m.content.includes('8') ||
1166 m.content.trim() === (`cancel`);
1167 } else if (max === 8) {
1168 filter = m => m.author.id === msg.author.id &&
1169 m.content.includes('1') ||
1170 m.content.includes('2') ||
1171 m.content.includes('3') ||
1172 m.content.includes('4') ||
1173 m.content.includes('5') ||
1174 m.content.includes('6') ||
1175 m.content.includes('7') ||
1176 m.content.includes('8') ||
1177 m.content.includes('9') ||
1178 m.content.trim() === (`cancel`);
1179 } else if (max === 9) {
1180 filter = m => m.author.id === msg.author.id &&
1181 m.content.includes('1') ||
1182 m.content.includes('2') ||
1183 m.content.includes('3') ||
1184 m.content.includes('4') ||
1185 m.content.includes('5') ||
1186 m.content.includes('6') ||
1187 m.content.includes('7') ||
1188 m.content.includes('8') ||
1189 m.content.includes('9') ||
1190 m.content.includes('10') ||
1191 m.content.trim() === (`cancel`);
1192 }
1193 msg.channel.awaitMessages(filter, {
1194 max: 1,
1195 time: 60000,
1196 errors: ['time']
1197 })
1198 .then(collected => {
1199 musicbot.userSearching.delete(us);
1200 const newColl = Array.from(collected);
1201 const mcon = newColl[0][1].content;
1202
1203 if (mcon === "cancel") return firstMsg.edit(musicbot.note('note', 'Searching canceled.'));
1204 const song_number = parseInt(mcon) - 1;
1205 if (song_number >= 0) {
1206 firstMsg.delete();
1207
1208 videos[song_number].requester = msg.author.id;
1209 videos[song_number].position = queue.songs.length ? queue.songs.length : 0;
1210 var embed = new Discord.MessageEmbed();
1211 embed.setAuthor('Adding To Queue', client.user.avatarURL());
1212 var songTitle = videos[song_number].title.replace(/\\/g, '\\\\')
1213 .replace(/\`/g, '\\`')
1214 .replace(/\*/g, '\\*')
1215 .replace(/_/g, '\\_')
1216 .replace(/~/g, '\\~')
1217 .replace(/`/g, '\\`');
1218 embed.setColor(musicbot.embedColor);
1219 embed.addField(videos[song_number].channelTitle, `[${songTitle}](${videos[song_number].url})`, musicbot.inlineEmbeds);
1220 embed.addField("Queued On", videos[song_number].queuedOn, musicbot.inlineEmbeds);
1221 if (!musicbot.bigPicture) embed.setThumbnail(`https://img.youtube.com/vi/${videos[song_number].id}/maxresdefault.jpg`);
1222 if (musicbot.bigPicture) embed.setImage(`https://img.youtube.com/vi/${videos[song_number].id}/maxresdefault.jpg`);
1223 const resMem = client.users.cache.get(videos[song_number].requester);
1224 if (musicbot.requesterName && resMem) embed.setFooter(`Song added by: ${client.users.cache.get(videos[song_number].requester).username}`, videos[song_number].requesterAvatarURL);
1225 if (musicbot.requesterName && !resMem) embed.setFooter(`Song added by: \`UnknownUser (ID: ${videos[song_number].requester})\``, videos[song_number].requesterAvatarURL);
1226 msg.channel.send({
1227 embed
1228 }).then(() => {
1229 queue.songs.push(videos[song_number]);
1230 if (queue.songs.length === 1 || !client.voice.connections.find(val => val.channel.guild.id == msg.guild.id)) musicbot.executeQueue(msg, queue);
1231 })
1232 .catch(console.log);
1233 };
1234 })
1235 .catch(collected => {
1236 musicbot.userSearching.delete(us);
1237 if (collected.toString()
1238 .match(/error|Error|TypeError|RangeError|Uncaught/)) return firstMsg.edit(`\`\`\`xl\nSearching canceled. ${collected}\n\`\`\``);
1239 return firstMsg.edit(`\`\`\`xl\nSearching canceled.\n\`\`\``);
1240 });
1241 })
1242 }
1243 };
1244
1245 const max = searchResult.totalResults >= 10 ? 9 : searchResult.totalResults - 1;
1246 var videos = [];
1247 for (var i = 0; i < 99; i++) {
1248 var result = searchResult.currentPage[i];
1249 result.requester = msg.author.id;
1250 if (musicbot.requesterName) result.requesterAvatarURL = msg.author.displayAvatarURL();
1251 result.channelURL = `https://www.youtube.com/channel/${result.channelId}`;
1252 result.queuedOn = new Date().toLocaleDateString(musicbot.dateLocal, { weekday: 'long', hour: 'numeric' });
1253 videos.push(result);
1254 if (i === max) {
1255 i = 101;
1256 startTheFun(videos, max);
1257 }
1258 };
1259 });
1260 })
1261 .catch(console.log);
1262 };
1263
1264 musicbot.volumeFunction = (msg, suffix, args) => {
1265 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `No estás en un canal de voz.`));
1266 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
1267 if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'No music is being played.'));
1268 if (voiceConnection && voiceConnection.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
1269 if (!musicbot.canAdjust(msg.member, musicbot.queues.get(msg.guild.id))) return msg.channel.send(musicbot.note('fail', `Only admins or DJ's may change volume.`));
1270 const dispatcher = voiceConnection.dispatcher;
1271
1272 if (!suffix || isNaN(suffix)) return msg.channel.send(musicbot.note('fail', 'No volume specified.'));
1273 suffix = parseInt(suffix);
1274 if (suffix > 200 || suffix <= 0) return msg.channel.send(musicbot.note('fail', 'Volume out of range, must be within 1 to 200'));
1275
1276 dispatcher.setVolume((suffix / 100));
1277 musicbot.queues.get(msg.guild.id).volume = suffix;
1278 msg.channel.send(musicbot.note('note', `Volume changed to ${suffix}%.`));
1279 };
1280
1281 musicbot.clearFunction = (msg, suffix, args) => {
1282 if (!musicbot.queues.has(msg.guild.id)) return msg.channel.send(musicbot.note("fail", "No queue found for this server."));
1283 if (!musicbot.isAdmin(msg.member)) return msg.channel.send(musicbot.note("fail", `Only Admins or people with the ${musicbot.djRole} can clear queues.`));
1284 let vc = client.voice.connections.find(val => val.channel.guild.id == msg.member.guild.id)
1285 if (vc && vc.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
1286 musicbot.emptyQueue(msg.guild.id).then(res => {
1287 msg.channel.send(musicbot.note("note", "Queue cleared."));
1288 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
1289 if (voiceConnection !== null) {
1290 const dispatcher = voiceConnection.dispatcher;
1291 if (!dispatcher || dispatcher === null) {
1292 if (musicbot.logging) return console.log(new Error(`dispatcher null on skip cmd [${msg.guild.name}] [${msg.author.username}]`));
1293 return msg.channel.send(musicbot.note("fail", "Something went wrong."));
1294 };
1295 if (voiceConnection.paused) dispatcher.destroy();
1296 dispatcher.destroy();
1297 }
1298 }).catch(res => {
1299 console.error(new Error(`[clearCmd] [${msg.guild.id}] ${res}`))
1300 return msg.channel.send(musicbot.note("fail", "Something went wrong clearing the queue."));
1301 })
1302 };
1303
1304 musicbot.removeFunction = (msg, suffix, args) => {
1305 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `You are not in a voice channel.`));
1306 if (!musicbot.queues.has(msg.guild.id)) return msg.channel.send(musicbot.note('fail', `No queue for this server found!`));
1307 if (!suffix) return msg.channel.send(musicbot.note("fail", "No video position given."));
1308 let vc = client.voice.connections.find(val => val.channel.guild.id == msg.member.guild.id)
1309 if (vc && vc.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
1310 if (parseInt(suffix) - 1 == 0) return msg.channel.send(musicbot.note("fail", "You cannot clear the currently playing music."));
1311 let test = musicbot.queues.get(msg.guild.id).songs.find(x => x.position == parseInt(suffix) - 1);
1312 if (test) {
1313 if (test.requester !== msg.author.id && !musicbot.isAdmin(msg.member)) return msg.channel.send(musicbot.note("fail", "You cannot remove that item."));
1314 let newq = musicbot.queues.get(msg.guild.id).songs.filter(s => s !== test);
1315 musicbot.updatePositions(musicbot.queues.get(msg.guild.id), msg.guild.id).then(res => {
1316 musicbot.queues.get(msg.guild.id).songs = res;
1317 msg.channel.send(musicbot.note("note", `Removed: \`${test.title.replace(/`/g, "'")}\``));
1318 }).catch(e=> {
1319 console.log(e)
1320 console.log("@ remove function");
1321 })
1322 } else {
1323 msg.channel.send(musicbot.note("fail", "Couldn't find that video or something went wrong."));
1324 }
1325 };
1326
1327 musicbot.loopFunction = (msg, suffix, args) => {
1328 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `You are not in a voice channel.`));
1329 if (!musicbot.queues.has(msg.guild.id)) return msg.channel.send(musicbot.note('fail', `No queue for this server found!`));
1330 let vc = client.voice.connections.find(val => val.channel.guild.id == msg.member.guild.id)
1331 if (vc && vc.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as me.`));
1332 if (musicbot.queues.get(msg.guild.id).loop == "none" || musicbot.queues.get(msg.guild.id).loop == null) {
1333 musicbot.queues.get(msg.guild.id).loop = "song";
1334 msg.channel.send(musicbot.note('note', 'Looping single enabled! :repeat_one:'));
1335 } else if (musicbot.queues.get(msg.guild.id).loop == "song") {
1336 musicbot.queues.get(msg.guild.id).loop = "queue";
1337 msg.channel.send(musicbot.note('note', 'Looping queue enabled! :repeat:'));
1338 } else if (musicbot.queues.get(msg.guild.id).loop == "queue") {
1339 musicbot.queues.get(msg.guild.id).loop = "none";
1340 msg.channel.send(musicbot.note('note', 'Looping disabled! :arrow_forward:'));
1341 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
1342 const dispatcher = voiceConnection.dispatcher;
1343 let wasPaused = dispatcher.paused;
1344 if (wasPaused) dispatcher.pause();
1345 let newq = musicbot.queues.get(msg.guild.id).songs.slice(musicbot.queues.get(msg.guild.id).last.position - 1);
1346 if (newq !== musicbot.queues.get(msg.guild.id).songs) musicbot.updatePositions(musicbot.queues.get(msg.guild.id), msg.guild.id).then(res => {
1347 musicbot.queues.get(msg.guild.id).songs = res;
1348 }).catch(e=> {
1349 console.log(e)
1350 console.log("@ loop function");
1351 })
1352 if (wasPaused) dispatcher.resume();
1353 }
1354 };
1355 musicbot.shuffleFunction = (msg, suffix, args) => {
1356 let q = musicbot.getQueue(msg.guild.id);
1357 if (q.working == true) return msg.channel.send(musicbot.note('fail', `The server queue is already performing a task!`));
1358 if (!msg.member.voice.channel) return msg.channel.send(musicbot.note('fail', `You are not in a voice channel.`));
1359 if (!musicbot.queues.has(msg.guild.id)) return msg.channel.send(musicbot.note('fail', `No queue found!`));
1360 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
1361 if (voiceConnection && voiceConnection.channel.id != msg.member.voice.channel.id) return msg.channel.send(musicbot.note('fail', `You must be in the same voice channel as the bot.`));
1362 if (musicbot.queues.get(msg.guild.id).songs.length < musicbot.minShuffle) return msg.channel.send(musicbot.note('fail', `Queue must have a minimum of ${musicbot.minShuffle} songs to shuffle!`));
1363 if (musicbot.queues.get(msg.guild.id).loop == "song") return msg.channel.send(musicbot.note("fail", `Cannot shuffle while loop is set to single.`));
1364 const dispatcher = voiceConnection.dispatcher;
1365 q.oldSongs = q.songs;
1366 q.songs.musicBotShuffle();
1367 q.needsRefresh = true;
1368 musicbot.updatePositions(q, msg.guild.id).then((res) => {
1369 q.songs = res.songs;
1370 musicbot.queues.set(msg.guild.id, q);
1371 if (voiceConnection.paused) dispatcher.resume();
1372 msg.channel.send(musicbot.note('note', `Queue shuffled.`));
1373
1374 dispatcher.end();
1375 }).catch((res) => {
1376 msg.channel.send(musicbot.note("fail", "I was unable to shuffle the queue."))
1377 console.log("@shuffleFunction " + res);
1378 })
1379 };
1380
1381 musicbot.loadCommand = (obj) => {
1382 return new Promise((resolve, reject) => {
1383 let props = {
1384 enabled: obj.enabled,
1385 run: obj.run,
1386 alt: obj.alt,
1387 help: obj.help,
1388 name: obj.name,
1389 exclude: obj.exclude,
1390 masked: obj.masked
1391 };
1392 if (props.enabled == undefined || null) props.enabled = true;
1393 if (obj.alt.length > 0) {
1394 obj.alt.forEach((a) => {
1395 musicbot.aliases.set(a, props);
1396 })
1397 };
1398 musicbot.commands.set(obj.name, props);
1399 musicbot.commandsArray.push(props);
1400 resolve(musicbot.commands.get(obj.name));
1401 });
1402 }
1403
1404 musicbot.executeQueue = (msg, queue) => {
1405 musicbot.queues.set(queue.id, queue);
1406 if (queue.songs.length < 1) {
1407 msg.channel.send(musicbot.note('note', "Queue Finished."));
1408 if (musicbot.musicPresence) musicbot.updatePresence(musicbot.queues.get(msg.guild.id), msg.client, musicbot.clearPresence).catch((res) => { console.warn(`[MUSIC] Problem updating MusicPresence`); });
1409 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
1410 if (voiceConnection) return voiceConnection.channel.leave();
1411 };
1412
1413 new Promise((resolve, reject) => {
1414 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
1415 if (!voiceConnection) {
1416 if (msg.member.voice.channel && msg.member.voice.channel.joinable) {
1417 msg.member.voice.channel.join()
1418 .then(connection => {
1419 resolve(connection);
1420 })
1421 .catch((error) => {
1422 console.log(error);
1423 });
1424 } else if (!msg.member.voice.channel.joinable || msg.member.voice.channel.full) {
1425 msg.channel.send(musicbot.note('fail', 'I do not have permission to join your voice channel!'))
1426 reject();
1427 } else {
1428 musicbot.emptyQueue(msg.guild.id).then(() => {
1429 reject();
1430 })
1431 }
1432 } else {
1433 resolve(voiceConnection);
1434 }
1435 }).then(async connection => {
1436 let video;
1437 if (!queue.last) {
1438 video = queue.songs[0];
1439 } else {
1440 if (queue.loop == "queue") {
1441 video = queue.songs.find(s => s.position == queue.last.position + 1);
1442 if (!video || video && !video.url) video = queue.songs[0];
1443 } else if (queue.loop == "single") {
1444 video = queue.last;
1445 } else {
1446 video = queue.songs.find(s => s.position == queue.last.position);
1447 };
1448 }
1449 if (!video) {
1450 video = queue.songs ? queue.songs[0] : false;
1451 if (!video) {
1452 msg.channel.send(musicbot.note('note', 'Playback finished!'));
1453 musicbot.emptyQueue(msg.guild.id);
1454 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
1455 if (voiceConnection !== null) return voiceConnection.disconnect();
1456 }
1457 }
1458 let timee = await fetch(`https://tao-is-developing.online/api/search/?q=${video.id}`).then(asd => asd.json())
1459 if (musicbot.messageNewSong == true && queue.last && queue.loop !== "song") {
1460 let req = client.users.cache.get(video.requester);
1461 if (msg.channel.permissionsFor(msg.guild.me).has('EMBED_LINKS')) {
1462 const embed = new Discord.MessageEmbed()
1463 .setTitle("Playing now:", `${req !== null ? req.displayAvatarURL() : null}`)
1464 .setThumbnail(`https://img.youtube.com/vi/${video.id}/maxresdefault.jpg`)
1465 .setDescription(`Title: [${video.title.replace(/\\/g, '\\\\').replace(/\`/g, '\\`').replace(/\*/g, '\\*').replace(/_/g, '\\_').replace(/~/g, '\\~').replace(/`/g, '\\`')}](${video.url})
1466
1467 Author: [${video.channelTitle}](${video.channelURL})\nTime: ${video.duration}`)
1468 .setColor(musicbot.embedColor)
1469 .setFooter(`Song added by: ${req !== null ? req.username : "Unknown User"}`, `${req !== null ? req.displayAvatarURL() : null}`);
1470 msg.channel.send({embed});
1471 } else {
1472 msg.channel.send(musicbot.note("note", `\`${video.title.replace(/`/g, "''")}\` by \`${video.channelURL.replace(/`/g, "''")}\``))
1473 }
1474 }
1475
1476 try {
1477 musicbot.setLast(msg.guild.id, video).then(() => {
1478 if (musicbot.musicPresence) musicbot.updatePresence(queue, msg.client, musicbot.clearPresence).catch((res) => { console.warn(`[MUSIC] Problem updating MusicPresence`); });
1479 });
1480
1481 let dispatcher = connection.play(await ytdl(video.url, {
1482 filter: 'audioonly',
1483 highWaterMark: 1 << 25,
1484 }), {
1485 type: "opus",
1486 volume: (queue.volume / 100)
1487 })
1488
1489 connection.on('error', (error) => {
1490 console.error(error);
1491 if (msg && msg.channel) msg.channel.send(musicbot.note('fail', `Something went wrong with the connection. Retrying queue...`));
1492 musicbot.executeQueue(msg, queue);
1493 });
1494
1495 dispatcher.on('debug', (d) => {
1496 console.log(d);
1497 });
1498
1499 dispatcher.on('finish', () => {
1500 if (musicbot.queues.get(queue.id).needsRefresh) {
1501 queue = musicbot.queues.get(queue.id);
1502 queue.needsRefresh = false;
1503 musicbot.queues.set(queue.id, queue)
1504 }
1505 let loop = queue.loop;
1506 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
1507 if (voiceConnection && voiceConnection.channel.members.size <= 1){
1508 msg.channel.send(musicbot.note('note', 'All members have left the voice channel. Disconnected.'))
1509 musicbot.queues.set(msg.guild.id, {songs: [], last: null, loop: "none", id: msg.guild.id, volume: musicbot.defVolume, oldSongs: [],working: false, needsRefresh: false});
1510 console.log(musicbot.musicPresence)
1511 if (musicbot.musicPresence) musicbot.updatePresence(musicbot.queues.get(msg.guild.id), msg.client, musicbot.clearPresence).catch((res) => { console.warn(`[MUSIC] Problem updating MusicPresence`); });
1512 return voiceConnection.disconnect();
1513 }
1514 if (queue.songs.length > 0) {
1515 if (loop == "none" || !loop) {
1516 queue.songs.shift();
1517 musicbot.updatePositions(queue, msg ? msg.guild.id : 0).then(res => {
1518 queue.songs = typeof res.songs == "object" ? Array.from(res.songs) : [];
1519 musicbot.executeQueue(msg, queue);
1520 }).catch(e=> {
1521 console.log(e)
1522 console.log("@ dispatcher function");
1523 })
1524 } else if (loop == "queue" || loop == "song") {
1525 musicbot.executeQueue(msg, queue);
1526 };
1527 } else if (queue.songs.length <= 0) {
1528 if (msg && msg.channel) msg.channel.send(musicbot.note('note', 'I will go to rest.'));
1529 musicbot.queues.set(msg.guild.id, {songs: [], last: null, loop: "none", id: msg.guild.id, volume: musicbot.defVolume, oldSongs: [],working: false, needsRefresh: false});
1530 console.log(musicbot.musicPresence)
1531 if (musicbot.musicPresence) musicbot.updatePresence(queue, msg.client, musicbot.clearPresence).catch((res) => { console.warn(`[MUSIC] Problem updating MusicPresence`); });
1532 const voiceConnection = client.voice.connections.find(val => val.channel.guild.id == msg.guild.id);
1533 if (voiceConnection) return voiceConnection.disconnect();
1534 }
1535 });
1536 } catch (error) {
1537 console.log(error);
1538 }
1539 })
1540 .catch((error) => {
1541 console.log(error);
1542 });
1543 }
1544
1545 musicbot.note = (type, text) => {
1546 if (type === 'wrap') {
1547 let ntext = text
1548 .replace(/`/g, '`' + String.fromCharCode(8203))
1549 .replace(/@/g, '@' + String.fromCharCode(8203))
1550 .replace(client.token, 'REMOVED');
1551 return '```\n' + ntext + '\n```';
1552 } else if (type === 'note') {
1553 return text.replace(/`/g, '`' + String.fromCharCode(8203));
1554 } else if (type === 'search') {
1555 return text.replace(/`/g, '`' + String.fromCharCode(8203));
1556 } else if (type === 'fail') {
1557 return text.replace(/`/g, '`' + String.fromCharCode(8203));
1558 } else if (type === 'font') {
1559 return text.replace(/`/g, '`' + String.fromCharCode(8203))
1560 .replace(/@/g, '@' + String.fromCharCode(8203))
1561 .replace(/\\/g, '\\\\')
1562 .replace(/\*/g, '\\*')
1563 .replace(/_/g, '\\_')
1564 .replace(/~/g, '\\~')
1565 .replace(/`/g, '\\`');
1566 } else {
1567 console.error(new Error(`${type} era un tipo no válido`));
1568 }
1569 };
1570
1571 musicbot.loadCommands = async () => {
1572 try {
1573 await musicbot.loadCommand(musicbot.play);
1574 await musicbot.loadCommand(musicbot.remove);
1575 await musicbot.loadCommand(musicbot.musichelp);
1576 await musicbot.loadCommand(musicbot.skip);
1577 await musicbot.loadCommand(musicbot.leave);
1578 await musicbot.loadCommand(musicbot.search);
1579 await musicbot.loadCommand(musicbot.pause);
1580 await musicbot.loadCommand(musicbot.resume);
1581 await musicbot.loadCommand(musicbot.volume);
1582 await musicbot.loadCommand(musicbot.queue);
1583 await musicbot.loadCommand(musicbot.loop);
1584 await musicbot.loadCommand(musicbot.clearqueue);
1585 await musicbot.loadCommand(musicbot.np);
1586 await musicbot.loadCommand(musicbot.shuffle)
1587 await musicbot.loadCommand(musicbot.deleteQueue)
1588 } catch (e) {
1589 console.error(new Error(e));
1590 };
1591 }
1592 musicbot.loadCommands();
1593
1594 try {
1595 Object.defineProperty(Array.prototype, 'musicArraySort', {value: function(n) {
1596 return Array.from(Array(Math.ceil(this.length/n)), (_,i)=>this.slice(i*n,i*n+n));
1597 }});
1598 Object.defineProperty(Array.prototype, 'musicBotShuffle', {value: function() {
1599 let input = this;
1600 for (let i = input.length - 1; i >= 0; i--) {
1601 let randomIndex = Math.floor(Math.random() * (i + 1));
1602 let itemAtIndex = input[randomIndex];
1603 input[randomIndex] = input[i];
1604 input[i] = itemAtIndex;
1605 }
1606 return input;
1607 }});
1608 } catch (e) {
1609 throw new Error("Could not define musicArraySort or musicBotShuffle property (s), you are probably running this script twice. Error: " + e.stack)
1610 };
1611 } catch (e) {
1612 console.error(e);
1613 };
1614}