import { Message } from "discord.js"; import { AkairoClient } from "discord-akairo"; import ytdlDiscord from 'ytdl-core-discord'; import * as scdl from 'soundcloud-downloader'; import { StreamDispatcher } from "discord.js"; import { MessageCollector } from "discord.js"; import Util from '../utils/Utils'; module.exports = { async play(song, client: AkairoClient, msg: Message) { const { PRUNING, SOUNDCLOUD_CLIENT_ID } = require('../Config'); const queue = client.queue.get(msg.guild.id); if (!song) { queue.channel.leave(); client.queue.delete(msg.guild.id); return queue.channel.send('Music queue ended.'); // catch } let stream = null; try { if (song.url.includes('youtube.com')) { stream = await ytdlDiscord(song.url, { highWaterMark: 1 << 25 }); } else if (song.url.includes('soundcloud.com') && SOUNDCLOUD_CLIENT_ID) { stream = await scdl.downloadFormat(song.url, scdl.FORMATS.OPUS, SOUNDCLOUD_CLIENT_ID); } } catch (error) { if (queue) { queue.songs.shift(); module.exports.play(queue.songs[0], msg); } // error return msg.channel.send(`Error: ${error.message ? error.message : error}`); } queue.connection.on('disconnect', () => client.queue.delete(msg.guild.id)); const type = song.url.includes('youtube.com') ? 'opus' : 'ogg/opus'; const dispatcher: StreamDispatcher = queue.connection .play(stream, { type: type }) .on('finish', () => { if (collector && !collector.ended) collector.stop(); if (queue.loop) { let lastSong = queue.songs.shift(); queue.songs.push(lastSong); // export } else { queue.songs.shift(); // export } }) .on('error', (err) => { // error queue.songs.shift(); module.exports.play(queue.songs[0], msg); }); dispatcher.setVolumeLogarithmic(queue.volume / 100); try { var playingMessage = await queue.channel.send(`Started playing: **${song.title}** ${song.url}`); await playingMessage.react("⏭"); await playingMessage.react("⏯"); await playingMessage.react("🔁"); await playingMessage.react("⏹"); } catch (error) { // error } const filter = (reaction, user) => user.id !== client.user.id; var collector: MessageCollector = playingMessage.createReactionCollector(filter, { time: song.duration > 0 ? song.duration * 1000 : 600000 }); collector.on('collect', (reaction, user) => { if (!queue) return; const member = msg.guild.member(user); switch (reaction.emoji.name) { case "⏭": queue.playing = true; reaction.users.remove(user).catch(console.error); if (!Util.canModifyQueue(member)) return; queue.connection.dispatcher.end(); queue.textChannel.send(`${user} ⏩ skipped the song`).catch(console.error); collector.stop(); break; case "⏯": reaction.users.remove(user).catch(console.error); if (!Util.canModifyQueue(member)) return; if (queue.playing) { queue.playing = !queue.playing; queue.connection.dispatcher.pause(true); queue.textChannel.send(`${user} ⏸ paused the music.`).catch(console.error); } else { queue.playing = !queue.playing; queue.connection.dispatcher.resume(); queue.textChannel.send(`${user} ▶ resumed the music!`).catch(console.error); } break; case "🔁": reaction.users.remove(user).catch(console.error); if (!Util.canModifyQueue(member)) return; queue.loop = !queue.loop; queue.textChannel.send(`Loop is now ${queue.loop ? "**on**" : "**off**"}`).catch(console.error); break; case "⏹": reaction.users.remove(user).catch(console.error); if (!Util.canModifyQueue(member)) return; queue.songs = []; queue.textChannel.send(`${user} ⏹ stopped the music!`).catch(console.error); try { queue.connection.dispatcher.end(); } catch (error) { console.error(error); queue.connection.disconnect(); } collector.stop(); break; default: reaction.users.remove(user).catch(console.error); break; } }); collector.on('end', () => { playingMessage.reactions.removeAll(); // catch if (PRUNING && playingMessage && !playingMessage.deleted) playingMessage.delete({ timeout: 3000 }); // catch }); } }