diff --git a/CHANGELOG.md b/CHANGELOG.md index c387313..d0a0d49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - bug where the bot counts itself when calculating needed votes to skip/stop music - bug on the `ExtendedRichEmbed` where `addField` and `setDescription` throws an error when the value is null or undefined - bug on `AnilistApiCommands` where the `RichCharacterInfo` uses a nonexistent function of the `ExtendedRichEmbed` +- Typo in changelog ### Changed -- name of MiscCommands module from `TemplateCommandModule` to `MiscoCommandModule` +- name of MiscCommands module from `TemplateCommandModule` to `MiscCommandModule` - moved everything in `lib` to subfolders with the same name as the files and renamed the files to `index.js` +- renamed libfolders to lowercase and removed the lib suffix - moved commands outside of `lib` +### Added +- state lib with `EventRouter` and `EventGroup` and `Event` classes + ## [0.11.0-beta] - 2019-03-03 ### Changed - template Files to name `template.yaml` diff --git a/bot.js b/bot.js index 2c3a2f9..e45269c 100644 --- a/bot.js +++ b/bot.js @@ -1,7 +1,7 @@ const Discord = require("discord.js"), fs = require('fs-extra'), logging = require('./lib/utils/logging'), - msgLib = require('./lib/MessageLib'), + msgLib = require('./lib/message'), guilding = require('./lib/guilding'), utils = require('./lib/utils'), config = require('./config.json'), @@ -128,7 +128,7 @@ class Bot { */ async initializeWebserver() { this.logger.verbose('Importing weblib'); - weblib = require('./lib/WebLib'); + weblib = require('./lib/web'); this.logger.verbose('Creating WebServer'); this.webServer = new weblib.WebServer(config.webinterface.port || 8080); this.logger.debug('Setting Reference Objects to webserver'); diff --git a/commands/.template/index.js b/commands/.template/index.js index caf55f0..966beba 100644 --- a/commands/.template/index.js +++ b/commands/.template/index.js @@ -1,5 +1,5 @@ /* template index.js. Doesn't implement actual commands */ -const cmdLib = require('../../lib/CommandLib'); // required for command objects +const cmdLib = require('../../lib/command'); // required for command objects /** * A description what the command module includes and why. Doesn't need to list commands but explains diff --git a/commands/AnilistApiCommands/index.js b/commands/AnilistApiCommands/index.js index af30baa..9354d4c 100644 --- a/commands/AnilistApiCommands/index.js +++ b/commands/AnilistApiCommands/index.js @@ -1,4 +1,4 @@ -const cmdLib = require('../../lib/CommandLib'), +const cmdLib = require('../../lib/command'), anilistApi = require('../../lib/api/AniListApi'); /** diff --git a/commands/InfoCommands/index.js b/commands/InfoCommands/index.js index ac68869..e81d97a 100644 --- a/commands/InfoCommands/index.js +++ b/commands/InfoCommands/index.js @@ -1,4 +1,4 @@ -const cmdLib = require('../../lib/CommandLib'), +const cmdLib = require('../../lib/command'), fsx = require('fs-extra'), utils = require('../../lib/utils'); diff --git a/commands/MiscCommands/index.js b/commands/MiscCommands/index.js index f9cc408..be12770 100644 --- a/commands/MiscCommands/index.js +++ b/commands/MiscCommands/index.js @@ -1,5 +1,5 @@ /* template index.js. Doesn't implement actual commands */ -const cmdLib = require('../../lib/CommandLib'); +const cmdLib = require('../../lib/command'); /** * Several commands that are that special that they can't be included in any other module. diff --git a/commands/MusicCommands/index.js b/commands/MusicCommands/index.js index 469749d..c805577 100644 --- a/commands/MusicCommands/index.js +++ b/commands/MusicCommands/index.js @@ -1,4 +1,4 @@ -const cmdLib = require('../../lib/CommandLib'), +const cmdLib = require('../../lib/command'), utils = require('../../lib/utils'), config = require('../../config'); @@ -313,5 +313,5 @@ class MusicCommandModule extends cmdLib.CommandModule { } Object.assign(exports, { - 'module': MusicCommandModule + module: MusicCommandModule }); diff --git a/commands/ServerUtilityCommands/index.js b/commands/ServerUtilityCommands/index.js index a560cc3..78b5620 100644 --- a/commands/ServerUtilityCommands/index.js +++ b/commands/ServerUtilityCommands/index.js @@ -1,4 +1,4 @@ -const cmdLib = require('../../lib/CommandLib'); +const cmdLib = require('../../lib/command'); /** * This command module includes utility commands for the server. diff --git a/commands/UtilityCommands/index.js b/commands/UtilityCommands/index.js index be9e9ff..6e624c3 100644 --- a/commands/UtilityCommands/index.js +++ b/commands/UtilityCommands/index.js @@ -1,4 +1,4 @@ -const cmdLib = require('../../lib/CommandLib'); +const cmdLib = require('../../lib/command'); /** * Utility commands are all commands that allow the user to control the behaviour of the diff --git a/lib/StateLib/index.js b/lib/StateLib/index.js deleted file mode 100644 index b16339c..0000000 --- a/lib/StateLib/index.js +++ /dev/null @@ -1,26 +0,0 @@ - -class EventRouter { - - constructor() { - - } - - /** - * Dispatches - * @param event - */ - dispatchEvent(event) { - - } - - /** - * Registeres discord client events to the EventRouter - * @param client - */ - registerClientEvents(client) { - - } - -} - -class EventGroup diff --git a/lib/CommandLib/index.js b/lib/command/index.js similarity index 100% rename from lib/CommandLib/index.js rename to lib/command/index.js diff --git a/lib/guilding.js b/lib/guilding.js index 1e3a399..0199ec4 100644 --- a/lib/guilding.js +++ b/lib/guilding.js @@ -1,4 +1,4 @@ -const music = require('./MusicLib'), +const music = require('./music'), utils = require('./utils'), config = require('../config.json'), sqliteAsync = require('./utils/sqliteAsync'), diff --git a/lib/MessageLib/index.js b/lib/message/index.js similarity index 99% rename from lib/MessageLib/index.js rename to lib/message/index.js index dd477e3..e95bf1f 100644 --- a/lib/MessageLib/index.js +++ b/lib/message/index.js @@ -1,4 +1,4 @@ -const cmdLib = require('../CommandLib'), +const cmdLib = require('../command'), config = require('../../config.json'), Discord = require('discord.js'), logging = require('../utils/logging'), diff --git a/lib/MusicLib/index.js b/lib/music/index.js similarity index 100% rename from lib/MusicLib/index.js rename to lib/music/index.js diff --git a/lib/state/EventGroups.js b/lib/state/EventGroups.js new file mode 100644 index 0000000..ca22fe2 --- /dev/null +++ b/lib/state/EventGroups.js @@ -0,0 +1,163 @@ +let stateLib = require("index.js"); + +class DiscordGuildEvents extends EventGroup { + + constructor(client) { + super(); + this._registerClientEvents(client); + } + + /** + * Registeres the client events to the EventGroup + * @param client {Discord.Client} + * @private + */ + _registerClientEvents(client) { + this.registerEvent(new stateLib.Event('clientUserGuildSettingsUpdate')) + .registerEvent(new stateLib.Event('clientUserSettingsUpdate')) + .registerEvent(new stateLib.Event('emojiCreate')) + .registerEvent(new stateLib.Event('emojiDelete')) + .registerEvent(new stateLib.Event('emojiUpdate')) + .registerEvent(new stateLib.Event('guildBanAdd')) + .registerEvent(new stateLib.Event('guildBanRemove')) + .registerEvent(new stateLib.Event('guildCreate')) + .registerEvent(new stateLib.Event('guildDelete')) + .registerEvent(new stateLib.Event('guildMemberAdd')) + .registerEvent(new stateLib.Event('guildMemberAvailable')) + .registerEvent(new stateLib.Event('guildMemberRemove')) + .registerEvent(new stateLib.Event('guildMemberChunk')) + .registerEvent(new stateLib.Event('guildMemberSpeaking')) + .registerEvent(new stateLib.Event('guildMemberUpdate')) + .registerEvent(new stateLib.Event('guildUnavailable')) + .registerEvent(new stateLib.Event('guildUpdate')) + .registerEvent(new stateLib.Event('presenceUpdate')) + .registerEvent(new stateLib.Event('roleCreate')) + .registerEvent(new stateLib.Event('roleDelete')) + .registerEvent(new stateLib.Event('roleUpdate')) + .registerEvent(new stateLib.Event('userNoteUpdate')) + .registerEvent(new stateLib.Event('userUpdate')) + .registerEvent(new stateLib.Event('voiceStateUpdate')); + + client.on('clientUserGuildSettingsUpdate', (...o) => this.events.clientUserGuildSettingsUpdate.fire(o)); + client.on('clientUserSettingsUpdate', (...o) => this.events.clientUserSettingsUpdate.fire(o)); + client.on('emojiCreate', (...o) => this.events.emojiCreate.fire(o)); + client.on('emojiDelete', (...o) => this.events.emojiDelete.fire(o)); + client.on('emojiUpdate', (...o) => this.events.emojiUpdate.fire(o)); + client.on('guildBanAdd', (...o) => this.events.guildBanAdd.fire(o)); + client.on('guildBanRemove', (...o) => this.events.guildBanRemove.fire(o)); + client.on('guildCreate', (...o) => this.events.guildCreate.fire(o)); + client.on('guildDelete', (...o) => this.events.guildDelete.fire(o)); + client.on('guildMemberAdd', (...o) => this.events.guildMemberAdd.fire(o)); + client.on('guildMemberAvailable', (...o) => this.events.guildMemberAvailable.fire(o)); + client.on('guildMemberRemove', (...o) => this.events.guildMemberRemove.fire(o)); + client.on('guildMemberChunk', (...o) => this.events.guildMemberChunk.fire(o)); + client.on('guildMemberSpeaking', (...o) => this.events.guildMemberSpeaking.fire(o)); + client.on('guildMemberUpdate', (...o) => this.events.guildMemberUpdate.fire(o)); + client.on('guildUnavailable', (...o) => this.events.guildUnavailable.fire(o)); + client.on('guildUpdate', (...o) => this.events.guildUpdate.fire(o)); + client.on('presenceUpdate', (...o) => this.events.presenceUpdate.fire(o)); + client.on('roleCreate', (...o) => this.events.roleCreate.fire(o)); + client.on('roleDelete', (...o) => this.events.roleDelete.fire(o)); + client.on('roleUpdate', (...o) => this.events.roleUpdate.fire(o)); + client.on('userNoteUpdate', (...o) => this.events.userNoteUpdate.fire(o)); + client.on('userUpdate', (...o) => this.events.userUpdate.fire(o)); + client.on('voiceStateUpdate', (...o) => this.events.voiceStateUpdate.fire(o)); + + + } +} + +class DiscordMessageEvents extends stateLib.EventGroup { + + constructor(client) { + super(); + this._registerMessageEvents(client); + } + + /** + * Registeres all client message events + * @param client {Discord.Client} + * @private + */ + _registerMessageEvents(client) { + this.registerEvent(new stateLib.Event('messageDelete')) + .registerEvent(new stateLib.Event('messageDeleteBulk')) + .registerEvent(new stateLib.Event('messageReactionAdd')) + .registerEvent(new stateLib.Event('messageReactionRemove')) + .registerEvent(new stateLib.Event('messageReactionRemoveAll')) + .registerEvent(new stateLib.Event('messageUpdate')) + .registerEvent(new stateLib.Event('message')); + + client.on('messageDelete', (...o) => this.events.messageDelete.fire(o)); + client.on('messageDeleteBulk', (...o) => this.events.messageDeleteBulk.fire(o)); + client.on('messageReactionAdd', (...o) => this.events.messageReactionAdd.fire(o)); + client.on('messageReactionRemove', (...o) => this.events.messageReactionRemove.fire(o)); + client.on('messageReactionRemoveAll', (...o) => this.events.messageReactionRemoveAll.fire(o)); + client.on('messageUpdate', (...o) => this.events.messageUpdate.fire(o)); + client.on('message', (...o) => this.events.message.fire(o)); + } +} + +class DiscordChannelEvents extends stateLib.EventGroup { + + constructor(client) { + super(); + this._registerChannelEvents(client); + } + + /** + * Registers all events for discord channels. + * @param client {Discord.Client} + * @private + */ + _registerChannelEvents(client) { + this.registerEvent(new stateLib.Event('channelCreate')) + .registerEvent(new stateLib.Event('channelDelete')) + .registerEvent(new stateLib.Event('channelPinsUpdate')) + .registerEvent(new stateLib.Event('channelUpdate')) + .registerEvent(new stateLib.Event('typingStart')) + .registerEvent(new stateLib.Event('typingStop')); + + client.on('channelCreate', (...o) => this.events.channelCreate.fire(o)); + client.on('channelDelete', (...o) => this.events.channelDelete.fire(o)); + client.on('channelPinsUpdate', (...o) => this.events.channelPinsUpdate.fire(o)); + client.on('channelUpdate', (...o) => this.events.channelUpdate.fire(o)); + client.on('typingStart', (...o) => this.events.typingStart.fire(o)); + client.on('typingStop', (...o) => this.events.typingStop.fire(o)); + } + +} + +class DiscordClientEvents extends stateLib.EventGroup { + + constructor(client) { + super(); + this._registerClientEvents(client); + } + + /** + * Registers Discord client events + * @param client {Discord.Client} + * @private + */ + _registerClientEvents(client) { + this.registerEvent(new stateLib.Event('debug')) + .registerEvent(new stateLib.Event('warn')) + .registerEvent(new stateLib.Event('error')) + .registerEvent(new stateLib.Event('ready')) + .registerEvent(new stateLib.Event('resume')) + .registerEvent(new stateLib.Event('disconnect')) + .registerEvent(new stateLib.Event('reconnecting')) + .registerEvent(new stateLib.Event('rateLimit')); + + client.on('debug', (...o) => this.events.debug.fire(o)); + client.on('warn', (...o) => this.events.warn.fire(o)); + client.on('error', (...o) => this.events.error.fire(o)); + client.on('ready', (...o) => this.events.ready.fire(o)); + client.on('resume', (...o) => this.events.resume.fire(o)); + client.on('disconnect', (...o) => this.events.disconnect.fire(o)); + client.on('reconnecting', (...o) => this.events.reconnecting.fire(o)); + client.on('rateLimit', (...o) => this.events.rateLimit.fire(o)); + client.on('presenceUpdate', (...o) => this.events.presenceUpdate.fire(o)); + } +} diff --git a/lib/state/index.js b/lib/state/index.js new file mode 100644 index 0000000..3226cc3 --- /dev/null +++ b/lib/state/index.js @@ -0,0 +1,99 @@ +const logging = require('../utils/logging'); + +class EventRouter { + + constructor() { + this._logger = new logging.Logger(this); + this.eventGroups = {}; + } + + /** + * Fires an event of an event group with event data. + * @param eventGroup {String} + * @param eventName {String} + * @param eventData {Object} + */ + fireEvent(eventGroup, eventName, eventData) { + if (this.eventGroups[eventGroup] instanceof EventGroup) + this.eventGroups[eventGroup].fireEvent(eventName, eventData); + return this; + } + + /** + * Adds an EventRoute to the EventRouter + * @param group {EventGroup} + */ + registerEventGroup(group) { + this.eventGroups[group.name] = name; + } + +} + +class EventGroup { + + /** + * Creates a new EventGroup with the given name. + * @param [name] {String} + */ + constructor(name) { + this._logger = new logging.Logger(this); + this.name = name || this.constructor.name; + this.events = {}; + } + + fireEvent(eventName, eventData) { + if (this.events[eventName] instanceof Event) + this.events[eventName].fire(eventData); + return this; + } + + /** + * Registeres an Event to the EventGroup + * @param event {Event} + */ + registerEvent(event) { + this.events[event.name] = event; + } +} + +class Event { + + /** + * Creates a new Event with the given name. + * @param name + */ + constructor(name) { + this._logger = new logging.Logger(this); + this.name = name; + this.handlers = []; + } + + /** + * Adds an event handler to the Event + * @param handler {Function} + */ + addHandler(handler) { + this.handlers.push(handler); + return this; + } + + /** + * Fires the event with the given data. + * @param data {Object} + */ + fire(data) { + for (let handler in this.handlers) + try { + handler(data); + } catch (err) { + this._logger.verbose(err.message); + this._logger.silly(err.stack); + } + } +} + +Object.assign(exports, { + EventRouter: EventRouter, + EventGroup: EventGroup, + Event: Event +}); diff --git a/lib/utils/index.js b/lib/utils/index.js index 620689c..a2354c3 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -47,7 +47,7 @@ function objectDeepFind (object, attributePath) { /** * Shuffles an array with Fisher-Yates Shuffle * @param array - * @returns {Array}# + * @returns {Array} */ exports.shuffleArray = function(array) { let currentIndex = array.length, temporaryValue, randomIndex; diff --git a/lib/WebLib/index.js b/lib/web/index.js similarity index 100% rename from lib/WebLib/index.js rename to lib/web/index.js diff --git a/test/test.js b/test/test.js index 2ac6160..032c1b9 100644 --- a/test/test.js +++ b/test/test.js @@ -179,7 +179,7 @@ describe('lib/utils', function() { describe('lib/music', function() { - const music = rewire('../lib/MusicLib'); + const music = rewire('../lib/music'); const Readable = require('stream').Readable; music.__set__("logger", mockobjects.mockLogger); @@ -329,8 +329,8 @@ describe('lib/music', function() { }); }); -describe('lib/CommandLib', function() { - let cmdLib = require('../lib/CommandLib'); +describe('lib/command', function() { + let cmdLib = require('../lib/command'); describe('Answer', function() { @@ -373,8 +373,8 @@ describe('lib/CommandLib', function() { }); }); -describe('lib/MessageLib', function() { - let msgLib = require('../lib/MessageLib'); +describe('lib/message', function() { + let msgLib = require('../lib/message'); describe('MessageHandler', function() { it ('parses a command syntax', function() {