From f1abc3b9b44b60b3f22a016fa34edec68baf1f99 Mon Sep 17 00:00:00 2001 From: Trivernis Date: Wed, 30 Jan 2019 21:00:40 +0100 Subject: [PATCH] Structural changes - removed data.js - added Bot class to bot.js - moved handling guildhandlers to bot class - moved shuffleArray from music to utils - cleanup --- README.md | 2 +- bot.js | 429 ++++++++++++++++++++++++++---------------------- lib/cmd.js | 7 +- lib/data.js | 138 ---------------- lib/guilding.js | 52 +++--- lib/music.js | 45 ++--- lib/utils.js | 27 ++- 7 files changed, 305 insertions(+), 395 deletions(-) delete mode 100644 lib/data.js diff --git a/README.md b/README.md index 8ec6e7b..43cfff4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ discordbot [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blu A bot that does the discord thing. -`node bot.js [--token=] [--ytapi=] [--owner=] [--prefix=] [--game=] [-i=]` +`node bot.node [--token=] [--ytapi=] [--owner=] [--prefix=] [--game=] [-i=]` The arguments are optional because the token and youtube-api-key that the bot needs to run can also be defined in the config.json in the bot's directory: ```json5 diff --git a/bot.js b/bot.js index e5ab685..322510b 100644 --- a/bot.js +++ b/bot.js @@ -5,252 +5,287 @@ const Discord = require("discord.js"), guilding = require('./lib/guilding'), utils = require('./lib/utils'), config = require('./config.json'), - client = new Discord.Client(), args = require('args-parser')(process.argv), sqlite3 = require('sqlite3'), authToken = args.token || config.api.botToken, prefix = args.prefix || config.prefix || '~', gamepresence = args.game || config.presence; -let presences = [], // loaded from presences.txt file if the file exists - rotator = null, // an interval id to stop presence duration if needed - maindb = null; +class Bot { + constructor() { + this.client = new Discord.Client(); + this.mention = false; + this.rotator = null; + this.maindb = null; + this.presences = []; + this.guildHandlers = []; -function main() { - logger.verbose('Registering cleanup function'); - - utils.Cleanup(() => { - guilding.destroyAll(); - client.destroy(); - }); - cmd.setLogger(logger); - logger.verbose('Verifying config'); + logger.verbose('Registering cleanup function'); + utils.Cleanup(() => { + for (let gh in Object.values(this.guildHandlers)) { + if (gh) + gh.destroy(); + } + this.client.destroy().then(() => { + logger.debug('destroyed client'); + }); + }); + cmd.setLogger(logger); + logger.verbose('Verifying config'); - let configVerifyer = new utils.ConfigVerifyer(config, [ - "api.botToken", "api.youTubeApiKey" - ]); - if (!configVerifyer.verifyConfig(logger)) { - if (!args.i) { - logger.info('Invalid config. Exiting'); - process.exit(1); + let configVerifyer = new utils.ConfigVerifyer(config, [ + "api.botToken", "api.youTubeApiKey" + ]); + if (!configVerifyer.verifyConfig(logger)) { + if (!args.i) { + logger.info('Invalid config. Exiting'); + process.exit(1); + } } - } - guilding.setLogger(logger); - cmd.init(prefix); - logger.verbose('Registering commands'); - registerCommands(); - - logger.debug('Checking for ./data/ existence') - utils.dirExistence('./data', () => { - logger.verbose('Connecting to main database'); - maindb = new sqlite3.Database('./data/main.db', (err) => { - if (err) { - logger.error(err.message); - } else { - maindb.run(`${utils.sql.tableExistCreate} presences ( + guilding.setLogger(logger); + cmd.init(prefix); + logger.verbose('Registering commands'); + this.registerCommands(); + logger.debug('Checking for ./data/ existence'); + utils.dirExistence('./data', () => { + logger.verbose('Connecting to main database'); + this.maindb = new sqlite3.Database('./data/main.db', (err) => { + if (err) { + logger.error(err.message); + } else { + this.maindb.run(`${utils.sql.tableExistCreate} presences ( ${utils.sql.pkIdSerial}, text VARCHAR(255) UNIQUE NOT NULL )`, (err) => { - if (err) { - logger.error(err.message); - } else { - logger.debug('Loading presences'); - loadPresences(); - } - }); - } + if (err) { + logger.error(err.message); + } else { + logger.debug('Loading presences'); + this.loadPresences(); + } + }); + } + }); }); - }); - registerCallbacks(); + this.registerCallbacks(); + } - client.login(authToken).then(() => { - logger.debug("Logged in"); - }); -} + start() { + return new Promise((resolve, reject) => { + this.client.login(authToken).then(() => { + logger.debug("Logged in"); + resolve(); + }).catch((err) => { + reject(err); + }); + }) + } -/** - * If a data/presences.txt exists, it is read and each line is put into the presences array. - * Each line is also stored in the main.db database. After the file is completely read, it get's deleted. - * Then the data is read from the database and if the presence doesn't exist in the presences array, it get's - * pushed in there. If the presences.txt file does not exist, the data is just read from the database. In the end - * a rotator is created that rotates the presence every configured duration. - */ -function loadPresences() { - if(fs.existsSync('./data/presences.txt')) { - let lineReader = require('readline').createInterface({ - input: require('fs').createReadStream('./data/presences.txt') - }); - lineReader.on('line', (line) => { - maindb.run('INSERT INTO presences (text) VALUES (?)', [line], (err) => { - if(err) { + /** + * If a data/presences.txt exists, it is read and each line is put into the presences array. + * Each line is also stored in the main.db database. After the file is completely read, it get's deleted. + * Then the data is read from the database and if the presence doesn't exist in the presences array, it get's + * pushed in there. If the presences.txt file does not exist, the data is just read from the database. In the end + * a rotator is created that rotates the presence every configured duration. + */ + loadPresences() { + if (fs.existsSync('./data/presences.txt')) { + let lineReader = require('readline').createInterface({ + input: require('fs').createReadStream('./data/presences.txt') + }); + lineReader.on('line', (line) => { + this.maindb.run('INSERT INTO presences (text) VALUES (?)', [line], (err) => { + if (err) { + logger.warn(err.message); + } + }); + this.presences.push(line); + }); + this.rotator = this.client.setInterval(() => this.rotatePresence(), config.presence_duration || 360000); + fs.unlink('./data/presences.txt', (err) => { + if (err) logger.warn(err.message); - } }); - presences.push(line); - }); - rotator = client.setInterval(() => rotatePresence(), config.presence_duration || 360000); - fs.unlink('./data/presences.txt', (err) => { - if (err) - logger.warn(err.message); - }); - maindb.all('SELECT text FROM presences', (err, rows) => { - if (err) { - logger.warn(err.message); - } else { - for(let row of rows) { - if (!row[0] in presences) - presences.push(row.text); + this.maindb.all('SELECT text FROM presences', (err, rows) => { + if (err) { + logger.warn(err.message); + } else { + for (let row of rows) { + if (!row[0] in this.presences) + this.presences.push(row.text); + } } - } - }) - } else { - maindb.all('SELECT text FROM presences', (err, rows) => { - if (err) { - logger.warn(err.message); - } else { - for(let row of rows) { - presences.push(row.text); + }) + } else { + this.maindb.all('SELECT text FROM presences', (err, rows) => { + if (err) { + logger.warn(err.message); + } else { + for (let row of rows) { + this.presences.push(row.text); + } } - } - rotator = client.setInterval(() => rotatePresence(), config.presence_duration || 360000); - }) + this.rotator = this.client.setInterval(() => this.rotatePresence(), config.presence_duration || 360000); + }) + } } -} -/** - * registeres global commands - */ -function registerCommands() { - // useless test command - cmd.createGlobalCommand(prefix + 'repeatafterme', (msg, argv, args) => { - return args.join(' '); - }, [], "Repeats what you say"); + /** + * registeres global commands + */ + registerCommands() { + // useless test command + cmd.createGlobalCommand(prefix + 'repeatafterme', (msg, argv, args) => { + return args.join(' '); + }, [], "Repeats what you say"); - // adds a presence that will be saved in the presence file and added to the rotation - cmd.createGlobalCommand(prefix + 'addpresence', (msg, argv, args) => { - let p = args.join(' '); - presences.push(p); + // adds a presence that will be saved in the presence file and added to the rotation + cmd.createGlobalCommand(prefix + 'addpresence', (msg, argv, args) => { + let p = args.join(' '); + this.presences.push(p); - maindb.run('INSERT INTO presences (text) VALUES (?)', [p], (err) => { - if (err) - logger.warn(err.message); - }); - return `Added Presence \`${p}\``; - }, [], "Adds a presence to the rotation.", 'owner'); + this.maindb.run('INSERT INTO presences (text) VALUES (?)', [p], (err) => { + if (err) + logger.warn(err.message); + }); + return `Added Presence \`${p}\``; + }, [], "Adds a presence to the rotation.", 'owner'); - // shuts down the bot after destroying the client - cmd.createGlobalCommand(prefix + 'shutdown', (msg) => { + // shuts down the bot after destroying the client + cmd.createGlobalCommand(prefix + 'shutdown', (msg) => { - msg.reply('Shutting down...').finally(() => { - logger.debug('Destroying client...'); + msg.reply('Shutting down...').finally(() => { + logger.debug('Destroying client...'); - client.destroy().finally(() => { - logger.debug(`Exiting Process...`); - process.exit(0); + this.client.destroy().finally(() => { + logger.debug(`Exiting Process...`); + process.exit(0); + }); }); - }); - }, [], "Shuts the bot down.", 'owner'); + }, [], "Shuts the bot down.", 'owner'); - // forces a presence rotation - cmd.createGlobalCommand(prefix + 'rotate', () => { - try { - client.clearInterval(rotator); - rotatePresence(); - rotator = client.setInterval(() => rotatePresence(), config.presence_duration); - } catch (error) { - logger.warn(JSON.stringify(error)); - } - }, [], 'Force presence rotation', 'owner'); + // forces a presence rotation + cmd.createGlobalCommand(prefix + 'rotate', () => { + try { + this.client.clearInterval(this.rotator); + this.rotatePresence(); + this.rotator = this.client.setInterval(() => this.rotatePresence(), config.presence_duration); + } catch (error) { + logger.warn(JSON.stringify(error)); + } + }, [], 'Force presence rotation', 'owner'); - // ping command that returns the ping attribute of the client - cmd.createGlobalCommand(prefix + 'ping', () => { - return `Current average ping: \`${client.ping} ms\``; - }, [], 'Returns the current average ping', 'owner'); + // ping command that returns the ping attribute of the client + cmd.createGlobalCommand(prefix + 'ping', () => { + return `Current average ping: \`${this.client.ping} ms\``; + }, [], 'Returns the current average ping', 'owner'); - // returns the time the bot is running - cmd.createGlobalCommand(prefix + 'uptime', () => { - let uptime = utils.getSplitDuration(client.uptime); - return new Discord.RichEmbed().setDescription(` + // returns the time the bot is running + cmd.createGlobalCommand(prefix + 'uptime', () => { + let uptime = utils.getSplitDuration(this.client.uptime); + return new Discord.RichEmbed().setDescription(` **${uptime.days}** days **${uptime.hours}** hours **${uptime.minutes}** minutes **${uptime.seconds}** seconds **${uptime.milliseconds}** milliseconds `).setTitle('Uptime'); - }, [], 'Returns the uptime of the bot', 'owner'); + }, [], 'Returns the uptime of the bot', 'owner'); - // returns the numbe of guilds, the bot has joined - cmd.createGlobalCommand(prefix + 'guilds', () => { - return `Number of guilds: \`${client.guilds.size}\`` - }, [], 'Returns the number of guilds the bot has joined', 'owner'); -} - -/** - * changes the presence of the bot by using one stored in the presences array - */ -function rotatePresence() { - let pr = presences.shift(); - presences.push(pr); - client.user.setPresence({game: {name: `${gamepresence} | ${pr}`, type: "PLAYING"}, status: 'online'}); - logger.debug(`Presence rotation to ${pr}`); -} + // returns the numbe of guilds, the bot has joined + cmd.createGlobalCommand(prefix + 'guilds', () => { + return `Number of guilds: \`${this.client.guilds.size}\`` + }, [], 'Returns the number of guilds the bot has joined', 'owner'); + } -/** - * Sends the answer recieved from the commands callback. - * Handles the sending differently depending on the type of the callback return - * @param msg - * @param answer - */ -function 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) => answerMessage(msg, answer)) - .catch((error) => answerMessage(msg, error)); - } else { - (this.mention)? msg.reply(answer) : msg.channel.send(answer); - } - } else { - logger.warn(`Empty answer won't be send.`); + /** + * changes the presence of the bot by using one stored in the presences array + */ + rotatePresence() { + let pr = this.presences.shift(); + this.presences.push(pr); + this.client.user.setPresence({game: {name: `${gamepresence} | ${pr}`, type: "PLAYING"}, status: 'online'}); + logger.debug(`Presence rotation to ${pr}`); } -} -/** - * Registeres callbacks for client events - */ -function registerCallbacks() { - client.on('error', (err) => { - logger.error(err.message); - }); - client.on('ready', () => { - logger.info(`logged in as ${client.user.tag}!`); - client.user.setPresence({game: {name: gamepresence, type: "PLAYING"}, status: 'online'}); - }); + /** + * Registeres callbacks for client events + */ + registerCallbacks() { + this.client.on('error', (err) => { + logger.error(err.message); + }); + + this.client.on('ready', () => { + logger.info(`logged in as ${this.client.user.tag}!`); + this.client.user.setPresence({game: {name: gamepresence, type: "PLAYING"}, status: 'online'}) + .catch((err) => { + if (err) + logger.warn(err.message); + }); + }); - client.on('message', msg => { - try { - if (msg.author === client.user) { - logger.verbose(`ME: ${msg.content}`); - return; + this.client.on('message', msg => { + try { + if (msg.author === this.client.user) { + logger.verbose(`ME: ${msg.content}`); + return; + } + logger.verbose(`<${msg.author.tag}>: ${msg.content}`); + if (!msg.guild) { + let reply = cmd.parseMessage(msg); + this.answerMessage(msg, reply); + } else { + this.getGuildHandler(msg.guild, prefix).handleMessage(msg); + } + } catch (err) { + logger.error(err.stack); } - logger.verbose(`<${msg.author.tag}>: ${msg.content}`); - if (!msg.guild) { - let reply = cmd.parseMessage(msg); - answerMessage(msg, reply); + }); + } + + /** + * Sends the answer recieved from the commands callback. + * Handles the sending differently depending on the type of the callback return + * @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) => answerMessage(msg, answer)) + .catch((error) => answerMessage(msg, error)); } else { - guilding.getHandler(msg.guild, prefix).handleMessage(msg); + (this.mention) ? msg.reply(answer) : msg.channel.send(answer); } - } catch (err) { - logger.error(err.stack); + } else { + logger.warn(`Empty answer won't be send.`); } - }); + } + + /** + * Returns the guild handler by id, creates one if it doesn't exist and returns it then + * @param guild + * @param prefix + * @returns {*} + */ + getGuildHandler(guild, prefix) { + if (!this.guildHandlers[guild.id]) + this.guildHandlers[guild.id] = new guilding.GuildHandler(guild, prefix); + return this.guildHandlers[guild.id]; + }; } + // Executing the main function if (typeof require !== 'undefined' && require.main === module) { logger.info("Starting up... "); // log the current date so that the logfile is better to read. - main(); + let discordBot = new Bot(); + discordBot.start().catch((err) => { + logger.error(err.message); + }); } \ No newline at end of file diff --git a/lib/cmd.js b/lib/cmd.js index ea608b1..f9971b9 100644 --- a/lib/cmd.js +++ b/lib/cmd.js @@ -21,7 +21,7 @@ exports.Servant = class { this.createCommand(gcmdTempl.utils.help, (msg, kwargs) => { if (kwargs.command) { let cmd = kwargs.command; - let allCommands ={...globCommands, ...this.commands}; + let allCommands = {...globCommands, ...this.commands}; if (cmd.charAt(0) !== prefix) cmd = this.prefix + cmd; if (allCommands[cmd]) { @@ -58,7 +58,7 @@ exports.Servant = class { for (let cat of categories) { helpEmbed.addField(cat, catCommands[cat]); } - helpEmbed.setFooter( prefix + 'help [command] for more info to each command'); + helpEmbed.setFooter(prefix + 'help [command] for more info to each command'); return helpEmbed; } }); @@ -96,6 +96,7 @@ exports.Servant = class { /** * Removes a command * @param command + * @deprecated Why would you want to remove a command? */ removeCommand(command) { delete this.commands[command]; @@ -201,7 +202,7 @@ exports.init = function (prefix) { description += `\`${key}\` \t`; } }); - helpEmbed.setFooter( prefix + 'help [command] for more info to each command'); + helpEmbed.setFooter(prefix + 'help [command] for more info to each command'); helpEmbed.setDescription(description); return helpEmbed; } diff --git a/lib/data.js b/lib/data.js deleted file mode 100644 index 6069729..0000000 --- a/lib/data.js +++ /dev/null @@ -1,138 +0,0 @@ -/* Module definition */ -const - fs = require('fs'), - path = require('path'); - -/* Variable Definition */ -let logger = require('winston'), - datapath = './data', - entryfile = 'fileentries.json'; - -fs.exists(datapath, (exist) => { - if (!exist) { - fs.mkdir(datapath, (err) => { - if (err) - logger.warn(JSON.stringify(err)); - }) - } -}); - -/* Function Definition */ -/** - * @deprecated - * @type {DataHandler} - */ -exports.DataHandler = class { - constructor(name) { - this.workingDir = path.join(datapath, name); - this.fileEntries = {}; - this.fileData = {}; - fs.exists(this.workingDir, (exists) => { - if (!exists) { - fs.mkdir(this.workingDir, (err) => { - if (err) - logger.error(JSON.stringify(err)); - }); - } - }); - if (fs.existsSync(this.getfp(entryfile))) { - try { - this.fileEntries = this.getJSONSync(entryfile); - } catch (err) { - logger.error(JSON.stringify(err)); - } - } - } - - /** - * adds an entry to the fileEntries. refreshes the entrie file - * @param name - * @param path - */ - addEntry(name, path) { - this.fileEntries.name = path; - this.refreshEntries(); - } - - /** - * shortcut function to join the path with the working directory - * @param file - * @returns {Promise | string} - */ - getfp(file) { - return path.join(this.workingDir, file); - } - - /** - * shortcut function that evokes the callback after reading the file. the files path is the name - * joined with the working directory - * @param file - * @param callback - */ - getcont(file, callback) { - fs.readFile(this.getfp, 'utf-8', callback); - } - - /** - * returns the JSON content of a file in the working directory - * @param file - * @returns {any} - */ - getJSONSync(file) { - return JSON.parse(fs.readFileSync(this.getfp(file), 'utf-8')); - } - - /** - * writes all entris of the fileEntries variable into the fileEntries file. - */ - refreshEntries() { - fs.writeFile(this.getfp(entryfile), JSON.stringify(this.fileEntries), (err) => { - if (err) - logger.warn(JSON.stringify(err)); - }); - } - - /** - * returns the data for the entry - * @param name - * @returns {*} - */ - getData(name) { - try { - if (this.fileData[name]) - return this.fileData[name]; - else if (this.fileEntries[name]) { - this.fileData[name] = this.getJSONSync(this.fileEntries[name]); - return this.fileData[name]; - } - return {}; - } catch (err) { - logger.error(JSON.stringify(err)); - } - } - - /** - * sets the entry to data - * @param name - * @param data - */ - setData(name, data) { - this.fileData[name] = data; - if (!this.fileEntries[name]) { - this.fileEntries[name] = name + '.json'; - } - this.refreshEntries(); - fs.writeFile(this.getfp(this.fileEntries[name]), JSON.stringify(this.fileData[name]), (err) => { - if (err) - logger.warn(JSON.stringify(err)); - }); - } -}; - -/** - * Getting the logger - * @param {Object} newLogger - */ -exports.setLogger = function (newLogger) { - logger = newLogger; -}; \ No newline at end of file diff --git a/lib/guilding.js b/lib/guilding.js index 9ec2d28..7a2f743 100644 --- a/lib/guilding.js +++ b/lib/guilding.js @@ -6,7 +6,7 @@ const cmd = require('./cmd'), sqlite3 = require('sqlite3'), Discord = require('discord.js'), handlers = {}, - dbDir = './data/gdb'; + dataDir = config.dataPath || './data'; let logger = require('winston'); exports.setLogger = function (newLogger) { @@ -29,9 +29,9 @@ exports.GuildHandler = class { this.ready = false; this.msgsQueue = []; // checking if the data direcotry exists and if the gdb directory exists and creates them if they don't - utils.dirExistence('./data', () => { - utils.dirExistence('./data/gdb', () => { - this.db = new sqlite3.Database(`./data/gdb/${guild}.db`, (err) => { + utils.dirExistence(dataDir, () => { + utils.dirExistence(dataDir + '/gdb', () => { + this.db = new sqlite3.Database(`${dataDir}/gdb/${guild}.db`, (err) => { if (err) logger.error(err.message); logger.debug(`Connected to the database for ${guild}`); @@ -48,7 +48,10 @@ exports.GuildHandler = class { }); } - destroy(){ + /** + * Destroys the guild handler + */ + destroy() { this.dj.stop(); this.db.close(); } @@ -82,18 +85,19 @@ exports.GuildHandler = class { answerMessage(msg, answer) { if (answer instanceof Promise || answer) { if (answer instanceof Discord.RichEmbed) { - (this.mention)? msg.reply('', answer) : msg.channel.send('', answer); + (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); + (this.mention) ? msg.reply(answer) : msg.channel.send(answer); } } else { - logger.warn(`Empty answer won't be send.`); + logger.debug(`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. @@ -142,7 +146,6 @@ exports.GuildHandler = class { * @param cmdPrefix */ registerMusicCommands(cmdPrefix) { - let prefix = cmdPrefix || this.prefix; this.dj = new music.DJ(); // play command @@ -186,7 +189,7 @@ exports.GuildHandler = class { }); // playnext command - this.servant.createCommand(servercmd.music.playnext,(msg, kwargs, argv) => { + this.servant.createCommand(servercmd.music.playnext, (msg, kwargs, argv) => { return new Promise((resolve, reject) => { let vc = msg.member.voiceChannel; if (!this.dj.connected) this.dj.voiceChannel = vc; @@ -310,23 +313,20 @@ exports.GuildHandler = class { return new Promise((resolve, reject) => { let saveName = argv.join(' '); this.db.get('SELECT COUNT(*) count FROM playlists WHERE name = ?', [saveName], (err, row) => { - if(err) { + if (err) { logger.error(err.message); + reject(); } + let cb = (err) => { // defining the callback for usage below + if (err) + logger.error(err.message); + else + resolve(`Saved song/playlist as ${saveName}`); + }; 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}`); - }); + this.db.run('INSERT INTO playlists (name, url) VALUES (?, ?)', [saveName, kwargs.url], cb); } 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}`); - }); + this.db.run('UPDATE playlists SET url = ? WHERE name = ?', [kwargs.url, saveName], cb) } }); }); @@ -337,8 +337,10 @@ exports.GuildHandler = class { return new Promise((resolve, reject) => { let response = ''; this.db.all('SELECT name, url FROM playlists', (err, rows) => { - if (err) + if (err) { logger.error(err.message); + reject(); + } for (let row of rows) { response += `[${row.name}](${row.url})\n`; } @@ -360,6 +362,7 @@ exports.GuildHandler = class { * @param guild * @param prefix * @returns {GuildHandler} + * @deprecated use Bot class method instead */ exports.getHandler = function (guild, prefix) { if (!handlers[guild.id]) @@ -369,6 +372,7 @@ exports.getHandler = function (guild, prefix) { /** * Destroy all handlers to safely end all sql3-clients. + * @deprecated automated in Bot class cleanup */ exports.destroyAll = function () { logger.debug('Destroying all handlers...'); diff --git a/lib/music.js b/lib/music.js index 0039739..8ac2403 100644 --- a/lib/music.js +++ b/lib/music.js @@ -1,5 +1,4 @@ -const Discord = require("discord.js"), - ytdl = require("ytdl-core"), +const ytdl = require("ytdl-core"), ypi = require('youtube-playlist-info'), yttl = require('get-youtube-title'), args = require('args-parser')(process.argv), @@ -9,7 +8,6 @@ const Discord = require("discord.js"), /* Variable Definition */ let logger = require('winston'); let djs = {}; -let connections = {}; /* Function Definition */ @@ -288,7 +286,7 @@ exports.DJ = class { * Shuffles the queue */ shuffle() { - this.queue = shuffleArray(this.queue); + this.queue = utils.shuffleArray(this.queue); } /** @@ -310,6 +308,7 @@ exports.setLogger = function (newLogger) { /** * Connects to a voicechannel * @param voiceChannel + * @deprecated */ exports.connect = function (voiceChannel) { let gid = voiceChannel.guild.id; @@ -322,6 +321,7 @@ exports.connect = function (voiceChannel) { * Plays a file * @param filename * @param guildId + * @deprecated */ exports.playFile = function (guildId, filename) { djs[guildId].playFile(filename); @@ -331,6 +331,7 @@ exports.playFile = function (guildId, filename) { * Plays a YT Url * @param voiceChannel * @param url + * @deprecated */ exports.play = function (voiceChannel, url) { let guildId = voiceChannel.guild.id; @@ -347,6 +348,7 @@ exports.play = function (voiceChannel, url) { * plays the given url as next song * @param voiceChannel * @param url + * @deprecated */ exports.playnext = function (voiceChannel, url) { let guildId = voiceChannel.guild.id; @@ -363,6 +365,7 @@ exports.playnext = function (voiceChannel, url) { * Sets the volume of the music * @param percentage * @param guildId + * @deprecated */ exports.setVolume = function (guildId, percentage) { djs[guildId].setVolume(percentage); @@ -370,6 +373,7 @@ exports.setVolume = function (guildId, percentage) { /** * pauses the music + * @deprecated */ exports.pause = function (guildId) { djs[guildId].pause(); @@ -378,6 +382,7 @@ exports.pause = function (guildId) { /** * Resumes the music * @param guildId + * @deprecated */ exports.resume = function (guildId) { djs[guildId].resume(); @@ -386,6 +391,7 @@ exports.resume = function (guildId) { /** * Stops the music * @param guildId + * @deprecated */ exports.stop = function (guildId) { djs[guildId].stop(); @@ -395,6 +401,7 @@ exports.stop = function (guildId) { /** * Skips the song * @param guildId + * @deprecated */ exports.skip = function (guildId) { djs[guildId].skip(); @@ -403,6 +410,7 @@ exports.skip = function (guildId) { /** * Clears the playlist * @param guildId + * @deprecated */ exports.clearQueue = function (guildId) { djs[guildId].clear(); @@ -411,6 +419,7 @@ exports.clearQueue = function (guildId) { /** * Returns the queue * @param guildId + * @deprecated */ exports.getQueue = function (guildId) { return djs[guildId].playlist; @@ -419,6 +428,7 @@ exports.getQueue = function (guildId) { /** * evokes the callback function with the title of the current song * @param guildId + * @deprecated */ exports.nowPlaying = function (guildId) { return djs[guildId].song; @@ -427,31 +437,8 @@ exports.nowPlaying = function (guildId) { /** * shuffles the queue * @param guildId + * @deprecated */ exports.shuffle = function (guildId) { djs[guildId].shuffle(); -}; - -/** - * Shuffles an array with Fisher-Yates Shuffle - * @param array - * @returns {Array} - */ -function shuffleArray(array) { - let currentIndex = array.length, temporaryValue, randomIndex; - - // While there remain elements to shuffle... - while (0 !== currentIndex) { - - // Pick a remaining element... - randomIndex = Math.floor(Math.random() * currentIndex); - currentIndex -= 1; - - // And swap it with the current element. - temporaryValue = array[currentIndex]; - array[currentIndex] = array[randomIndex]; - array[randomIndex] = temporaryValue; - } - - return array; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/lib/utils.js b/lib/utils.js index 6c92e3c..b2c07e9 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -6,9 +6,6 @@ const fs = require('fs'); function noOp() { } -let sysdataPath = './res/data/sys.json'; -let sysData = {}; - /** * returns the extension of a file for the given filename. * @param {String} filename The name of the file. @@ -47,6 +44,30 @@ exports.objectDeepFind = function (object, attributePath) { return current; }; +/** + * Shuffles an array with Fisher-Yates Shuffle + * @param array + * @returns {Array}# + */ +exports.shuffleArray = function(array) { + let currentIndex = array.length, temporaryValue, randomIndex; + + // While there remain elements to shuffle... + while (0 !== currentIndex) { + + // Pick a remaining element... + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex -= 1; + + // And swap it with the current element. + temporaryValue = array[currentIndex]; + array[currentIndex] = array[randomIndex]; + array[randomIndex] = temporaryValue; + } + + return array; +} + /** * lets you define a cleanup for your program exit * @param {Function} callback the cleanup function