summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.js7
-rw-r--r--src/bot.ts71
-rw-r--r--src/commands/fun/8ball.js38
-rw-r--r--src/commands/fun/emoji.js24
-rw-r--r--src/commands/fun/gay.js34
-rw-r--r--src/commands/fun/quote.js40
-rw-r--r--src/commands/fun/respect.js23
-rw-r--r--src/commands/fun/say.js31
-rw-r--r--src/commands/fun/uwufy.ts31
-rw-r--r--src/commands/utility/btc.ts36
-rw-r--r--src/commands/utility/btcchange.js47
-rw-r--r--src/commands/utility/clear.js72
-rw-r--r--src/commands/utility/membercount.js29
-rw-r--r--src/commands/utility/server.js54
-rw-r--r--src/commands/utility/servers.ts28
-rw-r--r--src/commands/utility/uptime.ts40
-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
-rw-r--r--src/config.json4
34 files changed, 2180 insertions, 0 deletions
diff --git a/src/app.js b/src/app.js
new file mode 100644
index 0000000..fca1bad
--- /dev/null
+++ b/src/app.js
@@ -0,0 +1,7 @@
+const { ShardingManager } = require('discord.js');
+const config = require('./config.json');
+const manager = new ShardingManager('./dist/bot.js', { token: config['secret'] });
+//const manager = new ShardingManager('./bot.js', { token: config['secret'] });
+
+manager.spawn();
+manager.on('shardCreate', shard => console.log(`Launched shard: ${shard.id}`));
diff --git a/src/bot.ts b/src/bot.ts
new file mode 100644
index 0000000..cf90dfc
--- /dev/null
+++ b/src/bot.ts
@@ -0,0 +1,71 @@
+import config from './config.json';
+import { CommandoClient } from 'discord.js-commando';
+import path from 'path';
+import { Structures } from 'discord.js';
+import emoji from 'emoji-random';
+Structures.extend('Guild', Guild => {
+ class MusicGuild extends Guild {
+ musicData: { queue: never[]; isPlaying: boolean; volume: number; songDispatcher: null; };
+ constructor(client, data) {
+ super(client, data);
+ this.musicData = {
+ queue: [],
+ isPlaying: false,
+ volume: 1,
+ songDispatcher: null
+ };
+ }
+ }
+ return MusicGuild;
+});
+
+const client = new CommandoClient({
+ commandPrefix: 'uwu!',
+ owner: '217348698294714370'
+});
+
+client.registry
+ .registerDefaultTypes()
+ .registerGroups([
+ ['fun', 'Fun Command Group'],
+ ['moderation', 'Moderation Command Group'],
+ ['utility', 'Utility Command Group'],
+ ['voice', 'Voice Command Group']
+ ])
+ .registerDefaultGroups()
+ .registerDefaultCommands({
+ help: true
+ })
+ .registerCommandsIn(path.join(__dirname, 'commands'));
+
+client.once('ready', () => {
+ console.log(`Started bot: ${client.user.tag} (ID: ${client.user.id})\nCurrently running on ${client.guilds.cache.size} server(s).`);
+ client.user.setActivity('uwu!help | v5.0.0', {
+ type: 'WATCHING'
+ });
+});
+
+client.on('error', console.error);
+//client.on('debug', console.debug);
+
+client.on('message', async msg => {
+ var msgContent = msg.content.toLowerCase();
+ function prefixCheck() {
+ if (msgContent.startsWith('uwu!')) {
+ return true;
+ }
+ }
+ if (prefixCheck()) {
+ if (msg.channel.type == 'dm') {
+ console.log(msg.author.tag, 'says', msgContent, 'in a DM');
+ } else {
+ console.log(msg.member.user.tag, 'says', msgContent, 'in #' + msg.channel.name);
+ }
+ }
+
+ if (msg.mentions.everyone) {
+ msg.react(emoji.random());
+ }
+});
+
+client.login(config['secret']); \ No newline at end of file
diff --git a/src/commands/fun/8ball.js b/src/commands/fun/8ball.js
new file mode 100644
index 0000000..6be4f01
--- /dev/null
+++ b/src/commands/fun/8ball.js
@@ -0,0 +1,38 @@
+const { Command } = require('discord.js-commando');
+const { MessageEmbed } = require('discord.js');
+
+module.exports = class EightBallFun extends Command {
+ constructor(client) {
+ super(client, {
+ name: '8ball',
+ aliases: [
+ '8b',
+ '9b',
+ '9ball',
+ '7b',
+ '7ball'
+ ],
+ group: 'fun',
+ memberName: '8ball',
+ description: 'Shake the 8ball for a fortune.',
+ throttling: {
+ usages: 5,
+ duration: 30
+ },
+ examples: ['uwu!8ball', 'uwu!8b'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg) {
+ var r = ['Yes~ uwu', 'No.', 'Yes!', 'No!', 'What, no.', 'Yes.', 'Maybe.', 'Perhaps.', 'Try again.', 'I\'m not sure.'];
+ var s = r[Math.floor(Math.random() * r.length)];
+
+ let embed = new MessageEmbed()
+
+ .setAuthor('The 8-ball says', 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/8-Ball_Pool.svg/500px-8-Ball_Pool.svg.png')
+ .setDescription('`' + s + '`');
+
+ msg.channel.send(embed);
+ }
+}; \ No newline at end of file
diff --git a/src/commands/fun/emoji.js b/src/commands/fun/emoji.js
new file mode 100644
index 0000000..ca633b9
--- /dev/null
+++ b/src/commands/fun/emoji.js
@@ -0,0 +1,24 @@
+const emoji = require('emoji-random');
+const { Command } = require('discord.js-commando');
+
+module.exports = class EmojiFun extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'emoji',
+ aliases: ['moji'],
+ group: 'fun',
+ memberName: 'emoji',
+ description: 'Gives you a random emoji.' + emoji.random(),
+ throttling: {
+ usages: 5,
+ duration: 30
+ },
+ examples: ['uwu!emoji', 'uwu!moji'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg) {
+ msg.reply(emoji.random());
+ }
+}; \ No newline at end of file
diff --git a/src/commands/fun/gay.js b/src/commands/fun/gay.js
new file mode 100644
index 0000000..ec78ee3
--- /dev/null
+++ b/src/commands/fun/gay.js
@@ -0,0 +1,34 @@
+const { Command } = require('discord.js-commando');
+
+module.exports = class GayFun extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'gay',
+ aliases: [
+ 'gayamount',
+ 'gayrange',
+ 'gayrate'
+ ],
+ group: 'fun',
+ memberName: 'gay',
+ description: 'Tells you your gay-ness amount.',
+ examples: [
+ 'uwu!gay',
+ 'uwu!gayamount',
+ 'uwu!gayrange',
+ 'uwu!gayrate'
+ ],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg) {
+ var gayAmount = Math.floor((Math.random() * 100) + 1);
+ var gayAmountDecimal = Math.floor((Math.random() * 100) + 1);
+
+ msg.reply('Scanning..').then(scanningMsg => {
+ scanningMsg.delete()
+ msg.reply('Your gay-ness amount is **' + gayAmount + '.' + gayAmountDecimal + '%**. 🏳️‍🌈');
+ });
+ }
+}; \ No newline at end of file
diff --git a/src/commands/fun/quote.js b/src/commands/fun/quote.js
new file mode 100644
index 0000000..4a19a31
--- /dev/null
+++ b/src/commands/fun/quote.js
@@ -0,0 +1,40 @@
+const atquotes = require('at-quotes');
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class QuoteFun extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'quote',
+ aliases: ['quotes'],
+ group: 'fun',
+ memberName: 'quote',
+ description: 'Gives you a random quote from Adventure Time.',
+ throttling: {
+ usages: 5,
+ duration: 30
+ },
+ examples: ['s5n!quote', 's5n!quote finn'],
+ args: [
+ {
+ key: 'atCharacter',
+ prompt: 'Would you like a specific character? (Finn, Jake, Ice King, No)',
+ type: 'string'
+ }
+ ],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg, { atCharacter }) {
+ if (!atCharacter || atCharacter == 'no' || atCharacter == 'n') {
+ msg.reply(atquotes.getQuote() + ' ' + emoji.random());
+ } else if (atCharacter == 'finn' || atCharacter == 'f') {
+ msg.reply(atquotes.getFinnQuote() + ' ' + emoji.random());
+ } else if (atCharacter == 'jake' || atCharacter == 'j') {
+ msg.reply(atquotes.getJakeQuote() + ' ' + emoji.random());
+ } else if (atCharacter == 'ice king' || atCharacter == 'ik') {
+ msg.reply(atquotes.getIceKingQuote() + ' ' + emoji.random());
+ }
+ }
+}; \ No newline at end of file
diff --git a/src/commands/fun/respect.js b/src/commands/fun/respect.js
new file mode 100644
index 0000000..50d185b
--- /dev/null
+++ b/src/commands/fun/respect.js
@@ -0,0 +1,23 @@
+const { Command } = require('discord.js-commando');
+
+module.exports = class RespectFun extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'respect',
+ aliases: ['f'],
+ group: 'fun',
+ memberName: 'respect',
+ description: 'Press F to pay respects.',
+ examples: ['uwu!respect', 'uwu!f'],
+ guildOnly: true,
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg) {
+ msg.channel.send('Press F to pay respects.').then(m => {
+ m.react('🇫');
+ msg.delete();
+ });
+ }
+}; \ No newline at end of file
diff --git a/src/commands/fun/say.js b/src/commands/fun/say.js
new file mode 100644
index 0000000..667bb49
--- /dev/null
+++ b/src/commands/fun/say.js
@@ -0,0 +1,31 @@
+const { Command } = require('discord.js-commando');
+
+module.exports = class SayFun extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'say',
+ group: 'fun',
+ memberName: 'say',
+ description: 'Allows you to speak as the bot.',
+ guildOnly: true,
+ args: [
+ {
+ key: 'say',
+ prompt: 'What would you like to send?',
+ type: 'string'
+ }
+ ],
+ examples: ['uwu!say hi'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg, { say }) {
+ if (msg.member.hasPermission('KICK_MEMBERS')) {
+ msg.channel.send(say);
+ msg.delete();
+ } else {
+ msg.reply('Insufficent perms. ' + emoji.random());
+ }
+ }
+}; \ No newline at end of file
diff --git a/src/commands/fun/uwufy.ts b/src/commands/fun/uwufy.ts
new file mode 100644
index 0000000..9e40078
--- /dev/null
+++ b/src/commands/fun/uwufy.ts
@@ -0,0 +1,31 @@
+import { Message } from "discord.js";
+import { Command } from 'discord.js-commando';
+
+module.exports = class UwufyFun extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'uwufy',
+ aliases: ['uwu', 'owofy', 'owo'],
+ group: 'fun',
+ memberName: 'uwufy',
+ description: 'Uwufys anything you send.',
+ args: [
+ {
+ key: 'userMsg',
+ prompt: 'What would you like to uwufy?',
+ type: 'string'
+ }
+ ],
+ examples: ['uwu!say please uwufy this'],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ });
+ }
+ run(msg: Message, { userMsg }) {
+ var m = userMsg;
+ var u1 = m.replace('r', 'w');
+ var u2 = u1.replace('l', 'w');
+ msg.reply(u2);
+ msg.delete();
+ }
+}; \ No newline at end of file
diff --git a/src/commands/utility/btc.ts b/src/commands/utility/btc.ts
new file mode 100644
index 0000000..2845194
--- /dev/null
+++ b/src/commands/utility/btc.ts
@@ -0,0 +1,36 @@
+import { Command } from 'discord.js-commando';
+import emoji from 'emoji-random';
+import btc from 'btc-value';
+btc.setApiKey('a43419ce-fc59-4951-8af9-20c5e36ef73f');
+
+module.exports = class BTCUtility extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'btc',
+ aliases: ['bitcoin', 'crypto'],
+ group: 'utility',
+ memberName: 'btc',
+ description: 'Allows you to check current Bitcoin price.',
+ args: [
+ {
+ key: 'currencyName',
+ prompt: 'What currency could you like to see it in? (USD, AUD, CAD)',
+ type: 'string'
+ }
+ ],
+ examples: [
+ 'uwu!bitcoin aud',
+ 'uwu!crypto cad',
+ 'uwu!btc usd'
+ ],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg: Message, { currencyName }) {
+ currencyName = currencyName.toUpperCase();
+ btc({ isDecimal: true, currencyCode: currencyName }).then(value => {
+ msg.reply('The current price of *Bitcoin* in **' + currencyName + '** is **' + value + '**. ' + emoji.random());
+ });
+ }
+}; \ No newline at end of file
diff --git a/src/commands/utility/btcchange.js b/src/commands/utility/btcchange.js
new file mode 100644
index 0000000..474a3ee
--- /dev/null
+++ b/src/commands/utility/btcchange.js
@@ -0,0 +1,47 @@
+const { Command } = require('discord.js-commando');
+const btc = require('btc-value');
+btc.setApiKey('a43419ce-fc59-4951-8af9-20c5e36ef73f');
+
+module.exports = class BTCChangeUtility extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'btcchange',
+ aliases: ['bitcoinchange', 'cryptochange', 'btcc'],
+ group: 'utility',
+ memberName: 'btcchange',
+ description: 'Allows you to check the fluctuation in Bitcoin prices within a specified amount of time.',
+ args: [
+ {
+ key: 'timeAmount',
+ prompt: 'What time range do you want to check the fluction amount in? (day, hour, week)',
+ type: 'string'
+ }
+ ],
+ examples: [
+ 'uwu!btcchange day',
+ 'uwu!bitcoinchange hour',
+ 'uwu!cryptochange week',
+ 'uwu!btcc day'
+ ],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg, { timeAmount }) {
+ if (timeAmount == 'day') {
+ btc.getPercentageChangeLastDay().then(percentage => {
+ msg.reply('The fluction amount of *Bitcoin* in the last **' + timeAmount + '** is **' + percentage + '%**. ' + emoji.random());
+ });
+ } else if (timeAmount == 'hour') {
+ btc.getPercentageChangeLastHour().then(percentage => {
+ msg.reply('The fluction amount of *Bitcoin* in the last **' + timeAmount + '** is **' + percentage + '%**. ' + emoji.random());
+ });
+ } else if (timeAmount == 'week') {
+ btc.getPercentageChangeLastWeek().then(percentage => {
+ msg.reply('The fluction amount of *Bitcoin* in the last **' + timeAmount + '** is **' + percentage + '%**. ' + emoji.random());
+ });
+ } else {
+ msg.reply('*' + timeAmount + '* is not a valid range. ' + emoji.random());
+ }
+ }
+}; \ No newline at end of file
diff --git a/src/commands/utility/clear.js b/src/commands/utility/clear.js
new file mode 100644
index 0000000..6871cca
--- /dev/null
+++ b/src/commands/utility/clear.js
@@ -0,0 +1,72 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class ClearUtility extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'clear',
+ aliases: ['delete', 'del', 'c', 'd'],
+ group: 'utility',
+ memberName: 'clear',
+ description: 'Clears a specified amount of messages.',
+ guildOnly: true,
+ args: [
+ {
+ key: 'deleteAmount',
+ prompt: 'How many messages would you like to delete?',
+ type: 'integer'
+ }
+ ],
+ examples: [
+ 'uwu!clear 23',
+ 'uwu!delete 75',
+ 'uwu!del 32',
+ 'uwu!c 45',
+ 'uwu!d 84'
+ ],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY', 'MANAGE_MESSAGES'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY', 'MANAGE_MESSAGES']
+ });
+ }
+ async run(msg, { deleteAmount }) {
+ if (msg.member.hasPermission('MANAGE_MESSAGES')) {
+ if (!deleteAmount) {
+ msg.reply('You haven\'t specified an amount of messages which should be deleted. ' + emoji.random()).then(deleteNotificationMessage => {
+ deleteNotificationMessage.delete({ timeout: 1000 });
+ });
+ } else if (isNaN(deleteAmount)) {
+ msg.reply('The amount parameter isn\'t a number. ' + emoji.random()).then(deleteNotificationMessage => {
+ deleteNotificationMessage.delete({ timeout: 1000 });
+ });
+ } else if (deleteAmount > 100) {
+ msg.reply('You can\'t delete more than 100 messages at once. ' + emoji.random()).then(deleteNotificationMessage => {
+ deleteNotificationMessage.delete({ timeout: 1000 });
+ });
+ } else if (deleteAmount < 1) {
+ msg.reply('You have to delete at least 1 message. ' + emoji.random()).then(deleteNotificationMessage => {
+ deleteNotificationMessage.delete({ timeout: 1000 });
+ });
+ }
+ /*else if (msg.createdTimestamp > 1209600) {
+ msg.reply('due to discord rules, bots can only bulk delete messages that are under 14 days old :(')
+ } */
+ else {
+ var clearAmount = deleteAmount + 1;
+ // It took me so long to figure out why this was not really working. It would delete but an insane amount at a time.
+ // I realized that because it was getting parsed as a string, it would just add 1 to it so if I tried to delete 1
+ // message, it would delete 11 lol. Fixed by parsing as integer THEN adding one. 02:30 2020/04/03/2020
+
+ await msg.channel.messages.fetch({
+ limit: clearAmount
+ }).then(messages => { // I am on v11 discord.js
+ msg.channel.bulkDelete(messages);
+ });
+ msg.reply('It\'s been deleted ~uwu ' + emoji.random()).then(deleteNotificationMessage => {
+ deleteNotificationMessage.delete({ timeout: 1000 });
+ });
+ }
+ } else {
+ msg.reply('Insufficent perms. ' + emoji.random());
+ }
+ }
+}; \ No newline at end of file
diff --git a/src/commands/utility/membercount.js b/src/commands/utility/membercount.js
new file mode 100644
index 0000000..1178236
--- /dev/null
+++ b/src/commands/utility/membercount.js
@@ -0,0 +1,29 @@
+const { Command } = require('discord.js-commando');
+const emoji = require('emoji-random');
+
+module.exports = class MemberCountUtility extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'membercount',
+ aliases: ['memberc', 'mcount', 'mc'],
+ group: 'utility',
+ memberName: 'membercount',
+ description: 'Tells you how many members are in the current server.',
+ throttling: {
+ usages: 5,
+ duration: 30
+ },
+ examples: [
+ 'uwu!membercount',
+ 'uwu!memberc',
+ 'uwu!mcount',
+ 'uwu!mc'
+ ],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg) {
+ msg.reply(`There are **${msg.guild.memberCount}** members in **${msg.guild.name}**. ` + emoji.random());
+ }
+}; \ No newline at end of file
diff --git a/src/commands/utility/server.js b/src/commands/utility/server.js
new file mode 100644
index 0000000..58555fa
--- /dev/null
+++ b/src/commands/utility/server.js
@@ -0,0 +1,54 @@
+const { Command } = require('discord.js-commando');
+const { MessageEmbed } = require('discord.js');
+
+module.exports = class ServerUtility extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'server',
+ aliases: [
+ 'serverinfo',
+ 'si',
+ 'server-info',
+ 'serverstats',
+ 'server-stats'
+ ],
+ group: 'utility',
+ memberName: 'server',
+ description: 'Gives you information about the current server.',
+ throttling: {
+ usages: 2,
+ duration: 60
+ },
+ guildOnly: true,
+ examples: [
+ 'uwu!server',
+ 'uwu!serverinfo',
+ 'uwu!server-info',
+ 'uwu!serverstats',
+ 'uwu!server-stats',
+ 'uwu!si'
+ ],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg) {
+ var o = msg.guild.members.cache.filter(m => m.presence.status === 'online').size;
+
+ let embed = new MessageEmbed()
+
+ .setAuthor(`${msg.guild.name} - ${msg.guild.id}`, `${msg.guild.iconURL()}`, `https://discordapp.com/channels/${msg.guild.id}/${msg.guild.id}`)
+ .setDescription(`Here\'s all the information on \`${msg.guild.name}\``)
+ .setThumbnail(`${msg.guild.iconURL()}`)
+ .addField('Owner', `${msg.guild.owner}`, false)
+ .addField(`Members [${msg.guild.memberCount}]`, `${o} members are online.`, true)
+ .addField('Region', `${msg.guild.region}`, true)
+ .addField('Text channels', `${msg.guild.channels.filter(c => c.type === 'text').size}`, true)
+ .addField('Voice channels', `${msg.guild.channels.filter(c => c.type === 'voice').size}`, true)
+ .addField('Guild created', `${msg.guild.createdAt}`, false)
+ .addField(`${this.client.user.username} joined`, `${msg.guild.members.get('699473263998271489').joinedAt}`)
+ .setColor(0xFFCC4D);
+
+ msg.channel.send(embed);
+ }
+}; \ No newline at end of file
diff --git a/src/commands/utility/servers.ts b/src/commands/utility/servers.ts
new file mode 100644
index 0000000..1b3ce0f
--- /dev/null
+++ b/src/commands/utility/servers.ts
@@ -0,0 +1,28 @@
+import { Command } from 'discord.js-commando';
+import { MessageEmbed, Message } from 'discord.js';
+import emoji from 'emoji-random';
+
+module.exports = class ServersUtility extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'servers',
+ aliases: ['servercount', 'scount', 'serverc'],
+ group: 'utility',
+ memberName: 'servers',
+ description: 'Tells you the amount of servers uwufy is in.',
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg: Message) {
+ msg.channel.send('Please wait..').then(m => {
+ m.edit(`** **`);
+
+ let emb = new MessageEmbed()
+ .setDescription(`Currently running on 31${this.client.guilds.cache.size} server(s). ` + emoji.random())
+ .setColor(0xFFCC4D)
+
+ msg.channel.send(emb);
+ });
+ }
+}; \ No newline at end of file
diff --git a/src/commands/utility/uptime.ts b/src/commands/utility/uptime.ts
new file mode 100644
index 0000000..eebd031
--- /dev/null
+++ b/src/commands/utility/uptime.ts
@@ -0,0 +1,40 @@
+import { Command } from 'discord.js-commando';
+import { duration as _duration } from 'moment';
+import 'moment-duration-format';
+// @ts-ignore
+import emoji from 'emoji-random';
+import { MessageEmbed, Message } from 'discord.js';
+
+export default class UptimeUtility extends Command {
+ constructor(client) {
+ super(client, {
+ name: 'uptime',
+ aliases: ['ut'],
+ group: 'utility',
+ memberName: 'uptime',
+ description: 'Tells you how long the bot has been online.',
+ throttling: {
+ usages: 5,
+ duration: 30
+ },
+ examples: [
+ 'uwu!uptime',
+ 'uwu!ut'
+ ],
+ userPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY'],
+ clientPermissions: ['SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
+ });
+ }
+ run(msg: Message) {
+ const duration = _duration(this.client.uptime).format(" D [days], H [hrs], m [mins], s [secs]");
+ msg.channel.send('Please wait..').then(m => {
+ m.edit(`** **`);
+
+ let emb = new MessageEmbed()
+ .setDescription('uwufier has been up for ' + duration + '. ' + emoji.random())
+ .setColor(0xFFCC4D)
+
+ msg.channel.send(emb);
+ });
+ }
+} \ No newline at end of file
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
diff --git a/src/config.json b/src/config.json
new file mode 100644
index 0000000..16bac59
--- /dev/null
+++ b/src/config.json
@@ -0,0 +1,4 @@
+{
+ "secret":"Njk5NDczMjYzOTk4MjcxNDg5.XpU5oQ.btZuxVudhNllSQY6CxrXXtMJm9A",
+ "yt-api-key":"AIzaSyCeG1lQAeInv4vjFv_eTL9IFAFNdQC9Nk8"
+} \ No newline at end of file