summaryrefslogtreecommitdiff
path: root/src/commands/voice
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands/voice')
-rw-r--r--src/commands/voice/abee.ts199
-rw-r--r--src/commands/voice/itemshop.ts209
-rw-r--r--src/commands/voice/join.js31
-rw-r--r--src/commands/voice/leave.js34
-rw-r--r--src/commands/voice/loop.js34
-rw-r--r--src/commands/voice/minecraft.ts204
-rw-r--r--src/commands/voice/pause.js32
-rw-r--r--src/commands/voice/play.ts292
-rw-r--r--src/commands/voice/psycho.ts198
-rw-r--r--src/commands/voice/queue.js51
-rw-r--r--src/commands/voice/remove.js41
-rw-r--r--src/commands/voice/resume.js32
-rw-r--r--src/commands/voice/shuffle.js53
-rw-r--r--src/commands/voice/skip.js29
-rw-r--r--src/commands/voice/skipall.js44
-rw-r--r--src/commands/voice/skipto.js43
-rw-r--r--src/commands/voice/volume.js45
17 files changed, 1571 insertions, 0 deletions
diff --git a/src/commands/voice/abee.ts b/src/commands/voice/abee.ts
new file mode 100644
index 0000000..939b575
--- /dev/null
+++ b/src/commands/voice/abee.ts
@@ -0,0 +1,199 @@
+import ytdl from 'ytdl-core';
+import { Command } from 'discord.js-commando';
+import { MessageEmbed, Message } from 'discord.js';
+import Youtube from 'simple-youtube-api';
+//const { youtubeAPI } = require('../../config.json');
+import config from '../../config.json';
+const youtube = new Youtube(config['yt-api-key']);
+import emoji from 'emoji-random';
+
+module.exports = class ABeeVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'abee',
+ aliases: ['a-bee'],
+ group: 'voice',
+ memberName: 'abee',
+ description: 'A bee 🐝',
+ guildOnly: true,
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ examples: ['uwu!abee', 'uwu!a-bee'],
+ });
+ }
+ async run(msg: Message) {
+ const voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.say('Please join a channel and try again. ' + emoji.random());
+
+ const id = 'lvdnhWhQBdo';
+ const video = await youtube.getVideoByID(id).catch(function () {
+ return msg.say(
+ 'There was a problem getting the video you provided. ' + emoji.random()
+ );
+ });
+ // // can be uncommented if you don't want the bot to play live streams
+ // if (video.raw.snippet.liveBroadcastContent === 'live') {
+ // return msg.say("I don't support live streams!");
+ // }
+ // // can be uncommented if you don't want the bot to play videos longer than 1 hour
+ // if (video.duration.hours !== 0) {
+ // return msg.say('I cannot play videos longer than 1 hour');
+ // }
+ // // can be uncommented if you want to limit the queue
+ // if (msg.guild.musicData.queue.length > 10) {
+ // return msg.say(
+ // 'There are too many songs in the queue already, skip or wait a bit'
+ // );
+ // }
+ msg.guild.musicData.queue.push(
+ this.constructSongObj(video, voiceChannel)
+ );
+ if (
+ msg.guild.musicData.isPlaying == false ||
+ typeof msg.guild.musicData.isPlaying == 'undefined'
+ ) {
+ msg.guild.musicData.isPlaying = true;
+ return this.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ return msg.say(`${video.title} added to queue. ` + emoji.random());
+ }
+
+ var that = this;
+ msg.channel
+ .awaitMessages(
+ function (msg) {
+ return (msg.content > 0 && msg.content < 6) || msg.content === 'exit';
+ }, {
+ max: 1,
+ time: 60000,
+ errors: ['time']
+ }
+ )
+ .then(function (response) {
+ const videoIndex = parseInt(response.first().content);
+ if (response.first().content === 'exit') return songEmbed.delete();
+ youtube
+ .getVideoByID(videos[videoIndex - 1].id)
+ .then(function (video) {
+ // // can be uncommented if you don't want the bot to play live streams
+ // if (video.raw.snippet.liveBroadcastContent === 'live') {
+ // songEmbed.delete();
+ // return msg.say("I don't support live streams!");
+ // }
+
+ // // can be uncommented if you don't want the bot to play videos longer than 1 hour
+ // if (video.duration.hours !== 0) {
+ // songEmbed.delete();
+ // return msg.say('I cannot play videos longer than 1 hour');
+ // }
+
+ // // can be uncommented if you don't want to limit the queue
+ // if (msg.guild.musicData.queue.length > 10) {
+ // songEmbed.delete();
+ // return msg.say(
+ // 'There are too many songs in the queue already, skip or wait a bit'
+ // );
+ // }
+ msg.guild.musicData.queue.push(
+ that.constructSongObj(video, voiceChannel)
+ );
+ if (msg.guild.musicData.isPlaying == false) {
+ msg.guild.musicData.isPlaying = true;
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ that.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say(`${video.title} added to queue. ` + emoji.random());
+ }
+ })
+ .catch(function () {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say(
+ 'An error has occured when trying to get the video ID from YouTube. ' + emoji.random()
+ );
+ });
+ });
+ }
+ playSong(queue, msg) {
+ const classThis = this; // use classThis instead of 'this' because of lexical scope below
+ queue[0].voiceChannel
+ .join()
+ .then(function (connection) {
+ const dispatcher = connection
+ .play(
+ ytdl(queue[0].url, {
+ quality: 'highestaudio',
+ highWaterMark: 1024 * 1024 * 10
+ })
+ )
+ .on('start', function () {
+ msg.guild.musicData.songDispatcher = dispatcher;
+ const volume = 100 / 100;
+ msg.guild.musicData.volume = volume;
+ dispatcher.setVolume(msg.guild.musicData.volume);
+ const videoEmbed = new MessageEmbed()
+ .setThumbnail(queue[0].thumbnail)
+ .setColor(0xF97DAE)
+ .addField('Now playing:', queue[0].title)
+ .addField('Duration:', queue[0].duration);
+ if (queue[1]) videoEmbed.addField('Next song:', queue[1].title);
+ msg.say(videoEmbed);
+ msg.guild.musicData.nowPlaying = queue[0];
+ return queue.shift();
+ })
+ .on('finish', function () {
+ if (queue.length >= 1) {
+ return classThis.playSong(queue, msg);
+ } else {
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ }
+ })
+ .on('error', function (e) {
+ msg.say('Can\'t play song. ' + emoji.random());
+ console.error(e);
+ msg.guild.musicData.queue.length = 0;
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ });
+ })
+ .catch(function (e) {
+ console.error(e);
+ return msg.guild.me.voice.channel.leave();
+ });
+ }
+ constructSongObj(video, voiceChannel) {
+ let duration = this.formatDuration(video.duration);
+ if (duration == '00:00') duration = 'Live Stream';
+ return {
+ url: `https://www.youtube.com/watch?v=${video.raw.id}`,
+ title: video.title,
+ duration,
+ thumbnail: video.thumbnails.high.url,
+ voiceChannel
+ };
+ }
+ // prettier-ignore
+ formatDuration(durationObj) {
+ const duration = `${durationObj.hours ? (durationObj.hours + ':') : ''}${
+ durationObj.minutes ? durationObj.minutes : '00'
+ }:${
+ (durationObj.seconds < 10)
+ ? ('0' + durationObj.seconds)
+ : (durationObj.seconds
+ ? durationObj.seconds
+ : '00')
+ }`;
+ return duration;
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/itemshop.ts b/src/commands/voice/itemshop.ts
new file mode 100644
index 0000000..f8c0b2b
--- /dev/null
+++ b/src/commands/voice/itemshop.ts
@@ -0,0 +1,209 @@
+import ytdl from 'ytdl-core';
+import { Command } from 'discord.js-commando';
+import { MessageEmbed, Message } from 'discord.js';
+import Youtube from 'simple-youtube-api';
+//const { youtubeAPI } = require('../../config.json');
+import config from '../../config.json';
+const youtube = new Youtube(config['yt-api-key']);
+import emoji from 'emoji-random';
+
+module.exports = class ABeeVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'itemshop',
+ aliases: ['item-shop'],
+ group: 'voice',
+ memberName: 'itemshop',
+ description: 'Use code \'Frozen\' in the Fortnite item shop.',
+ guildOnly: true,
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ examples: ['uwu!itemshop', 'uwu!item-shop']
+ });
+ }
+ async run(msg: Message) {
+ const voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.say('Please join a channel and try again. ' + emoji.random());
+
+ const id = 'pBiI1hTwU7E';
+ const video = await youtube.getVideoByID(id).catch(function () {
+ return msg.say(
+ 'There was a problem getting the video you provided. ' + emoji.random()
+ );
+ });
+ // // can be uncommented if you don't want the bot to play live streams
+ // if (video.raw.snippet.liveBroadcastContent === 'live') {
+ // return msg.say("I don't support live streams!");
+ // }
+ // // can be uncommented if you don't want the bot to play videos longer than 1 hour
+ // if (video.duration.hours !== 0) {
+ // return msg.say('I cannot play videos longer than 1 hour');
+ // }
+ // // can be uncommented if you want to limit the queue
+ // if (msg.guild.musicData.queue.length > 10) {
+ // return msg.say(
+ // 'There are too many songs in the queue already, skip or wait a bit'
+ // );
+ // }
+ msg.guild.musicData.queue.push(
+ this.constructSongObj(video, voiceChannel)
+ );
+ if (
+ msg.guild.musicData.isPlaying == false ||
+ typeof msg.guild.musicData.isPlaying == 'undefined'
+ ) {
+ msg.guild.musicData.isPlaying = true;
+ return this.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ return msg.say(`${video.title} added to queue. ` + emoji.random());
+ }
+
+ var that = this;
+ msg.channel
+ .awaitMessages(
+ function (msg) {
+ return (msg.content > 0 && msg.content < 6) || msg.content === 'exit';
+ }, {
+ max: 1,
+ time: 60000,
+ errors: ['time']
+ }
+ )
+ .then(function (response) {
+ const videoIndex = parseInt(response.first().content);
+ if (response.first().content === 'exit') return songEmbed.delete();
+ youtube
+ .getVideoByID(videos[videoIndex - 1].id)
+ .then(function (video) {
+ // // can be uncommented if you don't want the bot to play live streams
+ // if (video.raw.snippet.liveBroadcastContent === 'live') {
+ // songEmbed.delete();
+ // return msg.say("I don't support live streams!");
+ // }
+
+ // // can be uncommented if you don't want the bot to play videos longer than 1 hour
+ // if (video.duration.hours !== 0) {
+ // songEmbed.delete();
+ // return msg.say('I cannot play videos longer than 1 hour');
+ // }
+
+ // // can be uncommented if you don't want to limit the queue
+ // if (msg.guild.musicData.queue.length > 10) {
+ // songEmbed.delete();
+ // return msg.say(
+ // 'There are too many songs in the queue already, skip or wait a bit'
+ // );
+ // }
+ msg.guild.musicData.queue.push(
+ that.constructSongObj(video, voiceChannel)
+ );
+ if (msg.guild.musicData.isPlaying == false) {
+ msg.guild.musicData.isPlaying = true;
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ that.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ msg.say(`${video.title} added to queue. ` + emoji.random());
+ return;
+ }
+ })
+ .catch(function () {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say(
+ 'An error has occured when trying to get the video ID from Youtube.' + emoji.random()
+ );
+ });
+ });
+ }
+ playSong(queue, msg) {
+ const classThis = this; // use classThis instead of 'this' because of lexical scope below
+ queue[0].voiceChannel
+ .join()
+ .then(function (connection) {
+ const dispatcher = connection
+ .play(
+ ytdl(queue[0].url, {
+ quality: 'highestaudio',
+ highWaterMark: 1024 * 1024 * 10
+ })
+
+ )
+ .on('start', function () {
+ msg.guild.musicData.songDispatcher = dispatcher;
+ const volume = 100 / 100;
+ msg.guild.musicData.volume = volume;
+ dispatcher.setVolume(msg.guild.musicData.volume);
+ const videoEmbed = new MessageEmbed()
+ .setThumbnail(queue[0].thumbnail)
+ .setColor(0xF97DAE)
+ .addField('Now playing:', queue[0].title)
+ .addField('Duration:', queue[0].duration);
+ if (queue[1]) videoEmbed.addField('Next song:', queue[1].title);
+ msg.say(videoEmbed);
+ msg.guild.musicData.nowPlaying = queue[0];
+ return queue.shift();
+ })
+ .on('finish', function () {
+ if (queue.length >= 1) {
+ return classThis.playSong(queue, msg);
+ } else {
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ }
+ })
+ .on('error', function (e) {
+ msg.say('Can\'t play song. ' + emoji.random());
+ console.error(e);
+ msg.guild.musicData.queue.length = 0;
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ });
+ function timeCheck() {
+ if (dispatcher.streamTime >= 6000) {
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ }
+ }
+ setInterval(timeCheck, 500);
+ })
+ .catch(function (e) {
+ console.error(e);
+ return msg.guild.me.voice.channel.leave();
+ });
+ }
+ constructSongObj(video, voiceChannel) {
+ let duration = this.formatDuration(video.duration);
+ if (duration == '00:00') duration = 'Live Stream';
+ return {
+ url: `https://www.youtube.com/watch?v=${video.raw.id}`,
+ title: video.title,
+ duration,
+ thumbnail: video.thumbnails.high.url,
+ voiceChannel
+ };
+ }
+ // prettier-ignore
+ formatDuration(durationObj) {
+ const duration = `${durationObj.hours ? (durationObj.hours + ':') : ''}${
+ durationObj.minutes ? durationObj.minutes : '00'
+ }:${
+ (durationObj.seconds < 10)
+ ? ('0' + durationObj.seconds)
+ : (durationObj.seconds
+ ? durationObj.seconds
+ : '00')
+ }`;
+ return duration;
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/join.js b/src/commands/voice/join.js
new file mode 100644
index 0000000..4410e4c
--- /dev/null
+++ b/src/commands/voice/join.js
@@ -0,0 +1,31 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class JoinVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'join',
+ group: 'voice',
+ memberName: 'join',
+ description: 'Joins your current voice channel.',
+ throttling: {
+ usages: 2,
+ duration: 5
+ },
+ guildOnly: true,
+ examples: ['uwu!join'],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg) {
+ if (msg.guild.musicData.isPlaying == false && msg.member.voice.channel) {
+ msg.member.voice.channel.join();
+ msg.reply('Succesfully joined voice channel. ' + emoji.random());
+ } else if (msg.guild.musicData.isPlaying == false) {
+ msg.reply('I\'m already in voice channel. ' + emoji.random());
+ } else if (!msg.member.voice.channel) {
+ msg.reply('Please join a channel and try again. ' + emoji.random());
+ }
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/leave.js b/src/commands/voice/leave.js
new file mode 100644
index 0000000..4c25e62
--- /dev/null
+++ b/src/commands/voice/leave.js
@@ -0,0 +1,34 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class LeaveVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'leave',
+ aliases: ['end', 'stop'],
+ group: 'voice',
+ memberName: 'leave',
+ description: 'Leaves voice channel and stops currently playing audio.',
+ guildOnly: true,
+ examples: ['uwu!leave', 'uwu!end', 'uwu!stop'],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg) {
+ var voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join a channel and try again. ' + emoji.random());
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+ if (!msg.guild.musicData.queue)
+ return msg.say('There aren\'t any songs in the current queue. ' + emoji.random());
+ msg.guild.musicData.songDispatcher.end();
+ msg.guild.musicData.queue.length = 0;
+ return;
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/loop.js b/src/commands/voice/loop.js
new file mode 100644
index 0000000..05c0e99
--- /dev/null
+++ b/src/commands/voice/loop.js
@@ -0,0 +1,34 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class LoopVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'loop',
+ aliases: ['repeat'],
+ group: 'voice',
+ memberName: 'loop',
+ description: 'Loops currently playing audio.',
+ guildOnly: true,
+ examples: ['uwu!loop', 'uwu!repeat'],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg) {
+ var voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join a channel and try again. ' + emoji.random());
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+ msg.channel.send(
+ `${msg.guild.musicData.nowPlaying.title} added to queue. ` + emoji.random()
+ );
+ msg.guild.musicData.queue.unshift(msg.guild.musicData.nowPlaying);
+ return;
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/minecraft.ts b/src/commands/voice/minecraft.ts
new file mode 100644
index 0000000..cad7c06
--- /dev/null
+++ b/src/commands/voice/minecraft.ts
@@ -0,0 +1,204 @@
+import ytdl from 'ytdl-core';
+import { Command } from 'discord.js-commando';
+import { MessageEmbed } from 'discord.js';
+import Youtube from 'simple-youtube-api';
+//const { youtubeAPI } = require('../../config.json');
+import config from '../../config.json';
+const youtube = new Youtube(config['yt-api-key']);
+import emoji from 'emoji-random';
+
+module.exports = class MinecraftVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'minecraft',
+ aliases: ['minecraftsountrack', 'minecraft-soundtrack', 'mcs', 'mc-s'],
+ group: 'voice',
+ memberName: 'minecraft',
+ description: 'Plays the Minecraft soundtrack.',
+ guildOnly: true,
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ examples: [
+ 'uwu!minecraft',
+ 'uwu!minecraftsountrack',
+ 'uwu!minecraft-soundtrack',
+ 'uwu!mcs',
+ 'uwu!mc-s'
+ ]
+ });
+ }
+ async run(msg) {
+ const voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.say('Join a channel and try again. ' + emoji.random());
+
+ const playlist = await youtube.getPlaylist('https://www.youtube.com/watch?v=05UM-i4PuOY&list=PLxOTV5xn7n1i2HcKtRBthP2loWjrBGAIY').catch(function () {
+ return msg.say('There was a problem getting the soundtrack. ' + emoji.random());
+ });
+ // remove the 10 if you removed the queue limit conditions below
+ const videosObj = await playlist.getVideos(24).catch(function () {
+ return msg.say(
+ 'There was a problem getting the soundtrack. ' + emoji.random()
+ );
+ });
+ for (let i = 0; i < videosObj.length; i++) {
+ const video = await videosObj[i].fetch();
+ // this can be uncommented if you choose to limit the queue
+ // if (msg.guild.musicData.queue.length < 10) {
+ //
+ msg.guild.musicData.queue.push(
+ this.constructSongObj(video, voiceChannel)
+ );
+ // } else {
+ // return msg.say(
+ // `I can't play the full playlist because there will be more than 10 songs in queue`
+ // );
+ // }
+ }
+ if (msg.guild.musicData.isPlaying == false) {
+ msg.guild.musicData.isPlaying = true;
+ return this.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ return msg.say(
+ 'Now playing the Minecraft soundtrack. ' + emoji.random()
+ );
+ }
+
+ var that = this;
+ msg.channel
+ .awaitMessages(
+ function (msg) {
+ return (msg.content > 0 && msg.content < 6) || msg.content === 'exit';
+ }, {
+ max: 1,
+ time: 60000,
+ errors: ['time']
+ }
+ )
+ .then(function (response) {
+ const videoIndex = parseInt(response.first().content);
+ if (response.first().content === 'exit') return songEmbed.delete();
+ youtube
+ .getVideoByID(videos[videoIndex - 1].id)
+ .then(function (video) {
+ // // can be uncommented if you don't want the bot to play live streams
+ // if (video.raw.snippet.liveBroadcastContent === 'live') {
+ // songEmbed.delete();
+ // return msg.say("I don't support live streams!");
+ // }
+
+ // // can be uncommented if you don't want the bot to play videos longer than 1 hour
+ // if (video.duration.hours !== 0) {
+ // songEmbed.delete();
+ // return msg.say('I cannot play videos longer than 1 hour');
+ // }
+
+ // // can be uncommented if you don't want to limit the queue
+ // if (msg.guild.musicData.queue.length > 10) {
+ // songEmbed.delete();
+ // return msg.say(
+ // 'There are too many songs in the queue already, skip or wait a bit'
+ // );
+ // }
+ msg.guild.musicData.queue.push(
+ that.constructSongObj(video, voiceChannel)
+ );
+ if (msg.guild.musicData.isPlaying == false) {
+ msg.guild.musicData.isPlaying = true;
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ that.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say('Now playing the Minecraft soundtrack. ' + emoji.random());
+ }
+ })
+ .catch(function () {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say(
+ 'An error has occured when trying to get the video ID from YouTube. ' + emoji.random()
+ );
+ });
+ });
+ }
+ playSong(queue, msg) {
+ const classThis = this; // use classThis instead of 'this' because of lexical scope below
+ queue[0].voiceChannel
+ .join()
+ .then(function (connection) {
+ const dispatcher = connection
+ .play(
+ ytdl(queue[0].url, {
+ quality: 'highestaudio',
+ highWaterMark: 1024 * 1024 * 10
+ })
+ )
+ .on('start', function () {
+ msg.guild.musicData.songDispatcher = dispatcher;
+ const volume = 100 / 100;
+ msg.guild.musicData.volume = volume;
+ dispatcher.setVolume(msg.guild.musicData.volume);
+ const videoEmbed = new MessageEmbed()
+ .setThumbnail(queue[0].thumbnail)
+ .setColor(0xFFCC4D)
+ .addField('Now Playing:', queue[0].title)
+ .addField('Duration:', queue[0].duration);
+ if (queue[1]) videoEmbed.addField('Next Song:', queue[1].title);
+ msg.say(videoEmbed);
+ msg.guild.musicData.nowPlaying = queue[0];
+ return queue.shift();
+ })
+ .on('finish', function () {
+ if (queue.length >= 1) {
+ return classThis.playSong(queue, msg);
+ } else {
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ }
+ })
+ .on('error', function (e) {
+ msg.say('Can\'t play soundtrack. ' + emoji.random());
+ console.error(e);
+ msg.guild.musicData.queue.length = 0;
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ });
+ })
+ .catch(function (e) {
+ console.error(e);
+ return msg.guild.me.voice.channel.leave();
+ });
+ }
+ constructSongObj(video, voiceChannel) {
+ let duration = this.formatDuration(video.duration);
+ if (duration == '00:00') duration = 'Live Stream';
+ return {
+ url: `https://www.youtube.com/watch?v=${video.raw.id}`,
+ title: video.title,
+ duration,
+ thumbnail: video.thumbnails.high.url,
+ voiceChannel
+ };
+ }
+ // prettier-ignore
+ formatDuration(durationObj) {
+ const duration = `${durationObj.hours ? (durationObj.hours + ':') : ''}${
+ durationObj.minutes ? durationObj.minutes : '00'
+ }:${
+ (durationObj.seconds < 10)
+ ? ('0' + durationObj.seconds)
+ : (durationObj.seconds
+ ? durationObj.seconds
+ : '00')
+ }`;
+ return duration;
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/pause.js b/src/commands/voice/pause.js
new file mode 100644
index 0000000..6ab6fb0
--- /dev/null
+++ b/src/commands/voice/pause.js
@@ -0,0 +1,32 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class PauseVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'pause',
+ group: 'voice',
+ memberName: 'pause',
+ description: 'Pauses audio of previously playing.',
+ guildOnly: true,
+ examples: ['uwu!pause'],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg) {
+ var voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join a channel and try again. ' + emoji.random());
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+
+ msg.say('Song paused :pause_button:');
+
+ msg.guild.musicData.songDispatcher.pause();
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/play.ts b/src/commands/voice/play.ts
new file mode 100644
index 0000000..61cf5d4
--- /dev/null
+++ b/src/commands/voice/play.ts
@@ -0,0 +1,292 @@
+import ytdl from 'ytdl-core';
+import { Command } from 'discord.js-commando';
+import { MessageEmbed, Message } from 'discord.js';
+import Youtube from 'simple-youtube-api';
+//const { youtubeAPI } = require('../../config.json');
+import config from '../../config.json';
+const youtube = new Youtube(config['yt-api-key']);
+import emoji from 'emoji-random';
+
+module.exports = class PlayVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'play',
+ group: 'voice',
+ memberName: 'play',
+ description: 'Play the audio of a YouTube video in a voice channel.',
+ guildOnly: true,
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ args: [
+ {
+ key: 'query',
+ prompt: 'What song would you like to hear?',
+ type: 'string',
+ validate: function (query) {
+ return query.length > 0 && query.length < 200;
+ }
+ }
+ ],
+ examples: [
+ 'uwu!play https://www.youtube.com/watch?v=dQw4w9WgXcQ',
+ 'uwu!play despacito'
+ ]
+ });
+ }
+ async run(msg: Message, { query }) {
+ const voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.say('Please join a channel and try again. ' + emoji.random());
+
+ if (
+ // if the user entered yt playlist url
+ query.match(
+ /^(?!.*\?.*\bv=)https:\/\/www\.youtube\.com\/.*\?.*\blist=.*$/
+ )
+ ) {
+ const playlist = await youtube.getPlaylist(query).catch(function () {
+ return msg.say('Playlist is either private or it does not exist. ' + emoji.random());
+ });
+ // remove the 10 if you removed the queue limit conditions below
+ const videosObj = await playlist.getVideos(10).catch(function () {
+ return msg.say(
+ 'There was a problem getting one or more of the videos in the playlist. ' + emoji.random()
+ );
+ });
+ for (let i = 0; i < videosObj.length; i++) {
+ const video = await videosObj[i].fetch();
+ // this can be uncommented if you choose to limit the queue
+ // if (msg.guild.musicData.queue.length < 10) {
+ //
+ msg.guild.musicData.queue.push(
+ this.constructSongObj(video, voiceChannel)
+ );
+ // } else {
+ // return msg.say(
+ // `I can't play the full playlist because there will be more than 10 songs in queue`
+ // );
+ // }
+ }
+ if (msg.guild.musicData.isPlaying == false) {
+ msg.guild.musicData.isPlaying = true;
+ return this.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ return msg.say(
+ `Playlist - :musical_note: ${playlist.title} :musical_note: has been added to queue. ` + emoji.random()
+ );
+ }
+ }
+
+ // This if statement checks if the user entered a youtube url, it can be any kind of youtube url
+ if (query.match(/^(http(s)?:\/\/)?((w){3}.)?youtu(be|.be)?(\.com)?\/.+/)) {
+ query = query
+ .replace(/(>|<)/gi, '')
+ .split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/);
+ const id = query[2].split(/[^0-9a-z_\-]/i)[0];
+ const video = await youtube.getVideoByID(id).catch(function () {
+ return msg.say(
+ 'There was a problem getting the video you provided. ' + emoji.random()
+ );
+ });
+ // // can be uncommented if you don't want the bot to play live streams
+ // if (video.raw.snippet.liveBroadcastContent === 'live') {
+ // return msg.say("I don't support live streams!");
+ // }
+ // // can be uncommented if you don't want the bot to play videos longer than 1 hour
+ // if (video.duration.hours !== 0) {
+ // return msg.say('I cannot play videos longer than 1 hour');
+ // }
+ // // can be uncommented if you want to limit the queue
+ // if (msg.guild.musicData.queue.length > 10) {
+ // return msg.say(
+ // 'There are too many songs in the queue already, skip or wait a bit'
+ // );
+ // }
+ msg.guild.musicData.queue.push(
+ this.constructSongObj(video, voiceChannel)
+ );
+ if (
+ msg.guild.musicData.isPlaying == false ||
+ typeof msg.guild.musicData.isPlaying == 'undefined'
+ ) {
+ msg.guild.musicData.isPlaying = true;
+ return this.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ return msg.say(`${video.title} added to queue. ` + emoji.random());
+ }
+ }
+
+ // if user provided a song/video name
+ const videos = await youtube.searchVideos(query, 5).catch(function () {
+ return msg.say(
+ 'There was a problem searching the video you requested. ' + emoji.random()
+ );
+ });
+ if (videos.length < 5) {
+ return msg.say(
+ `There was some trouble finding what you were looking for, please try again or be more specific. ` + emoji.random()
+ );
+ }
+ const vidNameArr = [];
+ for (let i = 0; i < videos.length; i++) {
+ vidNameArr.push(`${i + 1}: ${videos[i].title}`);
+ }
+ vidNameArr.push('exit');
+ const embed = new MessageEmbed()
+ .setColor(0xFFCC4D)
+ .setTitle('Please choose a song (1 to 5) ' + emoji.random())
+ .addField(`‎`, '**Song #**' + vidNameArr[0])
+ .addField(`‎`, '**Song #**' + vidNameArr[1])
+ .addField(`‎`, '**Song #**' + vidNameArr[2])
+ .addField(`‎`, '**Song #**' + vidNameArr[3])
+ .addField(`‎`, '**Song #**' + vidNameArr[4])
+ .addField(`‎`, '**Exit selection**: ' + 'exit');
+ var songEmbed = await msg.channel.send({
+ embed
+ });
+ var that = this;
+ msg.channel
+ .awaitMessages(
+ function (msg) {
+ return (msg.content > 0 && msg.content < 6) || msg.content === 'exit';
+ }, {
+ max: 1,
+ time: 60000,
+ errors: ['time']
+ }
+ )
+ .then(function (response) {
+ const videoIndex = parseInt(response.first().content);
+ if (response.first().content === 'exit') return songEmbed.delete();
+ youtube
+ .getVideoByID(videos[videoIndex - 1].id)
+ .then(function (video) {
+ // // can be uncommented if you don't want the bot to play live streams
+ // if (video.raw.snippet.liveBroadcastContent === 'live') {
+ // songEmbed.delete();
+ // return msg.say("I don't support live streams!");
+ // }
+
+ // // can be uncommented if you don't want the bot to play videos longer than 1 hour
+ // if (video.duration.hours !== 0) {
+ // songEmbed.delete();
+ // return msg.say('I cannot play videos longer than 1 hour');
+ // }
+
+ // // can be uncommented if you don't want to limit the queue
+ // if (msg.guild.musicData.queue.length > 10) {
+ // songEmbed.delete();
+ // return msg.say(
+ // 'There are too many songs in the queue already, skip or wait a bit'
+ // );
+ // }
+ msg.guild.musicData.queue.push(
+ that.constructSongObj(video, voiceChannel)
+ );
+ if (msg.guild.musicData.isPlaying == false) {
+ msg.guild.musicData.isPlaying = true;
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ that.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say(`${video.title} added to queue. ` + emoji.random());
+ }
+ })
+ .catch(function () {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say(
+ 'An error has occured when trying to get the video ID from YouTube. ' + emoji.random()
+ );
+ });
+ })
+ .catch(function () {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say(
+ 'Try again and enter a number between 1 and 5 or exit. ' + emoji.random()
+ );
+ });
+ }
+ playSong(queue, msg) {
+ const classThis = this; // use classThis instead of 'this' because of lexical scope below
+ queue[0].voiceChannel
+ .join()
+ .then(function (connection) {
+ const dispatcher = connection
+ .play(
+ ytdl(queue[0].url, {
+ quality: 'highestaudio',
+ highWaterMark: 1024 * 1024 * 10
+ })
+ )
+ .on('start', function () {
+ msg.guild.musicData.songDispatcher = dispatcher;
+ const volume = 100 / 100;
+ msg.guild.musicData.volume = volume;
+ dispatcher.setVolume(msg.guild.musicData.volume);
+ const videoEmbed = new MessageEmbed()
+ .setThumbnail(queue[0].thumbnail)
+ .setColor(0xFFCC4D)
+ .addField('Now playing:', queue[0].title)
+ .addField('Duration:', queue[0].duration);
+ if (queue[1]) videoEmbed.addField('Next song:', queue[1].title);
+ msg.say(videoEmbed);
+ msg.guild.musicData.nowPlaying = queue[0];
+ return queue.shift();
+ })
+ .on('finish', function () {
+ if (queue.length >= 1) {
+ return classThis.playSong(queue, msg);
+ } else {
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ }
+ })
+ .on('error', function (e) {
+ msg.say('Can\'t play song. ' + emoji.random());
+ console.error(e);
+ msg.guild.musicData.queue.length = 0;
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ });
+ })
+ .catch(function (e) {
+ console.error(e);
+ return msg.guild.me.voice.channel.leave();
+ });
+ }
+ constructSongObj(video, voiceChannel) {
+ let duration = this.formatDuration(video.duration);
+ if (duration == '00:00') duration = 'Live Stream';
+ return {
+ url: `https://www.youtube.com/watch?v=${video.raw.id}`,
+ title: video.title,
+ duration,
+ thumbnail: video.thumbnails.high.url,
+ voiceChannel
+ };
+ }
+ // prettier-ignore
+ formatDuration(durationObj) {
+ const duration = `${durationObj.hours ? (durationObj.hours + ':') : ''}${
+ durationObj.minutes ? durationObj.minutes : '00'
+ }:${
+ (durationObj.seconds < 10)
+ ? ('0' + durationObj.seconds)
+ : (durationObj.seconds
+ ? durationObj.seconds
+ : '00')
+ }`;
+ return duration;
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/psycho.ts b/src/commands/voice/psycho.ts
new file mode 100644
index 0000000..827c00a
--- /dev/null
+++ b/src/commands/voice/psycho.ts
@@ -0,0 +1,198 @@
+import ytdl from 'ytdl-core';
+import { Command } from 'discord.js-commando';
+import { MessageEmbed, Message } from 'discord.js';
+import Youtube from 'simple-youtube-api';
+//const { youtubeAPI } = require('../../config.json');
+import config from '../../config.json';
+const youtube = new Youtube(config['yt-api-key']);
+import emoji from 'emoji-random';
+
+module.exports = class PsychoVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'psycho',
+ group: 'voice',
+ memberName: 'psycho',
+ description: 'Plays Psycho by Mase.',
+ guildOnly: true,
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ examples: ['uwu!psycho']
+ });
+ }
+ async run(msg: Message, { query }) {
+ const voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.say('Please join a channel and try again. ' + emoji.random());
+
+ const id = 'fnd_HSmAODs';
+ const video = await youtube.getVideoByID(id).catch(function () {
+ return msg.say(
+ 'There was a problem getting the video you provided. ' + emoji.random()
+ );
+ });
+ // // can be uncommented if you don't want the bot to play live streams
+ // if (video.raw.snippet.liveBroadcastContent === 'live') {
+ // return msg.say("I don't support live streams!");
+ // }
+ // // can be uncommented if you don't want the bot to play videos longer than 1 hour
+ // if (video.duration.hours !== 0) {
+ // return msg.say('I cannot play videos longer than 1 hour');
+ // }
+ // // can be uncommented if you want to limit the queue
+ // if (msg.guild.musicData.queue.length > 10) {
+ // return msg.say(
+ // 'There are too many songs in the queue already, skip or wait a bit'
+ // );
+ // }
+ msg.guild.musicData.queue.push(
+ this.constructSongObj(video, voiceChannel)
+ );
+ if (
+ msg.guild.musicData.isPlaying == false ||
+ typeof msg.guild.musicData.isPlaying == 'undefined'
+ ) {
+ msg.guild.musicData.isPlaying = true;
+ return this.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ return msg.say(`${video.title} added to queue. ` + emoji.random());
+ }
+
+ var that = this;
+ msg.channel
+ .awaitMessages(
+ function (msg) {
+ return (msg.content > 0 && msg.content < 6) || msg.content === 'exit';
+ }, {
+ max: 1,
+ time: 60000,
+ errors: ['time']
+ }
+ )
+ .then(function (response) {
+ const videoIndex = parseInt(response.first().content);
+ if (response.first().content === 'exit') return songEmbed.delete();
+ youtube
+ .getVideoByID(videos[videoIndex - 1].id)
+ .then(function (video) {
+ // // can be uncommented if you don't want the bot to play live streams
+ // if (video.raw.snippet.liveBroadcastContent === 'live') {
+ // songEmbed.delete();
+ // return msg.say("I don't support live streams!");
+ // }
+
+ // // can be uncommented if you don't want the bot to play videos longer than 1 hour
+ // if (video.duration.hours !== 0) {
+ // songEmbed.delete();
+ // return msg.say('I cannot play videos longer than 1 hour');
+ // }
+
+ // // can be uncommented if you don't want to limit the queue
+ // if (msg.guild.musicData.queue.length > 10) {
+ // songEmbed.delete();
+ // return msg.say(
+ // 'There are too many songs in the queue already, skip or wait a bit'
+ // );
+ // }
+ msg.guild.musicData.queue.push(
+ that.constructSongObj(video, voiceChannel)
+ );
+ if (msg.guild.musicData.isPlaying == false) {
+ msg.guild.musicData.isPlaying = true;
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ that.playSong(msg.guild.musicData.queue, msg);
+ } else if (msg.guild.musicData.isPlaying == true) {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say(`${video.title} added to queue. ` + emoji.random());
+ }
+ })
+ .catch(function () {
+ if (songEmbed) {
+ songEmbed.delete();
+ }
+ return msg.say(
+ 'An error has occured when trying to get the video ID from YouTube. ' + emoji.random()
+ );
+ });
+ });
+ }
+ playSong(queue, msg) {
+ const classThis = this; // use classThis instead of 'this' because of lexical scope below
+ queue[0].voiceChannel
+ .join()
+ .then(function (connection) {
+ const dispatcher = connection
+ .play(
+ ytdl(queue[0].url, {
+ quality: 'highestaudio',
+ highWaterMark: 1024 * 1024 * 10
+ })
+ )
+ .on('start', function () {
+ msg.guild.musicData.songDispatcher = dispatcher;
+ const volume = 100 / 100;
+ msg.guild.musicData.volume = volume;
+ dispatcher.setVolume(msg.guild.musicData.volume);
+ const videoEmbed = new MessageEmbed()
+ .setThumbnail(queue[0].thumbnail)
+ .setColor(0xFFCC4D)
+ .addField('Now playing:', queue[0].title)
+ .addField('Duration:', queue[0].duration);
+ if (queue[1]) videoEmbed.addField('Next song:', queue[1].title);
+ msg.say(videoEmbed);
+ msg.guild.musicData.nowPlaying = queue[0];
+ return queue.shift();
+ })
+ .on('finish', function () {
+ if (queue.length >= 1) {
+ return classThis.playSong(queue, msg);
+ } else {
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ }
+ })
+ .on('error', function (e) {
+ msg.say('Can\'t play song ' + emoji.random());
+ console.error(e);
+ msg.guild.musicData.queue.length = 0;
+ msg.guild.musicData.isPlaying = false;
+ msg.guild.musicData.nowPlaying = null;
+ msg.guild.musicData.songDispatcher = null;
+ return msg.guild.me.voice.channel.leave();
+ });
+ })
+ .catch(function (e) {
+ console.error(e);
+ return msg.guild.me.voice.channel.leave();
+ });
+ }
+ constructSongObj(video, voiceChannel) {
+ let duration = this.formatDuration(video.duration);
+ if (duration == '00:00') duration = 'Live Stream';
+ return {
+ url: `https://www.youtube.com/watch?v=${video.raw.id}`,
+ title: video.title,
+ duration,
+ thumbnail: video.thumbnails.high.url,
+ voiceChannel
+ };
+ }
+ // prettier-ignore
+ formatDuration(durationObj) {
+ const duration = `${durationObj.hours ? (durationObj.hours + ':') : ''}${
+ durationObj.minutes ? durationObj.minutes : '00'
+ }:${
+ (durationObj.seconds < 10)
+ ? ('0' + durationObj.seconds)
+ : (durationObj.seconds
+ ? durationObj.seconds
+ : '00')
+ }`;
+ return duration;
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/queue.js b/src/commands/voice/queue.js
new file mode 100644
index 0000000..59fce1a
--- /dev/null
+++ b/src/commands/voice/queue.js
@@ -0,0 +1,51 @@
+const { Command } = require('discord.js-commando');
+const { MessageEmbed } = require('discord.js');
+const emoji = require('emoji-random');
+
+module.exports = class QueueVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'queue',
+ aliases: [
+ 'q',
+ 'song-list',
+ 'next-songs',
+ 'songlist',
+ 'nextsongs',
+ 'nextsong',
+ 'next-song'
+ ],
+ group: 'voice',
+ memberName: 'queue',
+ description: 'Displays the current queue.',
+ guildOnly: true,
+ examples: [
+ 'uwu!queue',
+ 'uwu!q',
+ 'uwu!songlist',
+ 'uwu!song-list',
+ 'uwu!nextsong',
+ 'uwu!next-song',
+ 'uwu!nextsongs',
+ 'uwu!next-songs'
+ ],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg) {
+ if (msg.guild.musicData.queue.length == 0)
+ return msg.say('There aren\'t any songs in the current queue. ' + emoji.random());
+ const titleArray = [];
+ msg.guild.musicData.queue.map(obj => {
+ titleArray.push(obj.title);
+ });
+ let queueEmbed = new MessageEmbed()
+ .setColor(0xFFCC4D)
+ .setTitle('Music Queue ' + emoji.random());
+ for (let i = 0; i < titleArray.length; i++) {
+ queueEmbed.addField(`‎`, `**${i + 1}**: ` + `${titleArray[i]}`);
+ }
+ return msg.say(queueEmbed);
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/remove.js b/src/commands/voice/remove.js
new file mode 100644
index 0000000..34a30de
--- /dev/null
+++ b/src/commands/voice/remove.js
@@ -0,0 +1,41 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class RemoveVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'remove',
+ group: 'voice',
+ memberName: 'remove',
+ description: 'Removes a song from the current queue.',
+ guildOnly: true,
+ args: [
+ {
+ key: 'songNumber',
+ prompt: 'What song would you like to remove from the current queue?',
+ type: 'integer'
+ }
+ ],
+ examples: ['uwu!remove 2'],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg, { songNumber }) {
+ if (songNumber < 1 && songNumber >= msg.guild.musicData.queue.length) {
+ return msg.reply('Please enter a valid song. ' + emoji.random());
+ }
+ var voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join a channel and try again. ' + emoji.random());
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+
+ msg.guild.musicData.queue.splice(songNumber - 1, 1);
+ return msg.say(`Removed song **#${songNumber}** from current queue. ` + emoji.random());
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/resume.js b/src/commands/voice/resume.js
new file mode 100644
index 0000000..1b28b28
--- /dev/null
+++ b/src/commands/voice/resume.js
@@ -0,0 +1,32 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class ResumeVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'resume',
+ group: 'voice',
+ memberName: 'resume',
+ description: 'Resumes audio of previously paused.',
+ guildOnly: true,
+ examples: ['uwu!resume'],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg) {
+ var voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join a channel and try again. ') + emoji.random();
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+
+ msg.say('Song resumed :play_pause:');
+
+ msg.guild.musicData.songDispatcher.resume();
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/shuffle.js b/src/commands/voice/shuffle.js
new file mode 100644
index 0000000..3183f87
--- /dev/null
+++ b/src/commands/voice/shuffle.js
@@ -0,0 +1,53 @@
+const { Command } = require('discord.js-commando');
+const { MessageEmbed } = require('discord.js');
+const emoji = require('emoji-random');
+
+module.exports = class ShuffleVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'shuffle',
+ group: 'voice',
+ memberName: 'shuffle',
+ description: 'Shuffles the current queue.',
+ guildOnly: true,
+ examples: ['uwu!shuffle'],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg) {
+ var voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join channel and try again. ' + emoji.random());
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+
+ if (msg.guild.musicData.queue.length < 1)
+ return msg.say('There aren\'t any songs in the current queue. ' + emoji.random());
+
+ shuffleQueue(msg.guild.musicData.queue);
+
+ const titleArray = [];
+ msg.guild.musicData.queue.map(obj => {
+ titleArray.push(obj.title);
+ });
+ var queueEmbed = new MessageEmbed()
+ .setColor(0xF97DAE)
+ .setTitle('New Music Queue ' + emoji.random());
+ for (let i = 0; i < titleArray.length; i++) {
+ queueEmbed.addField(`${i + 1}:`, `${titleArray[i]}`);
+ }
+ return msg.say(queueEmbed);
+ }
+};
+
+function shuffleQueue(queue) {
+ for (let i = queue.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [queue[i], queue[j]] = [queue[j], queue[i]];
+ }
+} \ No newline at end of file
diff --git a/src/commands/voice/skip.js b/src/commands/voice/skip.js
new file mode 100644
index 0000000..8638291
--- /dev/null
+++ b/src/commands/voice/skip.js
@@ -0,0 +1,29 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class SkipVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'skip',
+ group: 'voice',
+ memberName: 'skip',
+ description: 'Skips one song ahead in the current queue.',
+ guildOnly: true,
+ examples: ['uwu!skip'],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg) {
+ const voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join a channel and try again. ' + emoji.random());
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+ msg.guild.musicData.songDispatcher.end();
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/skipall.js b/src/commands/voice/skipall.js
new file mode 100644
index 0000000..e981f46
--- /dev/null
+++ b/src/commands/voice/skipall.js
@@ -0,0 +1,44 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class SkipAllVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'skipall',
+ aliases: [
+ 'endqueue',
+ 'endq',
+ 'skipqueue',
+ 'skipq'
+ ],
+ group: 'voice',
+ memberName: 'skipall',
+ description: 'Removes all the songs from current queue.',
+ guildOnly: true,
+ examples: [
+ 'uwu!endqueue',
+ 'uwu!endq',
+ 'uwu!skipqueue',
+ 'uwu!skipq'
+ ],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg) {
+ var voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join a channel and try again. ' + emoji.random());
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+ if (!msg.guild.musicData.queue)
+ return msg.say('There aren\'t any songs in the current queue. ' + emoji.random());
+ msg.guild.musicData.songDispatcher.end();
+ msg.guild.musicData.queue.length = 0; // clear queue
+ return;
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/skipto.js b/src/commands/voice/skipto.js
new file mode 100644
index 0000000..f43d56c
--- /dev/null
+++ b/src/commands/voice/skipto.js
@@ -0,0 +1,43 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class SkipToVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'skipto',
+ group: 'voice',
+ memberName: 'skipto',
+ description: 'Skip to a certain song in the current queue.',
+ guildOnly: true,
+ args: [{
+ key: 'songNumber',
+ prompt: 'What song would you like to skip to in the current queue?',
+ type: 'integer'
+ }],
+ examples: ['uwu!skipto 5'],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg, { songNumber }) {
+ if (songNumber < 1 && songNumber >= msg.guild.musicData.queue.length) {
+ return msg.reply('Please enter a valid song. ' + emoji.random());
+ }
+ var voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join channel and try again. ' + emoji.random());
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+
+ if (msg.guild.musicData.queue < 1)
+ return msg.reply('There aren\'t any songs in the current queue. ' + emoji.random());
+
+ msg.guild.musicData.queue.splice(0, songNumber - 1);
+ msg.guild.musicData.songDispatcher.end();
+ return;
+ }
+}; \ No newline at end of file
diff --git a/src/commands/voice/volume.js b/src/commands/voice/volume.js
new file mode 100644
index 0000000..96a6de3
--- /dev/null
+++ b/src/commands/voice/volume.js
@@ -0,0 +1,45 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class VolumeVoice extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'volume',
+ aliases: ['vol'],
+ group: 'voice',
+ memberName: 'volume',
+ description: 'Changes volume of any currentaly playing audio.',
+ guildOnly: true,
+ args: [
+ {
+ key: 'wantedVol',
+ prompt: 'What would volume you like? (1 to 200)',
+ type: 'integer',
+ validate: wantedVol => wantedVol >= 1 && wantedVol <= 200
+ }
+ ],
+ examples: [
+ 'uwu!volume 20',
+ 'uwu!vol 50'
+ ],
+ clientPermissions: ['SPEAK', 'CONNECT', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg, { wantedVol }) {
+ var voiceChannel = msg.member.voice.channel;
+ if (!voiceChannel) return msg.reply('Please join a channel and try again. ' + emoji.random());
+
+ if (
+ typeof msg.guild.musicData.songDispatcher == 'undefined' ||
+ msg.guild.musicData.songDispatcher == null
+ ) {
+ return msg.reply('There isn\'t any audio playing right now. ' + emoji.random());
+ }
+
+ const volume = wantedVol / 100;
+ msg.guild.musicData.volume = volume;
+ msg.guild.musicData.songDispatcher.setVolume(volume);
+ msg.reply(`Volume is now: **${wantedVol}%**. ` + emoji.random());
+ }
+}; \ No newline at end of file