Added lib/state

- added with `Event`, `EventGroup` and `EventRouter` for optimized event handling
- added special subclasses of EventGroup for Client Events
feature/api-rewrite
Trivernis 5 years ago
parent 08d220b4c1
commit 016a3d042d

@ -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`

@ -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');

@ -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

@ -1,4 +1,4 @@
const cmdLib = require('../../lib/CommandLib'),
const cmdLib = require('../../lib/command'),
anilistApi = require('../../lib/api/AniListApi');
/**

@ -1,4 +1,4 @@
const cmdLib = require('../../lib/CommandLib'),
const cmdLib = require('../../lib/command'),
fsx = require('fs-extra'),
utils = require('../../lib/utils');

@ -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.

@ -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
});

@ -1,4 +1,4 @@
const cmdLib = require('../../lib/CommandLib');
const cmdLib = require('../../lib/command');
/**
* This command module includes utility commands for the server.

@ -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

@ -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

@ -1,4 +1,4 @@
const music = require('./MusicLib'),
const music = require('./music'),
utils = require('./utils'),
config = require('../config.json'),
sqliteAsync = require('./utils/sqliteAsync'),

@ -1,4 +1,4 @@
const cmdLib = require('../CommandLib'),
const cmdLib = require('../command'),
config = require('../../config.json'),
Discord = require('discord.js'),
logging = require('../utils/logging'),

@ -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));
}
}

@ -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
});

@ -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;

@ -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() {

Loading…
Cancel
Save