diff --git a/src/index.js b/src/index.js index 7e69009..1109e37 100644 --- a/src/index.js +++ b/src/index.js @@ -89,6 +89,7 @@ process.on('unhandledRejection', error => { const { selectPresence } = require('./utils/discord'); const Cryptr = require('cryptr'); const I18n = require('@eartharoid/i18n'); +const ListenerLoader = require('./modules/listeners/loader'); const CommandManager = require('./modules/commands/manager'); const PluginManager = require('./modules/plugins/manager'); const TicketManager = require('./modules/tickets/manager'); @@ -150,7 +151,9 @@ class Bot extends Client { this.setMaxListeners(this.config.max_listeners); // set the max listeners for each event require('./updater')(this); // check for updates - require('./modules/listeners')(this); // load internal listeners + + const listeners = new ListenerLoader(this); + listeners.load(); // load internal listeners /** The ticket manager */ this.tickets = new TicketManager(this); diff --git a/src/listeners/debug.js b/src/listeners/debug.js index 7726a75..fd81540 100644 --- a/src/listeners/debug.js +++ b/src/listeners/debug.js @@ -1,6 +1,15 @@ -module.exports = { - event: 'debug', - execute: (client, data) => { - if (client.config.debug) client.log.debug(data); +const EventListener = require('../modules/listeners/listener'); + +module.exports = class DebugEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'debug' + }); + } + + async execute(data) { + if (this.client.config.debug) { + this.client.log.debug(data); + } } }; \ No newline at end of file diff --git a/src/listeners/error.js b/src/listeners/error.js index d8aa5e0..1309bf7 100644 --- a/src/listeners/error.js +++ b/src/listeners/error.js @@ -1,7 +1,14 @@ -module.exports = { - event: 'error', - execute: (client, error) => { - client.log.warn('The client encountered an error'); - client.log.error(error); +const EventListener = require('../modules/listeners/listener'); + +module.exports = class ErrorEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'error' + }); + } + + async execute(error) { + this.client.log.warn('The client encountered an error'); + this.client.log.error(error); } }; \ No newline at end of file diff --git a/src/listeners/guildCreate.js b/src/listeners/guildCreate.js index 2c4bd18..bcde138 100644 --- a/src/listeners/guildCreate.js +++ b/src/listeners/guildCreate.js @@ -1,7 +1,14 @@ -module.exports = { - event: 'guildCreate', - execute: async (client, guild) => { - client.log.info(`Added to "${guild.name}"`); +const EventListener = require('../modules/listeners/listener'); + +module.exports = class GuildCreateEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'guildCreate' + }); + } + + async execute(guild) { + this.client.log.info(`Added to "${guild.name}"`); await guild.createSettings(); } }; \ No newline at end of file diff --git a/src/listeners/guildDelete.js b/src/listeners/guildDelete.js index b184e37..f4d9bd9 100644 --- a/src/listeners/guildDelete.js +++ b/src/listeners/guildDelete.js @@ -1,7 +1,14 @@ -module.exports = { - event: 'guildDelete', - execute: async (client, guild) => { - client.log.info(`Removed from "${guild.name}"`); - await guild.deleteSettings(); +const EventListener = require('../modules/listeners/listener'); + +module.exports = class GuildDeleteEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'guildDelete' + }); + } + + async execute(guild) { + this.client.log.info(`Removed from "${guild.name}"`); + // await guild.deleteSettings(); } }; \ No newline at end of file diff --git a/src/listeners/guildMemberRemove.js b/src/listeners/guildMemberRemove.js index 03cafa1..1d76780 100644 --- a/src/listeners/guildMemberRemove.js +++ b/src/listeners/guildMemberRemove.js @@ -1,7 +1,14 @@ -module.exports = { - event: 'guildMemberRemove', - execute: async (client, member) => { - let tickets = await client.db.models.Ticket.findAndCountAll({ +const EventListener = require('../modules/listeners/listener'); + +module.exports = class GuildMemberRemoveEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'guildMemberRemove' + }); + } + + async execute(member) { + let tickets = await this.client.db.models.Ticket.findAndCountAll({ where: { creator: member.id, guild: member.guild.id @@ -9,9 +16,9 @@ module.exports = { }); for (let ticket of tickets.rows) { - await client.tickets.close(ticket.id, null, member.guild.id, 'Member left the guild'); + await this.client.tickets.close(ticket.id, null, member.guild.id, 'Member left the guild'); } - client.log.info(`Closed ${tickets.count} ticket(s) belonging to ${member.user.tag} who left "${member.guild.name}"`); + this.client.log.info(`Closed ${tickets.count} ticket(s) belonging to ${member.user.tag} who left "${member.guild.name}"`); } }; \ No newline at end of file diff --git a/src/listeners/message.js b/src/listeners/message.js index 6b0d81b..d9decfe 100644 --- a/src/listeners/message.js +++ b/src/listeners/message.js @@ -1,16 +1,23 @@ +const EventListener = require('../modules/listeners/listener'); + const { MessageEmbed } = require('discord.js'); const { footer } = require('../utils/discord'); -module.exports = { - event: 'message', - execute: async (client, message) => { +module.exports = class MessageEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'message' + }); + } + + async execute(message) { if (!message.guild) return; let settings = await message.guild.settings; if (!settings) settings = await message.guild.createSettings(); - const i18n = client.i18n.getLocale(settings.locale); + const i18n = this.client.i18n.getLocale(settings.locale); - let t_row = await client.db.models.Ticket.findOne({ + let t_row = await this.client.db.models.Ticket.findOne({ where: { id: message.channel.id } @@ -18,10 +25,10 @@ module.exports = { if (t_row) { if (settings.log_messages && !message.system) { - client.tickets.archives.addMessage(message); // add the message to the archives (if it is in a ticket channel) + this.client.tickets.archives.addMessage(message); // add the message to the archives (if it is in a ticket channel) } - const ignore = [client.user.id, t_row.creator]; + const ignore = [this.client.user.id, t_row.creator]; if (!t_row.first_response && !ignore.includes(message.author.id)) { t_row.update({ first_response: new Date() @@ -29,8 +36,8 @@ module.exports = { } } else { if (message.author.bot) return; - - let p_row = await client.db.models.Panel.findOne({ + + let p_row = await this.client.db.models.Panel.findOne({ where: { channel: message.channel.id } @@ -41,13 +48,13 @@ module.exports = { await message.delete(); - let cat_row = await client.db.models.Category.findOne({ + let cat_row = await this.client.db.models.Category.findOne({ where: { id: p_row.categories } }); - let tickets = await client.db.models.Ticket.findAndCountAll({ + let tickets = await this.client.db.models.Ticket.findAndCountAll({ where: { category: cat_row.id, creator: message.author.id, @@ -94,7 +101,7 @@ module.exports = { } } else { try { - await client.tickets.create(message.guild.id, message.author.id, cat_row.id, message.cleanContent); + await this.client.tickets.create(message.guild.id, message.author.id, cat_row.id, message.cleanContent); } catch (error) { const embed = new MessageEmbed() .setColor(settings.error_colour) @@ -118,6 +125,7 @@ module.exports = { } } - client.commands.handle(message); // pass the message to the command handler + this.client.commands.handle(message); // pass the message to the command handler } -}; \ No newline at end of file +}; + diff --git a/src/listeners/messageDelete.js b/src/listeners/messageDelete.js index 6ff878a..e90efec 100644 --- a/src/listeners/messageDelete.js +++ b/src/listeners/messageDelete.js @@ -1,11 +1,18 @@ -module.exports = { - event: 'messageDelete', - execute: async (client, message) => { +const EventListener = require('../modules/listeners/listener'); + +module.exports = class MessageDeleteEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'messageDelete' + }); + } + + async execute(message) { if (!message.guild) return; let settings = await message.guild.settings; if (!settings) settings = await message.guild.createSettings(); - if (settings.log_messages && !message.system) client.tickets.archives.deleteMessage(message); // mark the message as deleted in the database (if it exists) + if (settings.log_messages && !message.system) this.client.tickets.archives.deleteMessage(message); // mark the message as deleted in the database (if it exists) } }; \ No newline at end of file diff --git a/src/listeners/messageReactionAdd.js b/src/listeners/messageReactionAdd.js index bc781c2..098cdbf 100644 --- a/src/listeners/messageReactionAdd.js +++ b/src/listeners/messageReactionAdd.js @@ -1,36 +1,43 @@ +const EventListener = require('../modules/listeners/listener'); + const { MessageEmbed } = require('discord.js'); const { footer } = require('../utils/discord'); -module.exports = { - event: 'messageReactionAdd', - execute: async (client, r, u) => { +module.exports = class MessageReactionAddEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'messageReactionAdd' + }); + } + + async execute(r, u) { if (r.partial) r = await r.fetch(); if (u.partial) u = await u.fetch(); - if (u.id === client.user.id) return; + if (u.id === this.client.user.id) return; const guild = r.message.guild; if (!guild) return; let settings = await guild.settings; if (!settings) settings = await guild.createSettings(); - const i18n = client.i18n.getLocale(settings.locale); - + const i18n = this.client.i18n.getLocale(settings.locale); + const channel = r.message.channel; const member = await guild.members.fetch(u.id); if (settings.blacklist.includes(u.id)) { - return client.log.info(`Ignoring blacklisted member ${u.tag}`); + return this.client.log.info(`Ignoring blacklisted member ${u.tag}`); } else { settings.blacklist.forEach(element => { if (guild.roles.cache.has(element) && member.roles.cache.has(element)) { - return client.log.info(`Ignoring member ${u.tag} with blacklisted role`); + return this.client.log.info(`Ignoring member ${u.tag} with blacklisted role`); } }); } - - let t_row = await client.db.models.Ticket.findOne({ + + let t_row = await this.client.db.models.Ticket.findOne({ where: { id: channel.id } @@ -48,7 +55,7 @@ module.exports = { VIEW_CHANNEL: true, }, `Ticket claimed by ${member.user.tag}`); - let cat_row = await client.db.models.Category.findOne({ + let cat_row = await this.client.db.models.Category.findOne({ where: { id: t_row.category } @@ -60,7 +67,7 @@ module.exports = { }, `Ticket claimed by ${member.user.tag}`); } - client.log.info(`${member.user.tag} has claimed "${channel.name}" in "${guild.name}"`); + this.client.log.info(`${member.user.tag} has claimed "${channel.name}" in "${guild.name}"`); await channel.send( new MessageEmbed() @@ -74,7 +81,7 @@ module.exports = { await r.users.remove(u.id); } } else { - let p_row = await client.db.models.Panel.findOne({ + let p_row = await this.client.db.models.Panel.findOne({ where: { message: r.message.id } @@ -83,17 +90,17 @@ module.exports = { if (p_row && typeof p_row.categories !== 'string') { // panels await r.users.remove(u.id); - + let category_id = p_row.categories[r.emoji.name]; if (!category_id) return; - let cat_row = await client.db.models.Category.findOne({ + let cat_row = await this.client.db.models.Category.findOne({ where: { id: category_id } }); - let tickets = await client.db.models.Ticket.findAndCountAll({ + let tickets = await this.client.db.models.Ticket.findAndCountAll({ where: { category: cat_row.id, creator: u.id, @@ -140,7 +147,7 @@ module.exports = { } } else { try { - await client.tickets.create(guild.id, u.id, cat_row.id); + await this.client.tickets.create(guild.id, u.id, cat_row.id); } catch (error) { const embed = new MessageEmbed() .setColor(settings.error_colour) @@ -157,7 +164,7 @@ module.exports = { } if (response) { - setTimeout(async() => { + setTimeout(async () => { await response.delete(); }, 15000); } @@ -165,4 +172,4 @@ module.exports = { } } -}; \ No newline at end of file +}; diff --git a/src/listeners/messageUpdate.js b/src/listeners/messageUpdate.js index 873152c..03d489b 100644 --- a/src/listeners/messageUpdate.js +++ b/src/listeners/messageUpdate.js @@ -1,12 +1,18 @@ -module.exports = { - event: 'messageUpdate', - execute: async (client, oldm, newm) => { +const EventListener = require('../modules/listeners/listener'); +module.exports = class MessageUpdateEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'messageUpdate' + }); + } + + async execute(oldm, newm) { if (newm.partial) { try { await newm.fetch(); } catch (err) { - return client.log.error(err); + return this.client.log.error(err); } } @@ -15,6 +21,6 @@ module.exports = { let settings = await newm.guild.settings; if (!settings) settings = await newm.guild.createSettings(); - if (settings.log_messages && !newm.system) client.tickets.archives.updateMessage(newm); // update the message in the database + if (settings.log_messages && !newm.system) this.client.tickets.archives.updateMessage(newm); // update the message in the database } }; \ No newline at end of file diff --git a/src/listeners/rateLimit.js b/src/listeners/rateLimit.js index 28c04d7..7722418 100644 --- a/src/listeners/rateLimit.js +++ b/src/listeners/rateLimit.js @@ -1,6 +1,13 @@ -module.exports = { - event: 'rateLimit', - execute: (client, limit) => { - client.log.warn('Rate-limited!', limit); +const EventListener = require('../modules/listeners/listener'); + +module.exports = class RateLimitEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'rateLimit' + }); + } + + async execute(limit) { + this.client.log.warn('Rate-limited!', limit); } }; \ No newline at end of file diff --git a/src/listeners/ready.js b/src/listeners/ready.js index e1881e1..ebdd60d 100644 --- a/src/listeners/ready.js +++ b/src/listeners/ready.js @@ -1,29 +1,34 @@ -module.exports = { - event: 'ready', - once: true, - execute: async (client) => { +const EventListener = require('../modules/listeners/listener'); - client.log.success(`Connected to Discord as "${client.user.tag}"`); +module.exports = class ReadyEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'ready', + once: true + }); + } - client.commands.load(); // load internal commands + async execute() { + this.client.log.success(`Connected to Discord as "${this.client.user.tag}"`); - client.plugins.plugins.forEach(p => p.load()); // call load function for each plugin + this.client.commands.load(); // load internal commands - if (client.config.presence.presences.length > 1) { + this.client.plugins.plugins.forEach(p => p.load()); // call load function for each plugin + + if (this.client.config.presence.presences.length > 1) { const { selectPresence } = require('../utils/discord'); setInterval(() => { let presence = selectPresence(); - client.user.setPresence(presence); - client.log.debug(`Updated presence: ${presence.activity.type} ${presence.activity.name}`); - }, client.config.presence.duration * 1000); + this.client.user.setPresence(presence); + this.client.log.debug(`Updated presence: ${presence.activity.type} ${presence.activity.name}`); + }, this.client.config.presence.duration * 1000); } - if(client.config.super_secret_setting) { + if (this.client.config.super_secret_setting) { setInterval(async () => { - await client.postStats(); + await this.client.postStats(); }, 3600000); - await client.postStats(); + await this.client.postStats(); } - } }; \ No newline at end of file diff --git a/src/listeners/warn.js b/src/listeners/warn.js index fe1cc6a..e3e7854 100644 --- a/src/listeners/warn.js +++ b/src/listeners/warn.js @@ -1,6 +1,13 @@ -module.exports = { - event: 'warn', - execute: (client, warning) => { - client.log.warn(warning); +const EventListener = require('../modules/listeners/listener'); + +module.exports = class WarnEventListener extends EventListener { + constructor(client) { + super(client, { + event: 'warn' + }); + } + + async execute(warning) { + this.client.log.warn(warning); } }; \ No newline at end of file diff --git a/src/modules/listeners.js b/src/modules/listeners.js deleted file mode 100644 index 7fc3ce0..0000000 --- a/src/modules/listeners.js +++ /dev/null @@ -1,17 +0,0 @@ -const fs = require('fs'); -const { path } = require('../utils/fs'); - -module.exports = client => { - const files = fs.readdirSync(path('./src/listeners')) - .filter(file => file.endsWith('.js')); - - for (const file of files) { - const listener = require(`../listeners/${file}`); - const exec = (...args) => listener.execute(client, ...args); - let on = listener.once ? 'once' : 'on'; - if (listener.raw) - client.ws[on](listener.event, exec); - else - client[on](listener.event, exec); - } -}; \ No newline at end of file diff --git a/src/modules/listeners/listener.js b/src/modules/listeners/listener.js new file mode 100644 index 0000000..54836de --- /dev/null +++ b/src/modules/listeners/listener.js @@ -0,0 +1,10 @@ +module.exports = class EventListener { + + constructor(client, data) { + this.client = client; + this.event = data.event; + this.raw = data.raw || false; + this.once = data.once || false; + } + +}; \ No newline at end of file diff --git a/src/modules/listeners/loader.js b/src/modules/listeners/loader.js new file mode 100644 index 0000000..4aecca9 --- /dev/null +++ b/src/modules/listeners/loader.js @@ -0,0 +1,38 @@ +const fs = require('fs'); +const { path } = require('../../utils/fs'); + +/** + * Manages the loading of event listeners + */ +module.exports = class ListenerLoader { + /** + * Create a ListenerLoader instance + * @param {Client} client + */ + constructor(client) { + /** The Discord Client */ + this.client = client; + } + + load() { + const files = fs.readdirSync(path('./src/listeners')) + .filter(file => file.endsWith('.js')); + + for (let file of files) { + try { + file = require(`../../listeners/${file}`); + const listener = new file(this.client); + let on = listener.once ? 'once' : 'on'; + if (listener.raw) + this.client.ws[on](listener.event, (...data) => listener.execute(...data)); + else + this.client[on](listener.event, (...data) => listener.execute(...data)); + } catch (e) { + this.client.log.warn('An error occurred whilst loading a listener'); + this.client.log.error(e); + } + } + + } + +}; \ No newline at end of file diff --git a/src/updater.js b/src/updater.js index 7008261..309cd45 100644 --- a/src/updater.js +++ b/src/updater.js @@ -16,12 +16,12 @@ module.exports = async client => { if (!semver.valid(latest)) return; if (semver.lt(current, latest)) { - client.log.notice(client.log.f(`There is an update available for Discord Tickets (${current} -> ${update.tag_name})`)); + client.log.notice(`There is an update available for Discord Tickets (${current} -> ${update.tag_name})`); let lines = [ - `&6You are currently using &c${current}&6, the latest is &a${update.tag_name}&6.`, - `&6Download "&f${update.name}&6" from`, - link('&6the GitHub releases page', 'https://github.com/discord-tickets/bot/releases/') + `&k&6You are currently using &c${current}&6, the latest is &a${update.tag_name}&6.&r`, + `&k&6Download "&f${update.name}&6" from&r`, + link('&k&6the GitHub releases page.&r&6', 'https://github.com/discord-tickets/bot/releases/') ]; console.log(