diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..9188ea1 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,57 @@ +# Javascript Node CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-javascript/ for more details +# +version: 2 +jobs: + build: + docker: + # specify the version you desire here + - image: circleci/node:10.11 + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + # - image: circleci/mongo:3.4.4 + + working_directory: ~/repo + + steps: + - checkout + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: + name: Installing dependencies + command: npm install + + - run: + name: installing additional dependencies + command: npm install sqlite3 + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + - run: + name: Creating config file + command: echo {} >> config.json + + # run tests! + - run: + name: Testing ./lib/music + command: node ./testscripts/musicTest.js + + - run: + name: Testing ./lib/cmd + command: node ./testscripts/cmdTest.js + + - run: + name: Testing ./lib/guilding + command: node ./testscripts/guildingTest.js \ No newline at end of file diff --git a/README.md b/README.md index a28a6e9..d1ae1bc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -discordbot +discordbot [![CircleCI](https://circleci.com/gh/Trivernis/discordbot.js.svg?style=svg)](https://circleci.com/gh/Trivernis/discordbot.js) [![CodeFactor](https://www.codefactor.io/repository/github/trivernis/discordbot.js/badge)](https://www.codefactor.io/repository/github/trivernis/discordbot.js) === A bot that does the discord thing. diff --git a/bot.js b/bot.js index b8e4547..e55a4f9 100644 --- a/bot.js +++ b/bot.js @@ -96,7 +96,7 @@ function registerCommands() { // returns the numbe of guilds, the bot has joined cmd.createGlobalCommand(prefix + 'guilds', () => { return `Number of guilds: \`${client.guilds.size}\`` - }, [], 'Returns the uptime of the bot', 'owner'); + }, [], 'Returns the number of guilds the bot has joined', 'owner'); } function rotatePresence() { @@ -120,7 +120,13 @@ client.on('message', msg => { logger.verbose(`<${msg.author.tag}>: ${msg.content}`); if (!msg.guild) { let reply = cmd.parseMessage(msg); - if (reply) msg.channel.send(reply); + if (reply) { + if (reply.isPrototypeOf(Discord.RichEmbed)) { + msg.channel.send('', reply); + } else { + msg.channel.send(reply) + } + } } else { guilding.getHandler(msg.guild, prefix).handleMessage(msg); } diff --git a/commands/globalcommands.json b/commands/globalcommands.json index 967c044..e544b7d 100644 --- a/commands/globalcommands.json +++ b/commands/globalcommands.json @@ -3,7 +3,11 @@ "help": { "name": "help", "permission": "all", - "description": "Shows this help command" + "description": "Shows this help command", + "category": "Utility", + "args": [ + "command" + ] } } } \ No newline at end of file diff --git a/commands/servercommands.json b/commands/servercommands.json index 7fe40c0..b150023 100644 --- a/commands/servercommands.json +++ b/commands/servercommands.json @@ -3,7 +3,8 @@ "roles": { "name": "roles", "permission": "all", - "description": "Shows the roles used for commands on the server." + "description": "Shows the roles used for commands on the server.", + "category": "Utility" } }, "music": { @@ -14,11 +15,13 @@ "url" ], "description": "Adds the url to the YouTube video/playlist into the queue.", + "category": "Music", "response": { "success": "Added Song/Playlist to the queue.", "failure": "Failed adding Song/Playlist to the queue.", "url_invalid": "This is not a valid url!", - "no_url": "I need an url to a video to play" + "no_url": "I need an url to a video to play!", + "no_voicechannel": "You need to join a voicechannel to do that!" } }, "playnext": { @@ -28,6 +31,7 @@ "url" ], "description": "Adds the url to the YouTube video as next song to the queue.", + "category": "Music", "response": { "success": "Added Song as next Song to the queue.", "failure": "Failed adding Song as next Song to the queue.", @@ -39,6 +43,7 @@ "name": "join", "permission": "all", "description": "Joins the VC you are in.", + "category": "Music", "response": { "not_connected": "You are not connected to a Voice Channel." } @@ -47,6 +52,7 @@ "name": "stop", "permission": "dj", "description": "Stops playing music and leaves.", + "category": "Music", "response": { "success": "Stopping now..." } @@ -55,6 +61,7 @@ "name": "pause", "permission": "all", "description": "Pauses playing.", + "category": "Music", "response": { "success": "Pausing playback." } @@ -63,6 +70,7 @@ "name": "resume", "permission": "all", "description": "Resumes playing.", + "category": "Music", "response": { "success": "Resuming playback." } @@ -71,6 +79,7 @@ "name": "skip", "permission": "dj", "description": "Skips the current song.", + "category": "Music", "response": { "success": "Skipping to the next song." } @@ -79,6 +88,7 @@ "name": "clear", "permission": "dj", "description": "Clears the queue.", + "category": "Music", "response": { "success": "The Queue has been cleared." } @@ -86,17 +96,20 @@ "playlist": { "name": "queue", "permission": "all", - "description": "Shows the next ten songs." + "description": "Shows the next ten songs.", + "category": "Music" }, "current": { "name": "np", "permission": "all", - "description": "Shows the currently playing song." + "description": "Shows the currently playing song.", + "category": "Music" }, "shuffle": { "name": "shuffle", "permission": "all", "description": "Shuffles the playlist.", + "category": "Music", "response": { "success": "The Queue has been shuffled." } @@ -105,6 +118,7 @@ "name": "repeat", "permission": "all", "description": "Toggle listening on repeat.", + "category": "Music", "response": { "repeat_true": "Listening on repeat now!", "repeat_false": "Not listening on repeat anymore." @@ -116,12 +130,14 @@ "args": [ "url" ], - "description": "Saves the YouTube song/playlist with a specific name" + "description": "Saves the YouTube song/playlist with a specific name", + "category": "Music" }, "saved": { "name": "saved", "permission": "all", "description": "Prints out all saved playlists.", + "category": "Music", "response": { "no_saved": "There are no saved songs/playlists :(" } diff --git a/lib/cmd.js b/lib/cmd.js index 844d57a..1c4cbb3 100644 --- a/lib/cmd.js +++ b/lib/cmd.js @@ -7,7 +7,8 @@ let logger = require('winston'), config = require('../config.json'), args = require('args-parser')(process.argv), gcmdTempl = require('../commands/globalcommands'), - scmdTempl = require('../commands/servercommands'); + scmdTempl = require('../commands/servercommands'), + Discord = require('discord.js'); /* Function Definition */ @@ -19,29 +20,49 @@ exports.Servant = class { this.commands = {}; this.prefix = prefix; // show all commands (except the owner commands if the user is not an owner) - this.createCommand(gcmdTempl.utils.help, (msg) => { - let helpstr = "```markdown\n"; - helpstr += "Commands\n===\n"; - helpstr += 'Global Commands\n---\n'; - Object.entries(globCommands).sort().forEach(([key, value]) => { - if (value.role !== 'owner' || checkPermission(msg, 'owner')) { - let cmdhelp = `${key} [${value.args.join('] [')}]`.replace('[]', '').padEnd(25, ' '); - cmdhelp += value.description || ''; - cmdhelp += `\nPermission: ${value.role||'all'}`; - helpstr += `\n${cmdhelp}\n`; + this.createCommand(gcmdTempl.utils.help, (msg, kwargs) => { + if (kwargs.command) { + let cmd = kwargs.command; + let allCommands ={...globCommands, ...this.commands}; + if (cmd.charAt(0) !== prefix) + cmd = this.prefix + cmd; + if (allCommands[cmd]) { + return new Discord.RichEmbed() + .setTitle(`Help for ${cmd}`) + .addField('Usage', `\`${cmd} [${allCommands[cmd].args.join('] [')}]\``.replace('[]', '')) + .addField('Description', allCommands[cmd].description) + .addField('Permission Role', allCommands[cmd].role || 'all'); + } else { + return 'Command not found :('; } - }); - helpstr += '\nServer Commands\n---\n'; - Object.entries(this.commands).sort().forEach(([key, value]) => { - if (value.role !== 'owner' || checkPermission(msg, 'owner')) { - let cmdhelp = `${key} [${value.args.join('] [')}]`.replace('[]', '').padEnd(25, ' '); - cmdhelp += value.description || ''; - cmdhelp += `\nPermission: ${value.role||'all'}`; - helpstr += `\n${cmdhelp}\n`; + } else { + let helpEmbed = new Discord.RichEmbed() + .setTitle('Commands'); + let globHelp = ''; + Object.entries(globCommands).sort().forEach(([key, value]) => { + if (value.role !== 'owner' || checkPermission(msg, 'owner')) { + globHelp += `\`${key}\` \t`; + } + }); + helpEmbed.addField('Global Commands', globHelp); + let categories = []; + let catCommands = {}; + Object.entries(this.commands).sort().forEach(([key, value]) => { + if (value.role !== 'owner' || checkPermission(msg, 'owner')) { + if (!categories.includes(value.category)) { + categories.push(value.category); + catCommands[value.category] = `\`${key}\` \t` + } else { + catCommands[value.category] += `\`${key}\` \t` + } + } + }); + for (let cat of categories) { + helpEmbed.addField(cat, catCommands[cat]); } - }); - helpstr += "```"; - return helpstr; + helpEmbed.setFooter( prefix + 'help [command] for more info to each command'); + return helpEmbed; + } }); // show all roles that are used by commands @@ -68,7 +89,8 @@ exports.Servant = class { 'args': template.args || [], 'description': template.description, 'callback': call, - 'role': template.permission + 'role': template.permission, + 'category': template.category || 'Other' }; logger.debug(`Created server command: ${this.prefix + template.name}, args: ${template.args}`); } @@ -104,7 +126,10 @@ exports.Servant = class { let argv = argvars.slice(nLength); logger.debug(`Executing callback for command: ${command}, kwargs: ${kwargs}, argv: ${argv}`); try { - return cmd.callback(msg, kwargs, argv) || globResult; + let locResult = cmd.callback(msg, kwargs, argv); + if (locResult instanceof Promise) + return locResult; // because Promise equals false in conditional + return locResult || globResult; } catch (err) { logger.error(err.message); return `The command \`${command}\` has thrown an error.`; @@ -154,20 +179,35 @@ exports.parseMessage = function (msg) { */ exports.init = function (prefix) { logger.verbose("Created help command"); - this.createGlobalCommand(((prefix || config.prefix) + 'help'), (msg) => { - let helpstr = "```markdown\n"; - helpstr += "Commands\n---\n"; - Object.entries(globCommands).sort().forEach(([key, value]) => { - if (value.role !== 'owner' || checkPermission(msg, 'owner')) { - let cmdhelp = `${key} [${value.args.join('] [')}]`.replace('[]', '').padEnd(25, ' '); - cmdhelp += value.description || ''; - cmdhelp += `\nPermission: ${value.role||'all'}`; - helpstr += `\n${cmdhelp}\n`; + this.createGlobalCommand(((prefix || config.prefix) + 'help'), (msg, kwargs) => { + if (kwargs.command) { + let cmd = kwargs.command; + if (cmd.charAt(0) !== prefix) + cmd = prefix + cmd; + if (globCommands[cmd]) { + return new Discord.RichEmbed() + .setTitle(`Help for ${cmd}`) + .addField('Usage', `\`${cmd} [${globCommands[cmd].args.join('] [')}]\``.replace('[]', '')) + .addField('Description', globCommands[cmd].description) + .addField('Permission Role', globCommands[cmd].role || 'all'); } - }); - helpstr += "```"; - return helpstr; - }, [], "Shows this help."); + } else { + let helpEmbed = new Discord.RichEmbed() + .setTitle('Global Commands') + .setTimestamp(); + let description = ''; + Object.entries(globCommands).sort().forEach(([key, value]) => { + if (value.role === 'owner' && checkPermission(msg, 'owner')) { + description += `\`${key}\` \t`; + } else if (value.role !== 'owner') { + description += `\`${key}\` \t`; + } + }); + helpEmbed.setFooter( prefix + 'help [command] for more info to each command'); + helpEmbed.setDescription(description); + return helpEmbed; + } + }, ['command'], "Shows this help."); }; /** diff --git a/lib/guilding.js b/lib/guilding.js index 19d6f33..a08265c 100644 --- a/lib/guilding.js +++ b/lib/guilding.js @@ -4,6 +4,7 @@ const cmd = require('./cmd'), config = require('../config.json'), servercmd = require('../commands/servercommands'), sqlite3 = require('sqlite3'), + Discord = require('discord.js'), handlers = {}, dbDir = './data/gdb'; let logger = require('winston'); @@ -74,6 +75,26 @@ exports.GuildHandler = class { )`); } + /** + * Answers a message via mention if mentioning is active or with just sending it to the same channel. + * @param msg + * @param answer + */ + answerMessage(msg, answer) { + if (answer instanceof Promise || answer) { + if (answer instanceof Discord.RichEmbed) { + (this.mention)? msg.reply('', answer) : msg.channel.send('', answer); + } else if (answer instanceof Promise) { + answer + .then((answer) => this.answerMessage(msg, answer)) + .catch((error) => this.answerMessage(msg, error)); + } else { + (this.mention)? msg.reply(answer) : msg.channel.send(answer); + } + } else { + logger.warning(`Empty answer won't be send.`); + } + } /** * handles the message by letting the servant parse the command. Depending on the message setting it * replies or just sends the answer. @@ -91,13 +112,7 @@ exports.GuildHandler = class { } ); } - let answer = this.servant.parseCommand(msg); - if (!answer) return; - if (this.mention) { - msg.reply(answer); - } else { - msg.channel.send(answer); - } + this.answerMessage(msg, this.servant.parseCommand(msg)); } else { this.msgsQueue.push(msg); } @@ -107,15 +122,20 @@ exports.GuildHandler = class { * Connect to a voice-channel if not connected and play the url * @param vc * @param url + * @param next */ - connectAndPlay(vc, url) { - if (!this.dj.connected) { - this.dj.connect(vc).then(() => { - this.dj.playYouTube(url); - }); - } else { - this.dj.playYouTube(url); - } + connectAndPlay(vc, url, next) { + return new Promise((resolve, reject) => { + if (!this.dj.connected) { + this.dj.connect(vc).then(() => { + this.dj.playYouTube(url, next); + resolve(); + }); + } else { + this.dj.playYouTube(url, next); + resolve(); + } + }); } /** @@ -128,74 +148,86 @@ exports.GuildHandler = class { // play command this.servant.createCommand(servercmd.music.play, (msg, kwargs, argv) => { - let vc = msg.member.voiceChannel; - let url = kwargs['url']; - if (!vc) - return 'You are not connected to a VoiceChannel'; - if (!url) - return servercmd.music.play.response.no_url; - if (!url.match(/http/g)) { - if (argv) - url += ' ' + argv.join(' '); - this.db.get('SELECT url FROM playlists WHERE name = ?', [url], (err, row) => { - if (err) { - console.error(err.message); - } - if (!row) { - return servercmd.music.play.response.url_invalid; - } - url = row.url; + return new Promise((resolve, reject) => { + let vc = this.dj.voiceChannel || msg.member.voiceChannel; + let url = kwargs['url']; + if (!vc) + reject(servercmd.music.play.response.no_voicechannel); + if (!url) + reject(servercmd.music.play.response.no_url); + if (!url.match(/http/g)) { + if (argv && argv.length > 0) + url += ' ' + argv.join(' '); // join to get the whole expression behind the command + this.db.get('SELECT url FROM playlists WHERE name = ?', [url], (err, row) => { + if (err) { + console.error(err.message); + } + if (!row) { + reject(servercmd.music.play.response.url_invalid); + logger.verbose('Got invalid url for play command.'); + } else { + url = row.url; + try { + this.connectAndPlay(vc, url).then(() => { + resolve(servercmd.music.play.response.success); + }); + } catch (err) { + logger.error(err.message); + reject(servercmd.music.play.response.failure); + } + } + }); + } else { try { - this.connectAndPlay(vc, url); + this.connectAndPlay(vc, url).then(() => { + resolve(servercmd.music.play.response.success); + }); } catch (err) { logger.error(err.message); - return servercmd.music.play.response.failure; + reject(servercmd.music.play.response.failure); } - }); - } else { - try { - this.connectAndPlay(vc, url); - } catch (err) { - logger.error(err.message); - return servercmd.music.play.response.failure; } - } - return servercmd.music.play.response.success; + }) }); // playnext command this.servant.createCommand(servercmd.music.playnext,(msg, kwargs, argv) => { - let vc = msg.member.voiceChannel; - if (!this.dj.connected) this.dj.voiceChannel = vc; - let url = kwargs['url']; - if (!url) return servercmd.music.playnext.response.no_url; - if (!url.match(/http/g)) { - if (argv) - url += ' ' + argv.join(' '); - this.db.get('SELECT url FROM playlists WHERE name = ?', [url], (err, row) => { - if (err) { - console.error(err.message); - } - if (!row) { - return servercmd.music.play.response.url_invalid; - } - url = row.url; + return new Promise((resolve, reject) => { + let vc = msg.member.voiceChannel; + if (!this.dj.connected) this.dj.voiceChannel = vc; + let url = kwargs['url']; + if (!url) reject(servercmd.music.playnext.response.no_url); + if (!url.match(/http/g)) { + if (argv) + url += ' ' + argv.join(' '); + this.db.get('SELECT url FROM playlists WHERE name = ?', [url], (err, row) => { + if (err) { + console.error(err.message); + } + if (!row) { + reject(servercmd.music.play.response.url_invalid); + } + url = row.url; + try { + this.connectAndPlay(url, true).then(() => { + resolve(servercmd.music.playnext.response.success); + }); + } catch (err) { + logger.error(err.message); + reject(servercmd.music.play.response.failure); + } + }); + } else { try { - this.dj.playYouTube(url, true); + this.connectAndPlay(url, true).then(() => { + resolve(servercmd.music.playnext.response.success); + }); } catch (err) { - logger.error(err.message); - return servercmd.music.play.response.failure; + logger.error(err); + reject(servercmd.music.playnext.response.failure); } - }); - } else { - try { - this.dj.playYouTube(url, true); - } catch (err) { - logger.error(err); - return servercmd.music.playnext.response.failure; } - } - return servercmd.music.playnext.response.success; + }) }); // join command @@ -274,44 +306,50 @@ exports.GuildHandler = class { // saves playlists this.servant.createCommand(servercmd.music.save, (msg, kwargs, argv) => { - let saveName = argv.join(' '); - this.db.get('SELECT COUNT(*) count FROM playlists WHERE name = ?', [saveName], (err, row) => { - if(err) { - logger.error(err.message); - } - if (!row || row.count === 0) { - this.db.run('INSERT INTO playlists (name, url) VALUES (?, ?)', [saveName, kwargs.url], (err) => { - if (err) - logger.error(err.message); - }); - } else { - this.db.run('UPDATE playlists SET url = ? WHERE name = ?', [kwargs.url, saveName], (err) => { - if (err) - logger.error(err.message); - }); - } + return new Promise((resolve, reject) => { + let saveName = argv.join(' '); + this.db.get('SELECT COUNT(*) count FROM playlists WHERE name = ?', [saveName], (err, row) => { + if(err) { + logger.error(err.message); + } + if (!row || row.count === 0) { + this.db.run('INSERT INTO playlists (name, url) VALUES (?, ?)', [saveName, kwargs.url], (err) => { + if (err) + logger.error(err.message); + else + resolve(`Saved song/playlist as ${saveName}`); + }); + } else { + this.db.run('UPDATE playlists SET url = ? WHERE name = ?', [kwargs.url, saveName], (err) => { + if (err) + logger.error(err.message); + else + resolve(`Saved song/playlist as ${saveName}`); + }); + } + }); }); - return `Saved song/playlist as ${saveName}` }); // saved command - prints out saved playlists this.servant.createCommand(servercmd.music.saved, (msg) => { - let response = ''; - this.db.all('SELECT name, url FROM playlists', (err, rows) => { - if (err) - logger.error(err.message); - for (let row of rows) { - response += `[${row.name}](${row.url})\n`; - } - if (rows.length === 0) { - msg.channel.send(servercmd.music.saved.response.no_saved); - } else { - msg.channel.send('', {embed: { - "title": "Saved Songs and Playlists", - "description": response, - "fields": [] - }}); - } + return new Promise((resolve, reject) => { + let response = ''; + this.db.all('SELECT name, url FROM playlists', (err, rows) => { + if (err) + logger.error(err.message); + for (let row of rows) { + response += `[${row.name}](${row.url})\n`; + } + if (rows.length === 0) { + msg.channel.send(servercmd.music.saved.response.no_saved); + } else { + let richEmbed = new Discord.RichEmbed() + .setTitle('Saved Songs and Playlists') + .setDescription(response); + resolve(richEmbed); + } + }); }); }); } diff --git a/lib/music.js b/lib/music.js index 05984dc..e00e2bd 100644 --- a/lib/music.js +++ b/lib/music.js @@ -31,16 +31,19 @@ exports.DJ = class { * VoiceChannel is saved as object variable. */ connect(voiceChannel) { - this.voiceChannel = voiceChannel || this.voiceChannel; - if (this.connected) { - this.stop(); - } - logger.verbose(`Connecting to voiceChannel ${this.voiceChannel.name}`); - return this.voiceChannel.join().then(connection => { - logger.info(`Connected to Voicechannel ${this.voiceChannel.name}`); - this.conn = connection; - this.checkListeners(); - }); + return new Promise((resolve, reject) => { + this.voiceChannel = voiceChannel || this.voiceChannel; + if (this.connected) { + this.stop(); + } + logger.verbose(`Connecting to voiceChannel ${this.voiceChannel.name}`); + this.voiceChannel.join().then(connection => { + logger.info(`Connected to Voicechannel ${this.voiceChannel.name}`); + this.conn = connection; + this.checkListeners(); + resolve(); + }).catch((error) => reject(error)); + }) } /** @@ -97,10 +100,14 @@ exports.DJ = class { * @param playnext */ playYouTube(url, playnext) { + /** Commented because it causes an connection overflow error. + * TODO: Decide to either fix this with promises or ignore it because connection checks are performed by the guild handler.**/ + /* if (!this.connected) { this.connect().then(this.playYouTube(url)); } - let plist = url.match(/(?<=\?list=)[\w\-]+/g); + */ + let plist = url.match(/(?<=\?list=)[\w\-]+/); if (plist) { logger.debug(`Adding playlist ${plist} to queue`); ypi(ytapiKey, plist).then(items => { diff --git a/package.json b/package.json index 3b16f26..f6b6d9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,9 @@ { "name": "discordbot", "version": "1.0.0", + "scripts": { + "start": "node bot.js" + }, "dependencies": { "args-parser": "1.1.0", "discord.js": "11.4.2", diff --git a/testscripts/cmdTest.js b/testscripts/cmdTest.js new file mode 100644 index 0000000..eae8b1a --- /dev/null +++ b/testscripts/cmdTest.js @@ -0,0 +1,39 @@ +const cmd = require("../lib/cmd.js"), + mockobjects = require("./mockobjects.js"), + servercmd = require('../commands/servercommands'); + +function main() { + cmd.setLogger(mockobjects.mockLogger); + console.log('Creating new servant instance'); + let servant = new cmd.Servant('#'); + console.log('registering all music commands...'); + + for (let [key, value] of Object.entries(servercmd.music)) { + servant.createCommand(value, () => { + console.log(` - invoked ${value.name} callback`); + }); + } + + console.log('parsing and deleting all music commands...'); + for (let [key, value] of Object.entries(servercmd.music)) { + servant.parseCommand({ + content: '#' + value.name, + author: { + tag: undefined + } + }); + servant.removeCommand(value.name); + } + + process.exit(0); +} + +if (typeof require !== "undefined" && require.main === module) { + process.on("unhandledRejection", (reason, p) => { + console.error("Unhandled Rejection at: Promise", p, "reason:", reason); + throw Error("Promise rejection"); + }); + + setTimeout(() => process.exit(1), 60000); + main(); +} \ No newline at end of file diff --git a/testscripts/guildingTest.js b/testscripts/guildingTest.js new file mode 100644 index 0000000..fcad9c1 --- /dev/null +++ b/testscripts/guildingTest.js @@ -0,0 +1,44 @@ +const guilding = require("../lib/guilding.js") + music = require("../lib/music.js"), + mockobjects = require("./mockobjects.js"), + servercmd = require("../commands/servercommands"); + +function main() { + guilding.setLogger(mockobjects.mockLogger); + music.setLogger(mockobjects.mockLogger); + console.log('Creating guildHandler instance'); + let guildHandler = new guilding.GuildHandler('TEST', '#'); + guildHandler.dj = new music.DJ(mockobjects.mockVoicechannel); + + setTimeout(() => { + for (let [key, value] of Object.entries(servercmd.music)) { + guildHandler.handleMessage({ + content: '#' + value.name + ' arg1 arg2 arg3 arg4', + author: { + tag: undefined, + id: 0, + createdTimestamp: new Date(), + username: 'TEST' + }, + member: { + voiceChannel: mockobjects.mockVoicechannel + }, + channel: mockobjects.mockChannel, + reply: mockobjects.mockChannel.send + }); + } + + guildHandler.destroy(); + process.exit(0); + }, 1000); +} + +if (typeof require !== "undefined" && require.main === module) { + process.on("unhandledRejection", (reason, p) => { + console.error("Unhandled Rejection at: Promise", p, "reason:", reason); + throw Error("Promise rejection"); + }); + + setTimeout(() => process.exit(1), 60000); + main(); +} \ No newline at end of file diff --git a/testscripts/mockobjects.js b/testscripts/mockobjects.js new file mode 100644 index 0000000..86e7ed0 --- /dev/null +++ b/testscripts/mockobjects.js @@ -0,0 +1,51 @@ +exports.mockLogger = { + error: msg => raise(msg), + warn: msg => console.error("warn: ", msg), + warning: msg => console.error("warn: ", msg), + info: msg => console.log("info: ", msg), + verbose: msg => console.log("verbose: ", msg), + debug: msg => console.log("debug: ", msg) +}; + +exports.mockDispatcher = { + pause: () => console.log('Dispatcher.pause();'), + resume: () => console.log('Dispatcher.resume();'), + setVolume: (perc) => console.log(`Dispatcher.setVolume(${perc});`), + on: (event, callback) => console.log(`Dispatcher.on(${event}, ${callback});`), + end: () => console.log('Dispatcher.end();') +}; + +exports.mockConnection = { + channel: { + members: { + size: 10 + }, + leave: () => console.log('Connection.leave();') + }, + status: 0, + playFile: (fname) => { + console.log(`Connection.playFile(${fname});`); + return exports.mockDispatcher; + }, + playStream: (stream, opts) => { + console.log(`Connection.playStream(ytdl, ${opts};`); + return exports.mockDispatcher; + }, + disconnect: () => console.log('Connection.disconnect();') +}; + +exports.mockVoicechannel = { + name: 'mockVoicechannel', + join: () => { + console.log('Voicechannel.join();'); + return new Promise((rs, rj) => rs(exports.mockConnection)); + }, + members: { + size: 10 + }, + leave: () => console.log('Voicechannel.leave();') +}; + +exports.mockChannel = { + send: (msg) => console.log('Send: ', msg) +} \ No newline at end of file diff --git a/testscripts/musicTest.js b/testscripts/musicTest.js new file mode 100644 index 0000000..1c90aab --- /dev/null +++ b/testscripts/musicTest.js @@ -0,0 +1,33 @@ +const music = require('../lib/music.js'), + mockobjects = require('./mockobjects.js'); + +function main() { + let dj = new music.DJ(mockobjects.mockVoicechannel) + music.setLogger(mockobjects.mockLogger); + dj.connect().then(() => { + console.log('connected', dj.connected); + dj.playFile('test'); + dj.playYouTube('https://www.youtube.com/watch?v=TEST'); + dj.setVolume(1); + dj.pause(); + dj.resume(); + dj.skip(); + dj.stop(); + dj.shuffle(); + console.log('dj.playlist: ', dj.playlist); + console.log('dj.song: ', dj.song); + dj.clear(); + process.exit(0); + }); +} + +// Executing the main function +if (typeof require !== 'undefined' && require.main === module) { + process.on('unhandledRejection', (reason, p) => { + console.error('Unhandled Rejection at: Promise', p, 'reason:', reason); + throw Error('Promise rejection'); + }); + + setTimeout(() => process.exit(1), 60000); + main(); +} \ No newline at end of file