diff --git a/.eslintrc.js b/.eslintrc.js index 7c39911..b354fdb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,10 +5,73 @@ module.exports = { 'node': true }, 'extends': 'eslint:recommended', - 'parserOptions': { - 'ecmaVersion': 12 - }, + 'parserOptions': { 'ecmaVersion': 12 }, 'rules': { + 'array-bracket-newline': [ + 'error', + 'consistent' + ], + 'array-bracket-spacing': [ + 'error', + 'never' + ], + 'array-element-newline': [ + 'error', + 'consistent' + ], + 'arrow-body-style': [ + 'error', + 'as-needed' + ], + 'arrow-parens': [ + 'error', + 'as-needed' + ], + 'block-spacing': [ + 'error', + 'always' + ], + 'brace-style': [ + 'error', + '1tbs' + ], + 'comma-dangle': [ + 'error', + 'never' + ], + 'comma-spacing': [ + 'error', + { + 'after': true, + 'before': false + } + ], + 'comma-style': [ + 'error', + 'last' + ], + 'computed-property-spacing': [ + 'error', + 'never' + ], + 'curly': [ + 'error', + 'multi-line', // 'multi' + 'consistent' + ], + 'default-case-last': [ + 'error' + ], + 'dot-location': [ + 'error', + 'property' + ], + 'dot-notation': [ + 'error' + ], + 'eqeqeq': [ + 'error' + ], 'indent': [ 'error', 'tab' @@ -17,6 +80,74 @@ module.exports = { 'off', 'windows' ], + 'max-depth': [ + 'warn', + { 'max': 5 } + ], + 'max-len': [ + 'warn', + { + 'code': 150, + 'ignoreRegExpLiterals': true, + 'ignoreStrings': true, + 'ignoreTemplateLiterals': true, + 'ignoreTrailingComments': true, + 'ignoreUrls': true + } + ], + 'max-lines': [ + 'warn' + ], + 'max-statements-per-line': [ + 'error' + ], + 'multiline-comment-style': [ + 'warn' + ], + 'no-console': [ + 'warn' + ], + 'no-return-assign': [ + 'error' + ], + 'no-template-curly-in-string': [ + 'warn' + ], + 'no-trailing-spaces': [ + 'error' + ], + 'no-underscore-dangle': [ + 'error' + ], + 'no-unneeded-ternary': [ + 'error' + ], + 'no-var': [ + 'error' + ], + 'no-whitespace-before-property': [ + 'error' + ], + 'object-curly-newline': [ + 'error', + { + 'minProperties': 2, + 'multiline': true + } + ], + 'object-curly-spacing': [ + 'error', + 'always' + ], + 'object-property-newline': [ + 'error' + ], + 'operator-linebreak': [ + 'error' + ], + 'prefer-arrow-callback': [ + 'error' + ], 'prefer-const': [ 'error', { @@ -32,5 +163,14 @@ module.exports = { 'error', 'always' ], + 'sort-keys': [ + 'error', + 'asc', + { 'natural': true } + ], + 'space-in-parens': [ + 'error', + 'never' + ] } }; \ No newline at end of file diff --git a/README.md b/README.md index 4ef5694..eedca6e 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,17 @@ - - - - -# [Discord Tickets](https://discordtickets.app) - [![GitHub stars](https://img.shields.io/github/stars/discord-tickets/bot?style=flat-square)](https://github.com/discord-tickets/bot/stargazers) [![GitHub forks](https://img.shields.io/github/forks/discord-tickets/bot?style=flat-square)](https://github.com/discord-tickets/bot/stargazers) [![License](https://img.shields.io/github/license/discord-tickets/bot?style=flat-square)](https://github.com/discord-tickets/bot/blob/master/LICENSE) -![Codacy grade](https://img.shields.io/codacy/grade/14e6851c85444424b75b8bc3f93e93db?logo=codacy&style=flat-square) -[![Discord](https://img.shields.io/discord/451745464480432129?label=discord&color=7289DA&style=flat-square)](https://discord.gg/pXc9vyC) +[![Codacy](https://img.shields.io/codacy/grade/b974eb5f984c40868e07d82c968bd02d?logo=codacy&style=flat-square)](https://www.codacy.com/gh/discord-tickets/bot/dashboard?utm_source=github.com&utm_medium=referral&utm_content=discord-tickets/bot&utm_campaign=Badge_Grade) +[![Discord](https://img.shields.io/discord/451745464480432129?label=discord&color=7289DA&style=flat-square)](https://go.eartharoid.me/discord) [![Crowdin](https://badges.crowdin.net/discord-tickets/localized.svg)](https://i18n.discordtickets.app/project/discord-tickets) +
+ +![Discord Tickets](https://ik.imagekit.io/eartharoid/discord-tickets/wordmark/gradient_HTC7nqZr9.png) + + An open-source ticket management bot for Discord - a free alternative to the premium and white-label plans of other popular ticketing bots. -

- -⚠️ -**The code on the master branch is for v3 which is not ready. Please go to the [v2 branch](https://github.com/discord-tickets/bot/tree/v2) for the current version of the code and [documentation](https://github.com/discord-tickets/bot/wiki)**. - -⚠️ -**The following information is about v3. Please read the README file on the [v2 branch](https://github.com/discord-tickets/bot/tree/v2) for information that is about the current version.** - ## What is this? Discord Tickets is a Discord bot for creating and managing "support ticket" channels. It is a free and open-source alternative to the popular paid "premium" and "white-label" ticketing bots, such as [Ticket Tool](https://tickettool.xyz/), [TicketsBot](https://ticketsbot.net/), [Tickety](https://tickety.net/), [Helper.gg](https://helper.gg/), [Helper](https://helper.wtf), and others. @@ -65,7 +56,7 @@ If you choose SQLite, which is the default as it is the easiest, you don't need ### Screenshots -> screenshot of a ticket channel +![The opening message of a ticket channel](https://i.imgur.com/2T5eSH0.png) > screenshot of a panel @@ -117,6 +108,6 @@ Does your community or company use Discord Tickets? Sponsor the project to get y Discord Tickets is licensed under the [GPLv3 license](https://github.com/discord-tickets/bot/blob/master/LICENSE). -Discord Tickets is not related to Discord Inc. +This is not an official Discord product. It is not affiliated with nor endorsed by Discord Inc. © 2021 Isaac Saunders diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index 2670155..0000000 --- a/jsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "include": [ - "src/**/*.js" - ] -} \ No newline at end of file diff --git a/src/banner.js b/src/banner.js index 37c3dff..30b8827 100644 --- a/src/banner.js +++ b/src/banner.js @@ -1,7 +1,10 @@ +/* eslint-disable no-console */ const link = require('terminal-link'); const leeks = require('leeks.js'); -const { version, homepage } = require('../package.json'); +const { + version, homepage +} = require('../package.json'); module.exports = () => { console.log(leeks.colours.cyan(` diff --git a/src/commands/add.js b/src/commands/add.js index 012cda6..1a3e384 100644 --- a/src/commands/add.js +++ b/src/commands/add.js @@ -1,30 +1,32 @@ const Command = require('../modules/commands/command'); -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); module.exports = class AddCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.add.name'), - description: i18n('commands.add.description'), aliases: [], - process_args: false, args: [ { - name: i18n('commands.add.args.member.name'), description: i18n('commands.add.args.member.description'), example: i18n('commands.add.args.member.example'), - required: true, + name: i18n('commands.add.args.member.name'), + required: true }, { - name: i18n('commands.add.args.ticket.name'), description: i18n('commands.add.args.ticket.description'), example: i18n('commands.add.args.ticket.example'), - required: false, + name: i18n('commands.add.args.ticket.name'), + required: false } - ] + ], + description: i18n('commands.add.description'), + internal: true, + name: i18n('commands.add.name'), + process_args: false }); } @@ -38,7 +40,7 @@ module.exports = class AddCommand extends Command { const i18n = this.client.i18n.getLocale(settings.locale); const ticket = message.mentions.channels.first() ?? message.channel; - const t_row = await this.client.tickets.resolve(ticket.id, message.guild.id); + const t_row = await this.client.tickets.resolve(ticket.id, message.guild.id); if (!t_row) { return await message.channel.send( @@ -93,10 +95,10 @@ module.exports = class AddCommand extends Command { ); await ticket.updateOverwrite(member, { - VIEW_CHANNEL: true, + ATTACH_FILES: true, READ_MESSAGE_HISTORY: true, SEND_MESSAGES: true, - ATTACH_FILES: true + VIEW_CHANNEL: true }, `${message.author.tag} added ${member.user.tag} to the ticket`); await this.client.tickets.archives.updateMember(ticket.id, member); diff --git a/src/commands/blacklist.js b/src/commands/blacklist.js index a409b2b..7785bc4 100644 --- a/src/commands/blacklist.js +++ b/src/commands/blacklist.js @@ -1,27 +1,29 @@ const Command = require('../modules/commands/command'); -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); module.exports = class BlacklistCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.blacklist.name'), - description: i18n('commands.blacklist.description'), aliases: [ - i18n('commands.blacklist.aliases.unblacklist'), + i18n('commands.blacklist.aliases.unblacklist') ], - process_args: false, args: [ { - name: i18n('commands.blacklist.args.member_or_role.name'), description: i18n('commands.blacklist.args.member_or_role.description'), example: i18n('commands.blacklist.args.member_or_role.example'), - required: false, + name: i18n('commands.blacklist.args.member_or_role.name'), + required: false } ], - permissions: ['MANAGE_GUILD'] + description: i18n('commands.blacklist.description'), + internal: true, + name: i18n('commands.blacklist.name'), + permissions: ['MANAGE_GUILD'], + process_args: false }); } @@ -45,16 +47,19 @@ module.exports = class BlacklistCommand extends Command { .setFooter(settings.footer, message.guild.iconURL()) ); } - - + + const role = message.mentions.roles.first(); let id; const input = args.trim().split(/\s/g)[0]; - if (member) id = member.id; - else if (role) id = role.id; - else if (/\d{17,19}/.test(input)) id = input; - else if (settings.blacklist?.length === 0) { + if (member) { + id = member.id; + } else if (role) { + id = role.id; + } else if (/\d{17,19}/.test(input)) { + id = input; + } else if (settings.blacklist?.length === 0) { return await message.channel.send( new MessageEmbed() .setColor(settings.colour) diff --git a/src/commands/close.js b/src/commands/close.js index 984d85b..d3c6d7c 100644 --- a/src/commands/close.js +++ b/src/commands/close.js @@ -1,6 +1,10 @@ const Command = require('../modules/commands/command'); // eslint-disable-next-line no-unused-vars -const { MessageEmbed, MessageMentions, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed, + MessageMentions +} = require('discord.js'); const { Op } = require('sequelize'); const toTime = require('to-time-monthsfork'); const { footer } = require('../utils/discord'); @@ -9,43 +13,40 @@ module.exports = class CloseCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.close.name'), - description: i18n('commands.close.description'), aliases: [ i18n('commands.close.aliases.delete'), - i18n('commands.close.aliases.lock'), + i18n('commands.close.aliases.lock') ], - process_args: true, args: [ { - name: i18n('commands.close.args.ticket.name'), + alias: i18n('commands.close.args.ticket.alias'), description: i18n('commands.close.args.ticket.description'), example: i18n('commands.close.args.ticket.example'), + name: i18n('commands.close.args.ticket.name'), required: false, - // for arg parsing - alias: i18n('commands.close.args.ticket.alias'), type: String }, { - name: i18n('commands.close.args.reason.name'), + alias: i18n('commands.close.args.reason.alias'), description: i18n('commands.close.args.reason.description'), example: i18n('commands.close.args.reason.example'), + name: i18n('commands.close.args.reason.name'), required: false, - // for arg parsing - alias: i18n('commands.close.args.reason.alias'), type: String }, { - name: i18n('commands.close.args.time.name'), + alias: i18n('commands.close.args.time.alias'), description: i18n('commands.close.args.time.description'), example: i18n('commands.close.args.time.example'), + name: i18n('commands.close.args.time.name'), required: false, - // for arg parsing - alias: i18n('commands.close.args.time.alias'), type: String } - ] + ], + description: i18n('commands.close.description'), + internal: true, + name: i18n('commands.close.name'), + process_args: true }); } @@ -79,10 +80,8 @@ module.exports = class CloseCommand extends Command { const tickets = await this.client.db.models.Ticket.findAndCountAll({ where: { - last_message: { - [Op.lte]: new Date(Date.now() - period) - }, - guild: message.guild.id + guild: message.guild.id, + last_message: { [Op.lte]: new Date(Date.now() - period) } } }); @@ -105,13 +104,9 @@ module.exports = class CloseCommand extends Command { await collector_message.react('✅'); - const collector_filter = (reaction, user) => { - return user.id === message.author.id && reaction.emoji.name === '✅'; - }; + const collector_filter = (reaction, user) => user.id === message.author.id && reaction.emoji.name === '✅'; - const collector = collector_message.createReactionCollector(collector_filter, { - time: 30000 - }); + const collector = collector_message.createReactionCollector(collector_filter, { time: 30000 }); collector.on('collect', async () => { await collector_message.reactions.removeAll(); @@ -130,7 +125,7 @@ module.exports = class CloseCommand extends Command { }); - collector.on('end', async (collected) => { + collector.on('end', async collected => { if (collected.size === 0) { await collector_message.reactions.removeAll(); await collector_message.edit( @@ -169,11 +164,7 @@ module.exports = class CloseCommand extends Command { ); } } else { - t_row = await this.client.db.models.Ticket.findOne({ - where: { - id: message.channel.id - } - }); + t_row = await this.client.db.models.Ticket.findOne({ where: { id: message.channel.id } }); if (!t_row) { return await message.channel.send( @@ -196,13 +187,9 @@ module.exports = class CloseCommand extends Command { await collector_message.react('✅'); - const collector_filter = (reaction, user) => { - return user.id === message.author.id && reaction.emoji.name === '✅'; - }; + const collector_filter = (reaction, user) => user.id === message.author.id && reaction.emoji.name === '✅'; - const collector = collector_message.createReactionCollector(collector_filter, { - time: 30000 - }); + const collector = collector_message.createReactionCollector(collector_filter, { time: 30000 }); collector.on('collect', async () => { collector.stop(); @@ -223,7 +210,7 @@ module.exports = class CloseCommand extends Command { await this.client.tickets.close(t_row.id, message.author.id, message.guild.id, args[arg_reason]); }); - collector.on('end', async (collected) => { + collector.on('end', async collected => { if (collected.size === 0) { await collector_message.reactions.removeAll(); await collector_message.edit( @@ -244,7 +231,7 @@ module.exports = class CloseCommand extends Command { }, 15000); } }); - + } } }; \ No newline at end of file diff --git a/src/commands/help.js b/src/commands/help.js index 325521e..4b8a0a8 100644 --- a/src/commands/help.js +++ b/src/commands/help.js @@ -1,33 +1,35 @@ const Command = require('../modules/commands/command'); -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); module.exports = class HelpCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.help.name'), - description: i18n('commands.help.description'), aliases: [ i18n('commands.help.aliases.command'), - i18n('commands.help.aliases.commands'), + i18n('commands.help.aliases.commands') ], - process_args: false, args: [ { - name: i18n('commands.help.args.command.name'), description: i18n('commands.help.args.command.description'), example: i18n('commands.help.args.command.example'), - required: false, + name: i18n('commands.help.args.command.name'), + required: false } - ] + ], + description: i18n('commands.help.description'), + internal: true, + name: i18n('commands.help.name'), + process_args: false }); } /** - * @param {Message} message - * @param {string} args + * @param {Message} message + * @param {string} args * @returns {Promise} */ async execute(message, args) { @@ -54,9 +56,7 @@ module.exports = class HelpCommand extends Command { new MessageEmbed() .setColor(settings.colour) .setTitle(i18n('commands.help.response.list.title')) - .setDescription(i18n('commands.help.response.list.description', { - prefix: settings.command_prefix, - })) + .setDescription(i18n('commands.help.response.list.description', { prefix: settings.command_prefix })) .addField(i18n('commands.help.response.list.fields.commands'), list.join('\n')) .setFooter(settings.footer, message.guild.iconURL()) ); diff --git a/src/commands/new.js b/src/commands/new.js index 7fc7080..52d9e82 100644 --- a/src/commands/new.js +++ b/src/commands/new.js @@ -1,6 +1,8 @@ const Command = require('../modules/commands/command'); -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); const { footer } = require('../utils/discord'); const { letters } = require('../utils/emoji'); const { wait } = require('../utils'); @@ -9,23 +11,23 @@ module.exports = class NewCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.new.name'), - description: i18n('commands.new.description'), aliases: [ i18n('commands.new.aliases.create'), i18n('commands.new.aliases.open'), - i18n('commands.new.aliases.ticket'), + i18n('commands.new.aliases.ticket') ], - process_args: false, args: [ { - name: i18n('commands.new.args.topic.name'), description: i18n('commands.new.args.topic.description'), example: i18n('commands.new.args.topic.example'), - required: false, + name: i18n('commands.new.args.topic.name'), + required: false } - ] + ], + description: i18n('commands.new.description'), + internal: true, + name: i18n('commands.new.name'), + process_args: false }); } @@ -114,11 +116,7 @@ module.exports = class NewCommand extends Command { }, 15000); }; - const categories = await this.client.db.models.Category.findAndCountAll({ - where: { - guild: message.guild.id - } - }); + const categories = await this.client.db.models.Category.findAndCountAll({ where: { guild: message.guild.id } }); if (categories.count === 0) { return await message.channel.send( @@ -153,21 +151,21 @@ module.exports = class NewCommand extends Command { return user.id === message.author.id && allowed.includes(reaction.emoji.name); }; - const collector = collector_message.createReactionCollector(collector_filter, { - time: 30000 - }); + const collector = collector_message.createReactionCollector(collector_filter, { time: 30000 }); - collector.on('collect', async (reaction) => { + collector.on('collect', async reaction => { collector.stop(); const index = letters_array.findIndex(value => value === reaction.emoji.name); // find where the letter is in the alphabet - if (index === -1) return setTimeout(async () => { - await collector_message.delete(); - }, 15000); + if (index === -1) { + return setTimeout(async () => { + await collector_message.delete(); + }, 15000); + } await collector_message.reactions.removeAll(); create(categories.rows[index], collector_message); // create the ticket, passing the existing response message to be edited instead of creating a new one }); - collector.on('end', async (collected) => { + collector.on('end', async collected => { if (collected.size === 0) { await collector_message.reactions.removeAll(); await collector_message.edit( diff --git a/src/commands/panel.js b/src/commands/panel.js index 7097b33..457d648 100644 --- a/src/commands/panel.js +++ b/src/commands/panel.js @@ -1,59 +1,59 @@ const Command = require('../modules/commands/command'); -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); -const { some, wait } = require('../utils'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); +const { + some, wait +} = require('../utils'); const { emojify } = require('node-emoji'); module.exports = class PanelCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.panel.name'), - description: i18n('commands.panel.description'), aliases: [], - process_args: true, args: [ { - name: i18n('commands.panel.args.title.name'), + alias: i18n('commands.panel.args.title.alias'), description: i18n('commands.panel.args.title.description'), example: i18n('commands.panel.args.title.example'), + name: i18n('commands.panel.args.title.name'), required: false, - // for arg parsing - alias: i18n('commands.panel.args.title.alias'), type: String }, { - name: i18n('commands.panel.args.description.name'), + alias: i18n('commands.panel.args.description.alias'), description: i18n('commands.panel.args.description.description'), example: i18n('commands.panel.args.description.example'), + name: i18n('commands.panel.args.description.name'), required: true, - // for arg parsing - alias: i18n('commands.panel.args.description.alias'), type: String }, { - name: i18n('commands.panel.args.emoji.name'), + alias: i18n('commands.panel.args.emoji.alias'), description: i18n('commands.panel.args.emoji.description'), example: i18n('commands.panel.args.emoji.example'), - required: false, - // for arg parsing - alias: i18n('commands.panel.args.emoji.alias'), - type: String, multiple: true, + name: i18n('commands.panel.args.emoji.name'), + required: false, + type: String }, { - name: i18n('commands.panel.args.categories.name'), + alias: i18n('commands.panel.args.categories.alias'), description: i18n('commands.panel.args.categories.description'), example: i18n('commands.panel.args.categories.example'), - required: true, - // for arg parsing - alias: i18n('commands.panel.args.categories.alias'), - type: String, multiple: true, + name: i18n('commands.panel.args.categories.name'), + required: true, + type: String } ], - permissions: ['MANAGE_GUILD'] + description: i18n('commands.panel.description'), + internal: true, + name: i18n('commands.panel.name'), + permissions: ['MANAGE_GUILD'], + process_args: true }); } @@ -72,21 +72,20 @@ module.exports = class PanelCommand extends Command { const settings = await message.guild.getSettings(); const i18n = this.client.i18n.getLocale(settings.locale); - if (!args[arg_emoji]) - args[arg_emoji] = []; - + if (!args[arg_emoji]) args[arg_emoji] = []; + args[arg_emoji] = args[arg_emoji].map(emoji => emojify(emoji.replace(/\\/g, ''))); const invalid_category = await some(args[arg_categories], async id => { const cat_row = await this.client.db.models.Category.findOne({ where: { - id: id, - guild: message.guild.id + guild: message.guild.id, + id } }); return !cat_row; }); - + if (invalid_category) { return await message.channel.send( new MessageEmbed() @@ -99,36 +98,35 @@ module.exports = class PanelCommand extends Command { let panel_channel, panel_message; - + let categories_map = args[arg_categories][0]; - + const embed = new MessageEmbed() .setColor(settings.colour) .setFooter(settings.footer, message.guild.iconURL()); - - if (args[arg_title]) - embed.setTitle(args[arg_title]); + + if (args[arg_title]) embed.setTitle(args[arg_title]); if (args[arg_emoji].length === 0) { // reaction-less panel panel_channel = await message.guild.channels.create('create-a-ticket', { - type: 'text', - rateLimitPerUser: 30, permissionOverwrites: [ { - id: message.guild.roles.everyone, allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'], - deny: ['ATTACH_FILES', 'EMBED_LINKS', 'ADD_REACTIONS'] + deny: ['ATTACH_FILES', 'EMBED_LINKS', 'ADD_REACTIONS'], + id: message.guild.roles.everyone }, { - id: this.client.user.id, - allow: ['EMBED_LINKS'] + allow: ['EMBED_LINKS'], + id: this.client.user.id } ], position: 1, - reason: `${message.author.tag} created a new reaction-less panel` + rateLimitPerUser: 30, + reason: `${message.author.tag} created a new reaction-less panel`, + type: 'text' }); - + embed.setDescription(args[arg_description]); panel_message = await panel_channel.send(embed); @@ -145,20 +143,20 @@ module.exports = class PanelCommand extends Command { ); } else { panel_channel = await message.guild.channels.create('create-a-ticket', { - type: 'text', permissionOverwrites: [ { - id: message.guild.roles.everyone, allow: ['VIEW_CHANNEL', 'READ_MESSAGE_HISTORY'], - deny: ['SEND_MESSAGES', 'ADD_REACTIONS'] + deny: ['SEND_MESSAGES', 'ADD_REACTIONS'], + id: message.guild.roles.everyone }, { - id: this.client.user.id, - allow: ['SEND_MESSAGES', 'EMBED_LINKS'] + allow: ['SEND_MESSAGES', 'EMBED_LINKS'], + id: this.client.user.id } ], position: 1, - reason: `${message.author.tag} created a new panel` + reason: `${message.author.tag} created a new panel`, + type: 'text' }); if (args[arg_emoji].length === 1) { @@ -172,13 +170,13 @@ module.exports = class PanelCommand extends Command { // multi category let description = ''; categories_map = {}; - + for (const i in args[arg_emoji]) { categories_map[args[arg_emoji][i]] = args[arg_categories][i]; const cat_row = await this.client.db.models.Category.findOne({ where: { - id: args[arg_categories][i], - guild: message.guild.id + guild: message.guild.id, + id: args[arg_categories][i] } }); description += `\n> ${args[arg_emoji][i]} | ${cat_row.name}`; @@ -191,7 +189,7 @@ module.exports = class PanelCommand extends Command { await panel_message.react(emoji); await wait(1000); // 1 reaction per second rate-limit } - + } this.client.log.info(`${message.author.tag} has created a new panel`); @@ -204,7 +202,7 @@ module.exports = class PanelCommand extends Command { categories: categories_map, channel: panel_channel.id, guild: message.guild.id, - message: panel_message.id, + message: panel_message.id }); } }; \ No newline at end of file diff --git a/src/commands/remove.js b/src/commands/remove.js index 5a1920b..d610303 100644 --- a/src/commands/remove.js +++ b/src/commands/remove.js @@ -1,30 +1,32 @@ const Command = require('../modules/commands/command'); -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); module.exports = class RemoveCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.remove.name'), - description: i18n('commands.remove.description'), aliases: [], - process_args: false, args: [ { - name: i18n('commands.remove.args.member.name'), description: i18n('commands.remove.args.member.description'), example: i18n('commands.remove.args.member.example'), - required: true, + name: i18n('commands.remove.args.member.name'), + required: true }, { - name: i18n('commands.remove.args.ticket.name'), description: i18n('commands.remove.args.ticket.description'), example: i18n('commands.remove.args.ticket.example'), - required: false, + name: i18n('commands.remove.args.ticket.name'), + required: false } - ] + ], + description: i18n('commands.remove.description'), + internal: true, + name: i18n('commands.remove.name'), + process_args: false }); } diff --git a/src/commands/settings.js b/src/commands/settings.js index fb48f22..5929502 100644 --- a/src/commands/settings.js +++ b/src/commands/settings.js @@ -1,22 +1,24 @@ const Command = require('../modules/commands/command'); const fetch = require('node-fetch'); -// eslint-disable-next-line no-unused-vars -const { MessageAttachment, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageAttachment +} = require('discord.js'); const { Validator } = require('jsonschema'); module.exports = class SettingsCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { + aliases: [ + i18n('commands.settings.aliases.config') + ], + args: [], + description: i18n('commands.settings.description'), internal: true, name: i18n('commands.settings.name'), - description: i18n('commands.settings.description'), - aliases: [ - i18n('commands.settings.aliases.config'), - ], - process_args: false, - args: [], - permissions: ['MANAGE_GUILD'] + permissions: ['MANAGE_GUILD'], + process_args: false }); this.schema = require('./extra/settings.schema.json'); @@ -40,7 +42,9 @@ module.exports = class SettingsCommand extends Command { this.client.log.info(`Downloading settings for "${message.guild.name}"`); const data = await (await fetch(attachments[0].url)).json(); - const { valid, errors } = this.v.validate(data, this.schema); + const { + valid, errors + } = this.v.validate(data, this.schema); if (!valid) { this.client.log.warn('Settings validation error'); @@ -60,11 +64,7 @@ module.exports = class SettingsCommand extends Command { for (const c of data.categories) { if (c.id) { // existing category - const cat_row = await this.client.db.models.Category.findOne({ - where: { - id: c.id - } - }); + const cat_row = await this.client.db.models.Category.findOne({ where: { id: c.id } }); cat_row.claiming = c.claiming; cat_row.image = c.image; cat_row.max_per_member = c.max_per_member; @@ -81,15 +81,14 @@ module.exports = class SettingsCommand extends Command { const cat_channel = await this.client.channels.fetch(c.id); if (cat_channel) { - if (cat_channel.name !== c.name) - await cat_channel.setName(c.name, `Tickets category updated by ${message.author.tag}`); + if (cat_channel.name !== c.name) await cat_channel.setName(c.name, `Tickets category updated by ${message.author.tag}`); for (const r of c.roles) { await cat_channel.updateOverwrite(r, { - VIEW_CHANNEL: true, + ATTACH_FILES: true, READ_MESSAGE_HISTORY: true, SEND_MESSAGES: true, - ATTACH_FILES: true + VIEW_CHANNEL: true }, `Tickets category updated by ${message.author.tag}`); } } @@ -97,33 +96,31 @@ module.exports = class SettingsCommand extends Command { // create a new category const allowed_permissions = ['VIEW_CHANNEL', 'READ_MESSAGE_HISTORY', 'SEND_MESSAGES', 'EMBED_LINKS', 'ATTACH_FILES']; const cat_channel = await message.guild.channels.create(c.name, { - type: 'category', - reason: `Tickets category created by ${message.author.tag}`, - position: 1, permissionOverwrites: [ ...[ { - id: message.guild.roles.everyone, - deny: ['VIEW_CHANNEL'] + deny: ['VIEW_CHANNEL'], + id: message.guild.roles.everyone }, { - id: this.client.user.id, - allow: allowed_permissions + allow: allowed_permissions, + id: this.client.user.id } ], - ...c.roles.map(r => { - return { - id: r, - allow: allowed_permissions - }; - }) - ] + ...c.roles.map(r => ({ + allow: allowed_permissions, + id: r + })) + ], + position: 1, + reason: `Tickets category created by ${message.author.tag}`, + type: 'category' }); await this.client.db.models.Category.create({ - id: cat_channel.id, claiming: c.claiming, guild: message.guild.id, + id: cat_channel.id, image: c.image, max_per_member: c.max_per_member, name: c.name, @@ -141,11 +138,11 @@ module.exports = class SettingsCommand extends Command { for (const survey in data.surveys) { const survey_data = { guild: message.guild.id, - name: survey, + name: survey }; const [s_row] = await this.client.db.models.Survey.findOrCreate({ - where: survey_data, - defaults: survey_data + defaults: survey_data, + where: survey_data }); s_row.questions = data.surveys[survey]; await s_row.save(); @@ -156,35 +153,25 @@ module.exports = class SettingsCommand extends Command { } else { // upload settings as json to be edited - const categories = await this.client.db.models.Category.findAll({ - where: { - guild: message.guild.id - } - }); - - const surveys = await this.client.db.models.Survey.findAll({ - where: { - guild: message.guild.id - } - }); + const categories = await this.client.db.models.Category.findAll({ where: { guild: message.guild.id } }); + + const surveys = await this.client.db.models.Survey.findAll({ where: { guild: message.guild.id } }); const data = { - categories: categories.map(c => { - return { - id: c.id, - claiming: c.claiming, - image: c.image, - max_per_member: c.max_per_member, - name: c.name, - name_format: c.name_format, - opening_message: c.opening_message, - opening_questions: c.opening_questions, - ping: c.ping, - require_topic: c.require_topic, - roles: c.roles, - survey: c.survey - }; - }), + categories: categories.map(c => ({ + claiming: c.claiming, + id: c.id, + image: c.image, + max_per_member: c.max_per_member, + name: c.name, + name_format: c.name_format, + opening_message: c.opening_message, + opening_questions: c.opening_questions, + ping: c.ping, + require_topic: c.require_topic, + roles: c.roles, + survey: c.survey + })), colour: settings.colour, command_prefix: settings.command_prefix, error_colour: settings.error_colour, @@ -197,7 +184,9 @@ module.exports = class SettingsCommand extends Command { }; for (const survey in surveys) { - const { name, questions } = surveys[survey]; + const { + name, questions + } = surveys[survey]; data.surveys[name] = questions; } @@ -206,9 +195,7 @@ module.exports = class SettingsCommand extends Command { `Settings for ${message.guild.name}.json` ); - return await message.channel.send({ - files: [attachment] - }); + return await message.channel.send({ files: [attachment] }); } } }; \ No newline at end of file diff --git a/src/commands/stats.js b/src/commands/stats.js index 3af6545..9ccbb65 100644 --- a/src/commands/stats.js +++ b/src/commands/stats.js @@ -1,24 +1,24 @@ const Command = require('../modules/commands/command'); const Keyv = require('keyv'); -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); module.exports = class StatsCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { + aliases: [], + args: [], + description: i18n('commands.stats.description'), internal: true, name: i18n('commands.stats.name'), - description: i18n('commands.stats.description'), - aliases: [], process_args: false, - args: [], staff_only: true }); - this.cache = new Keyv({ - namespace: 'cache.commands.stats' - }); + this.cache = new Keyv({ namespace: 'cache.commands.stats' }); } /** @@ -35,27 +35,19 @@ module.exports = class StatsCommand extends Command { let stats = await this.cache.get(message.guild.id); if (!stats) { - const tickets = await this.client.db.models.Ticket.findAndCountAll({ - where: { - guild: message.guild.id - } - }); + const tickets = await this.client.db.models.Ticket.findAndCountAll({ where: { guild: message.guild.id } }); stats = { // maths - tickets: tickets.count, messages: settings.log_messages ? await messages.rows - .reduce(async (acc, row) => (await this.client.db.models.Ticket.findOne({ - where: { - id: row.ticket - } - })).guild === message.guild.id + .reduce(async (acc, row) => (await this.client.db.models.Ticket.findOne({ where: { id: row.ticket } })) + .guild === message.guild.id ? await acc + 1 : await acc, 0) : null, - response_time: Math.floor(tickets.rows.reduce((acc, row) => row.first_response ? acc + ((Math.abs(new Date(row.createdAt) - new Date(row.first_response)) / 1000) / 60) - : acc, 0) / tickets.count) + : acc, 0) / tickets.count), + tickets: tickets.count }; await this.cache.set(message.guild.id, stats, 60 * 60 * 1000); // cache for an hour } @@ -67,7 +59,7 @@ module.exports = class StatsCommand extends Command { .addField(i18n('commands.stats.fields.tickets'), stats.tickets, true) .addField(i18n('commands.stats.fields.response_time.title'), i18n('commands.stats.fields.response_time.minutes', stats.response_time), true) .setFooter(settings.footer, message.guild.iconURL()); - + if (stats.messages) guild_embed.addField(i18n('commands.stats.fields.messages'), stats.messages, true); await message.channel.send(guild_embed); diff --git a/src/commands/survey.js b/src/commands/survey.js index a3345ea..2655954 100644 --- a/src/commands/survey.js +++ b/src/commands/survey.js @@ -1,6 +1,10 @@ const Command = require('../modules/commands/command'); // eslint-disable-next-line no-unused-vars -const { MessageAttachment, MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageAttachment, + MessageEmbed +} = require('discord.js'); const fsp = require('fs').promises; const { path } = require('../utils/fs'); const mustache = require('mustache'); @@ -9,21 +13,21 @@ module.exports = class SurveyCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.survey.name'), - description: i18n('commands.survey.description'), aliases: [ i18n('commands.survey.aliases.surveys') ], - process_args: false, args: [ { - name: i18n('commands.survey.args.survey.name'), description: i18n('commands.survey.args.survey.description'), example: i18n('commands.survey.args.survey.example'), - required: false, + name: i18n('commands.survey.args.survey.name'), + required: false } ], + description: i18n('commands.survey.description'), + internal: true, + name: i18n('commands.survey.name'), + process_args: false, staff_only: true }); } @@ -39,49 +43,41 @@ module.exports = class SurveyCommand extends Command { const survey = await this.client.db.models.Survey.findOne({ where: { - name: args, - guild: message.guild.id + guild: message.guild.id, + name: args } }); if (survey) { - const { rows: responses, count } = await this.client.db.models.SurveyResponse.findAndCountAll({ - where: { - survey: survey.id - } - }); + const { + rows: responses, count + } = await this.client.db.models.SurveyResponse.findAndCountAll({ where: { survey: survey.id } }); const users = new Set(); for (const i in responses) { - const ticket = await this.client.db.models.Ticket.findOne({ - where: { - id: responses[i].ticket - } - }); + const ticket = await this.client.db.models.Ticket.findOne({ where: { id: responses[i].ticket } }); users.add(ticket.creator); const answers = responses[i].answers.map(a => this.client.cryptr.decrypt(a)); answers.unshift(ticket.number); responses[i] = answers; } - let template = await fsp.readFile(path('./src/commands/extra/survey.template.html'), { - encoding: 'utf8' - }); + let template = await fsp.readFile(path('./src/commands/extra/survey.template.html'), { encoding: 'utf8' }); template = template.replace(/[\r\n\t]/g, ''); survey.questions.unshift('Ticket #'); const html = mustache.render(template, { - survey: survey.name.charAt(0).toUpperCase() + survey.name.slice(1), + columns: survey.questions, count: { responses: count, users: users.size }, - columns: survey.questions, - responses + responses, + survey: survey.name.charAt(0).toUpperCase() + survey.name.slice(1) }); const attachment = new MessageAttachment( @@ -89,15 +85,9 @@ module.exports = class SurveyCommand extends Command { `${survey.name}.html` ); - return await message.channel.send({ - files: [attachment] - }); + return await message.channel.send({ files: [attachment] }); } else { - const surveys = await this.client.db.models.Survey.findAll({ - where: { - guild: message.guild.id - } - }); + const surveys = await this.client.db.models.Survey.findAll({ where: { guild: message.guild.id } }); const list = surveys.map(s => `❯ **\`${s.name}\`**`); return await message.channel.send( diff --git a/src/commands/tag.js b/src/commands/tag.js index 9bafeae..2d3423e 100644 --- a/src/commands/tag.js +++ b/src/commands/tag.js @@ -1,6 +1,8 @@ const Command = require('../modules/commands/command'); -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); const { parseArgsStringToArgv: argv } = require('string-argv'); const parseArgs = require('command-line-args'); @@ -8,41 +10,37 @@ module.exports = class TagCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.tag.name'), - description: i18n('commands.tag.description'), aliases: [ i18n('commands.tag.aliases.faq'), i18n('commands.tag.aliases.t'), - i18n('commands.tag.aliases.tags'), + i18n('commands.tag.aliases.tags') ], - process_args: false, args: [ { - name: i18n('commands.tag.args.tag.name'), description: i18n('commands.tag.args.command.description'), example: i18n('commands.tag.args.tag.example'), - required: false, + name: i18n('commands.tag.args.tag.name'), + required: false } ], + description: i18n('commands.tag.description'), + internal: true, + name: i18n('commands.tag.name'), + process_args: false, staff_only: true }); } /** - * @param {Message} message - * @param {string} args + * @param {Message} message + * @param {string} args * @returns {Promise} */ async execute(message, args) { const settings = await message.guild.getSettings(); const i18n = this.client.i18n.getLocale(settings.locale); - const t_row = await this.client.db.models.Ticket.findOne({ - where: { - id: message.channel.id - } - }); + const t_row = await this.client.db.models.Ticket.findOne({ where: { id: message.channel.id } }); args = args.split(/\s/g); // convert to an array const tag_name = args.shift(); // shift the first element @@ -63,14 +61,12 @@ module.exports = class TagCommand extends Command { ); } - let expected = placeholders + const expected = placeholders .filter(p => p.startsWith(':')) - .map(p => { - return { - name: p.substr(1, p.length), - type: String, - }; - }); + .map(p => ({ + name: p.substr(1, p.length), + type: String + })); if (expected.length >= 1) { try { @@ -107,7 +103,7 @@ module.exports = class TagCommand extends Command { } // note that this regex is slightly different to the other - const text = tag.replace(/(? this.client.i18n.resolve(args, $1)); + const text = tag.replace(/(? this.client.i18n.resolve(args, $1)); return await message.channel.send( new MessageEmbed() .setColor(settings.colour) diff --git a/src/commands/topic.js b/src/commands/topic.js index 403b3d9..c3250c3 100644 --- a/src/commands/topic.js +++ b/src/commands/topic.js @@ -1,24 +1,26 @@ const Command = require('../modules/commands/command'); -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); module.exports = class TopicCommand extends Command { constructor(client) { const i18n = client.i18n.getLocale(client.config.locale); super(client, { - internal: true, - name: i18n('commands.topic.name'), - description: i18n('commands.topic.description'), aliases: [], - process_args: false, args: [ { - name: i18n('commands.topic.args.new_topic.name'), description: i18n('commands.topic.args.new_topic.description'), example: i18n('commands.topic.args.new_topic.example'), - required: true, + name: i18n('commands.topic.args.new_topic.name'), + required: true } - ] + ], + description: i18n('commands.topic.description'), + internal: true, + name: i18n('commands.topic.name'), + process_args: false }); } @@ -31,11 +33,7 @@ module.exports = class TopicCommand extends Command { const settings = await message.guild.getSettings(); const i18n = this.client.i18n.getLocale(settings.locale); - const t_row = await this.client.db.models.Ticket.findOne({ - where: { - id: message.channel.id - } - }); + const t_row = await this.client.db.models.Ticket.findOne({ where: { id: message.channel.id } }); if (!t_row) { return await message.channel.send( @@ -47,18 +45,12 @@ module.exports = class TopicCommand extends Command { ); } - await t_row.update({ - topic: this.client.cryptr.encrypt(args) - }); + await t_row.update({ topic: this.client.cryptr.encrypt(args) }); const member = await message.guild.members.fetch(t_row.creator); /* await */message.channel.setTopic(`${member} | ${args}`, { reason: 'User updated ticket topic' }); - const cat_row = await this.client.db.models.Category.findOne({ - where: { - id: t_row.category - } - }); + const cat_row = await this.client.db.models.Category.findOne({ where: { id: t_row.category } }); const description = cat_row.opening_message .replace(/{+\s?(user)?name\s?}+/gi, member.displayName) .replace(/{+\s?(tag|ping|mention)?\s?}+/gi, member.user.toString()); diff --git a/src/database/dialects.js b/src/database/dialects.js index 05a4353..1cd0b34 100644 --- a/src/database/dialects.js +++ b/src/database/dialects.js @@ -1,42 +1,42 @@ module.exports = { - sqlite: { - name: 'SQLite', - dialect: 'sqlite', - packages: ['sqlite3'], - }, - mysql: { - name: 'MySQL', - dialect: 'mysql', - packages: ['mysql2'] - }, maria: { - name: 'MariaDB', dialect: 'mariadb', + name: 'MariaDB', package: ['mariadb'] }, mariadb: { - name: 'MariaDB', dialect: 'mariadb', + name: 'MariaDB', package: ['mariadb'] }, + microsoft: { + dialect: 'mssql', + name: 'Microsoft SQL', + packages: ['tedious'] + }, + mysql: { + dialect: 'mysql', + name: 'MySQL', + packages: ['mysql2'] + }, postgre: { // this is wrong - name: 'PostgreSQL', dialect: 'postgres', + name: 'PostgreSQL', packages: ['pg', 'pg-hstore'] }, postgres: { - name: 'PostgreSQL', dialect: 'postgres', + name: 'PostgreSQL', packages: ['pg', 'pg-hstore'] }, postgresql: { - name: 'PostgreSQL', dialect: 'postgres', + name: 'PostgreSQL', packages: ['pg', 'pg-hstore'] }, - microsoft: { - name: 'Microsoft SQL', - dialect: 'mssql', - packages: ['tedious'] - }, + sqlite: { + dialect: 'sqlite', + name: 'SQLite', + packages: ['sqlite3'] + } }; \ No newline at end of file diff --git a/src/database/index.js b/src/database/index.js index b0deb11..8082277 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -3,7 +3,7 @@ const fs = require('fs'); const { path } = require('../utils/fs'); const types = require('./dialects'); -module.exports = async (client) => { +module.exports = async client => { const { DB_TYPE, @@ -36,8 +36,8 @@ module.exports = async (client) => { client.log.info('Using SQLite storage'); sequelize = new Sequelize({ dialect: types[type].dialect, - storage: path('./user/database.sqlite'), - logging: text => client.log.debug(text) + logging: text => client.log.debug(text), + storage: path('./user/database.sqlite') }); client.log.warn('SQLite is not sufficient for a production environment if you want to use ticket archives. You should disable "log_messages" in your servers\' settings or use a different database.'); } else { @@ -45,8 +45,8 @@ module.exports = async (client) => { sequelize = new Sequelize(DB_NAME, DB_USER, DB_PASS, { dialect: types[type].dialect, host: DB_HOST, - port: DB_PORT, - logging: text => client.log.debug(text) + logging: text => client.log.debug(text), + port: DB_PORT }); } @@ -66,11 +66,7 @@ module.exports = async (client) => { require(`./models/${model}`)(client, sequelize); } - sequelize.sync({ - alter: { - drop: false - } - }); + sequelize.sync({ alter: { drop: false } }); return sequelize; }; \ No newline at end of file diff --git a/src/database/models/category.model.js b/src/database/models/category.model.js index 1fb4784..fcae59e 100644 --- a/src/database/models/category.model.js +++ b/src/database/models/category.model.js @@ -2,67 +2,65 @@ const { DataTypes } = require('sequelize'); module.exports = ({ config }, sequelize) => { const { DB_TABLE_PREFIX } = process.env; sequelize.define('Category', { - id: { - type: DataTypes.CHAR(19), - primaryKey: true, - allowNull: false, - }, claiming: { - type: DataTypes.BOOLEAN, defaultValue: false, + type: DataTypes.BOOLEAN }, guild: { - type: DataTypes.CHAR(19), allowNull: false, references: { - model: DB_TABLE_PREFIX + 'guilds', - key: 'id' + key: 'id', + model: DB_TABLE_PREFIX + 'guilds' }, + type: DataTypes.CHAR(19), unique: 'name-guild' }, + id: { + allowNull: false, + primaryKey: true, + type: DataTypes.CHAR(19) + }, image: { - type: DataTypes.STRING, allowNull: true, + type: DataTypes.STRING }, max_per_member: { - type: DataTypes.INTEGER, - defaultValue: 1 + defaultValue: 1, + type: DataTypes.INTEGER }, name: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, unique: 'name-guild' }, name_format: { - type: DataTypes.STRING, allowNull: false, - defaultValue: config.defaults.name_format + defaultValue: config.defaults.name_format, + type: DataTypes.STRING }, opening_message: { - type: DataTypes.STRING, defaultValue: config.defaults.opening_message, + type: DataTypes.STRING }, opening_questions: { - type: DataTypes.JSON, allowNull: true, + type: DataTypes.JSON }, ping: { - type: DataTypes.JSON, defaultValue: [], + type: DataTypes.JSON }, require_topic: { - type: DataTypes.BOOLEAN, defaultValue: false, + type: DataTypes.BOOLEAN }, roles: { - type: DataTypes.JSON, allowNull: false, + type: DataTypes.JSON }, survey: { - type: DataTypes.STRING, allowNull: true, + type: DataTypes.STRING } - }, { - tableName: DB_TABLE_PREFIX + 'categories' - }); + }, { tableName: DB_TABLE_PREFIX + 'categories' }); }; \ No newline at end of file diff --git a/src/database/models/channel_entity.model.js b/src/database/models/channel_entity.model.js index b795b60..d0a403d 100644 --- a/src/database/models/channel_entity.model.js +++ b/src/database/models/channel_entity.model.js @@ -1,23 +1,21 @@ const { DataTypes } = require('sequelize'); -module.exports = (client, sequelize) => { +module.exports = (_client, sequelize) => { const { DB_TABLE_PREFIX } = process.env; sequelize.define('ChannelEntity', { channel: { - type: DataTypes.CHAR(19), allowNull: false, + type: DataTypes.CHAR(19), unique: 'channel-ticket' }, name: DataTypes.TEXT, ticket: { - type: DataTypes.CHAR(19), allowNull: false, - unique: 'channel-ticket', references: { - model: DB_TABLE_PREFIX + 'tickets', - key: 'id' + key: 'id', + model: DB_TABLE_PREFIX + 'tickets' }, - }, - }, { - tableName: DB_TABLE_PREFIX + 'channel_entities' - }); + type: DataTypes.CHAR(19), + unique: 'channel-ticket' + } + }, { tableName: DB_TABLE_PREFIX + 'channel_entities' }); }; \ No newline at end of file diff --git a/src/database/models/guild.model.js b/src/database/models/guild.model.js index 5792378..2582bee 100644 --- a/src/database/models/guild.model.js +++ b/src/database/models/guild.model.js @@ -2,48 +2,47 @@ const { DataTypes } = require('sequelize'); module.exports = ({ config }, sequelize) => { const { DB_TABLE_PREFIX } = process.env; sequelize.define('Guild', { - id: { - type: DataTypes.CHAR(19), - primaryKey: true, - allowNull: false, - }, + blacklist: { - type: DataTypes.JSON, defaultValue: [], + type: DataTypes.JSON }, colour: { - type: DataTypes.STRING, - defaultValue: config.defaults.colour + defaultValue: config.defaults.colour, + type: DataTypes.STRING }, command_prefix: { - type: DataTypes.STRING, - defaultValue: config.defaults.command_prefix + defaultValue: config.defaults.command_prefix, + type: DataTypes.STRING }, error_colour: { - type: DataTypes.STRING, - defaultValue: 'RED' + defaultValue: 'RED', + type: DataTypes.STRING }, footer: { - type: DataTypes.STRING, - defaultValue: 'Discord Tickets by eartharoid' + defaultValue: 'Discord Tickets by eartharoid', + type: DataTypes.STRING + }, + id: { + allowNull: false, + primaryKey: true, + type: DataTypes.CHAR(19) }, locale: { - type: DataTypes.STRING, - defaultValue: config.locale + defaultValue: config.locale, + type: DataTypes.STRING }, log_messages: { - type: DataTypes.BOOLEAN, - defaultValue: config.defaults.log_messages + defaultValue: config.defaults.log_messages, + type: DataTypes.BOOLEAN }, success_colour: { - type: DataTypes.STRING, - defaultValue: 'GREEN' + defaultValue: 'GREEN', + type: DataTypes.STRING }, tags: { - type: DataTypes.JSON, - defaultValue: {} + defaultValue: {}, + type: DataTypes.JSON } - }, { - tableName: DB_TABLE_PREFIX + 'guilds' - }); + }, { tableName: DB_TABLE_PREFIX + 'guilds' }); }; \ No newline at end of file diff --git a/src/database/models/message.model.js b/src/database/models/message.model.js index 0dc2253..f10dbb2 100644 --- a/src/database/models/message.model.js +++ b/src/database/models/message.model.js @@ -1,37 +1,36 @@ const { DataTypes } = require('sequelize'); -module.exports = (client, sequelize) => { +module.exports = (_client, sequelize) => { const { DB_TABLE_PREFIX } = process.env; sequelize.define('Message', { - id: { - type: DataTypes.CHAR(19), - primaryKey: true, - allowNull: false, - }, + author: { - type: DataTypes.CHAR(19), allowNull: false, + type: DataTypes.CHAR(19) }, data: { - type: DataTypes.TEXT, allowNull: false, + type: DataTypes.TEXT }, deleted: { - type: DataTypes.BOOLEAN, defaultValue: false, + type: DataTypes.BOOLEAN }, edited: { - type: DataTypes.BOOLEAN, defaultValue: false, + type: DataTypes.BOOLEAN + }, + id: { + allowNull: false, + primaryKey: true, + type: DataTypes.CHAR(19) }, ticket: { - type: DataTypes.CHAR(19), allowNull: false, references: { - model: DB_TABLE_PREFIX + 'tickets', - key: 'id' + key: 'id', + model: DB_TABLE_PREFIX + 'tickets' }, - }, - }, { - tableName: DB_TABLE_PREFIX + 'messages' - }); + type: DataTypes.CHAR(19) + } + }, { tableName: DB_TABLE_PREFIX + 'messages' }); }; \ No newline at end of file diff --git a/src/database/models/panel.model.js b/src/database/models/panel.model.js index 870bd9a..87ba74b 100644 --- a/src/database/models/panel.model.js +++ b/src/database/models/panel.model.js @@ -3,26 +3,24 @@ module.exports = (client, sequelize) => { const { DB_TABLE_PREFIX } = process.env; sequelize.define('Panel', { categories: { - type: DataTypes.JSON, - allowNull: false + allowNull: false, + type: DataTypes.JSON }, channel: { - type: DataTypes.CHAR(19), - allowNull: false + allowNull: false, + type: DataTypes.CHAR(19) }, guild: { - type: DataTypes.CHAR(19), allowNull: false, references: { - model: DB_TABLE_PREFIX + 'guilds', - key: 'id' - } + key: 'id', + model: DB_TABLE_PREFIX + 'guilds' + }, + type: DataTypes.CHAR(19) }, message: { - type: DataTypes.CHAR(19), - allowNull: false + allowNull: false, + type: DataTypes.CHAR(19) } - }, { - tableName: DB_TABLE_PREFIX + 'panels' - }); + }, { tableName: DB_TABLE_PREFIX + 'panels' }); }; \ No newline at end of file diff --git a/src/database/models/role_entity.model.js b/src/database/models/role_entity.model.js index d0a9d7c..c6ea0e9 100644 --- a/src/database/models/role_entity.model.js +++ b/src/database/models/role_entity.model.js @@ -3,25 +3,23 @@ module.exports = (client, sequelize) => { const { DB_TABLE_PREFIX } = process.env; sequelize.define('RoleEntity', { colour: { - type: DataTypes.CHAR(6), defaultValue: '7289DA', + type: DataTypes.CHAR(6) }, name: DataTypes.TEXT, role: { - type: DataTypes.CHAR(19), allowNull: false, + type: DataTypes.CHAR(19), unique: 'role-ticket' }, ticket: { - type: DataTypes.CHAR(19), allowNull: false, - unique: 'role-ticket', references: { - model: DB_TABLE_PREFIX + 'tickets', - key: 'id' + key: 'id', + model: DB_TABLE_PREFIX + 'tickets' }, - }, - }, { - tableName: DB_TABLE_PREFIX + 'role_entities' - }); + type: DataTypes.CHAR(19), + unique: 'role-ticket' + } + }, { tableName: DB_TABLE_PREFIX + 'role_entities' }); }; \ No newline at end of file diff --git a/src/database/models/survey.model.js b/src/database/models/survey.model.js index 5e9fa53..4292930 100644 --- a/src/database/models/survey.model.js +++ b/src/database/models/survey.model.js @@ -3,24 +3,22 @@ module.exports = (client, sequelize) => { const { DB_TABLE_PREFIX } = process.env; sequelize.define('Survey', { guild: { - type: DataTypes.CHAR(19), allowNull: false, references: { - model: DB_TABLE_PREFIX + 'guilds', - key: 'id' + key: 'id', + model: DB_TABLE_PREFIX + 'guilds' }, + type: DataTypes.CHAR(19), unique: 'name-guild' }, name: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, unique: 'name-guild' }, questions: { - type: DataTypes.JSON, allowNull: true, - }, - }, { - tableName: DB_TABLE_PREFIX + 'surveys' - }); + type: DataTypes.JSON + } + }, { tableName: DB_TABLE_PREFIX + 'surveys' }); }; \ No newline at end of file diff --git a/src/database/models/survey_response.model.js b/src/database/models/survey_response.model.js index b0ed174..062ff80 100644 --- a/src/database/models/survey_response.model.js +++ b/src/database/models/survey_response.model.js @@ -3,28 +3,26 @@ module.exports = (client, sequelize) => { const { DB_TABLE_PREFIX } = process.env; sequelize.define('SurveyResponse', { answers: { - type: DataTypes.JSON, allowNull: true, + type: DataTypes.JSON }, survey: { - type: DataTypes.INTEGER, allowNull: false, - unique: 'survey-ticket', references: { - model: DB_TABLE_PREFIX + 'surveys', - key: 'id' + key: 'id', + model: DB_TABLE_PREFIX + 'surveys' }, + type: DataTypes.INTEGER, + unique: 'survey-ticket' }, ticket: { - type: DataTypes.CHAR(19), allowNull: false, - unique: 'survey-ticket', references: { - model: DB_TABLE_PREFIX + 'tickets', - key: 'id' + key: 'id', + model: DB_TABLE_PREFIX + 'tickets' }, - }, - }, { - tableName: DB_TABLE_PREFIX + 'survey_responses' - }); + type: DataTypes.CHAR(19), + unique: 'survey-ticket' + } + }, { tableName: DB_TABLE_PREFIX + 'survey_responses' }); }; \ No newline at end of file diff --git a/src/database/models/ticket.model.js b/src/database/models/ticket.model.js index a14b64b..ef0512e 100644 --- a/src/database/models/ticket.model.js +++ b/src/database/models/ticket.model.js @@ -1,75 +1,73 @@ const { DataTypes } = require('sequelize'); -module.exports = (client, sequelize) => { +module.exports = (_client, sequelize) => { const { DB_TABLE_PREFIX } = process.env; sequelize.define('Ticket', { - id: { - type: DataTypes.CHAR(19), - primaryKey: true, - allowNull: false, - }, category: { - type: DataTypes.CHAR(19), allowNull: false, references: { - model: DB_TABLE_PREFIX + 'categories', - key: 'id' + key: 'id', + model: DB_TABLE_PREFIX + 'categories' }, + type: DataTypes.CHAR(19) }, claimed_by: { - type: DataTypes.CHAR(19), allowNull: true, + type: DataTypes.CHAR(19) }, closed_by: { - type: DataTypes.CHAR(19), allowNull: true, + type: DataTypes.CHAR(19) }, closed_reason: { - type: DataTypes.STRING, allowNull: true, + type: DataTypes.STRING }, creator: { - type: DataTypes.CHAR(19), allowNull: false, + type: DataTypes.CHAR(19) }, first_response: { - type: DataTypes.DATE, allowNull: true, + type: DataTypes.DATE }, guild: { - type: DataTypes.CHAR(19), allowNull: false, references: { - model: DB_TABLE_PREFIX + 'guilds', - key: 'id' + key: 'id', + model: DB_TABLE_PREFIX + 'guilds' }, + type: DataTypes.CHAR(19), unique: 'number-guild' }, + id: { + allowNull: false, + primaryKey: true, + type: DataTypes.CHAR(19) + }, last_message: { - type: DataTypes.DATE, allowNull: true, + type: DataTypes.DATE }, number: { - type: DataTypes.INTEGER, allowNull: false, + type: DataTypes.INTEGER, unique: 'number-guild' }, open: { - type: DataTypes.BOOLEAN, - defaultValue: true + defaultValue: true, + type: DataTypes.BOOLEAN }, opening_message: { - type: DataTypes.CHAR(19), allowNull: true, + type: DataTypes.CHAR(19) }, pinned_messages: { - type: DataTypes.JSON, - defaultValue: [] + defaultValue: [], + type: DataTypes.JSON }, topic: { - type: DataTypes.TEXT, allowNull: true, - }, - }, { - tableName: DB_TABLE_PREFIX + 'tickets' - }); + type: DataTypes.TEXT + } + }, { tableName: DB_TABLE_PREFIX + 'tickets' }); }; \ No newline at end of file diff --git a/src/database/models/user_entity.model.js b/src/database/models/user_entity.model.js index 72c8962..0117ae6 100644 --- a/src/database/models/user_entity.model.js +++ b/src/database/models/user_entity.model.js @@ -6,30 +6,29 @@ module.exports = (client, sequelize) => { bot: DataTypes.BOOLEAN, discriminator: DataTypes.STRING, display_name: DataTypes.TEXT, - ticket: { - type: DataTypes.CHAR(19), + role: { allowNull: false, - unique: 'user-ticket', references: { - model: DB_TABLE_PREFIX + 'tickets', - key: 'id' + key: 'role', + model: DB_TABLE_PREFIX + 'role_entities' }, + type: DataTypes.CHAR(19) }, - user: { - type: DataTypes.CHAR(19), + ticket: { allowNull: false, + references: { + key: 'id', + model: DB_TABLE_PREFIX + 'tickets' + }, + type: DataTypes.CHAR(19), unique: 'user-ticket' }, - username: DataTypes.TEXT, - role: { - type: DataTypes.CHAR(19), + user: { allowNull: false, - references: { - model: DB_TABLE_PREFIX + 'role_entities', - key: 'role' - }, + type: DataTypes.CHAR(19), + unique: 'user-ticket' }, - }, { - tableName: DB_TABLE_PREFIX + 'user_entities' - }); + username: DataTypes.TEXT + + }, { tableName: DB_TABLE_PREFIX + 'user_entities' }); }; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 1b175a3..29b1d1e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,20 +1,21 @@ +/* eslint-disable no-console */ /** * Discord Tickets * Copyright (C) 2021 Isaac Saunders - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * @name @eartharoid/discord-tickets * @description An open-source Discord bot for ticket management * @copyright 2021 Isaac Saunders @@ -24,8 +25,7 @@ process.title = 'Discord Tickets'; const node_version = Number(process.versions.node.split('.')[0]); -if (node_version < 14) - return console.log(`\x07Error: Discord Tickets does not work on Node v${node_version}. Please upgrade to v14 or above.`); +if (node_version < 14) return console.log(`\x07Error: Discord Tickets does not work on Node v${node_version}. Please upgrade to v14 or above.`); const leeks = require('leeks.js'); const fs = require('fs'); @@ -55,9 +55,7 @@ if (!checkFile('./.env', './example.env')) { .randomBytes(24) .toString('hex'); - let data = fs.readFileSync(file, { - encoding: 'utf-8' - }); + let data = fs.readFileSync(file, { encoding: 'utf-8' }); data = data.replace(key, key + value); fs.writeFileSync(file, data); @@ -69,9 +67,7 @@ if (!checkFile('./.env', './example.env')) { process.exit(); } -require('dotenv').config({ - path: path('./.env') -}); +require('dotenv').config({ path: path('./.env') }); require('./banner')(); @@ -119,11 +115,9 @@ class Bot extends Client { 'REACTION' ], presence: selectPresence(), - ws: { - intents: Intents.NON_PRIVILEGED, - } + ws: { intents: Intents.NON_PRIVILEGED } }); - + (async () => { /** The global bot configuration */ this.config = require('../user/config'); @@ -144,9 +138,7 @@ class Bot extends Client { fs.readdirSync(path('./src/locales')) .filter(file => file.endsWith('.json')) .forEach(file => { - const data = fs.readFileSync(path(`./src/locales/${file}`), { - encoding: 'utf8' - }); + const data = fs.readFileSync(path(`./src/locales/${file}`), { encoding: 'utf8' }); const name = file.slice(0, file.length - 5); locales[name] = JSON.parse(data); }); @@ -161,9 +153,9 @@ class Bot extends Client { this.db = await require('./database')(this), // this.db.models.Ticket... this.setMaxListeners(this.config.max_listeners); // set the max listeners for each event - + require('./updater')(this); // check for updates - + const listeners = new ListenerLoader(this); listeners.load(); // load listeners @@ -191,17 +183,13 @@ class Bot extends Client { */ if (this.config.super_secret_setting) { // you can disable it if you really want const tickets = await this.db.models.Ticket.count(); - await fetch(`https://stats.discordtickets.app/client?id=${this.user.id}&tickets=${tickets}`, { - method: 'post', - }).catch(e => { + await fetch(`https://stats.discordtickets.app/client?id=${this.user.id}&tickets=${tickets}`, { method: 'post' }).catch(e => { this.log.warn('Failed to post tickets count to stats server (you can disable sending stats by setting "super_secret_setting" to false)'); this.log.debug(e); }); this.guilds.cache.forEach(async g => { const members = (await g.fetch()).approximateMemberCount; - await fetch(`https://stats.discordtickets.app/guild?id=${g.id}&members=${members}`, { - method: 'post', - }).catch(e => { + await fetch(`https://stats.discordtickets.app/guild?id=${g.id}&members=${members}`, { method: 'post' }).catch(e => { // don't spam a warning for each server this.log.debug(e); }); diff --git a/src/listeners/debug.js b/src/listeners/debug.js index fd81540..cf54593 100644 --- a/src/listeners/debug.js +++ b/src/listeners/debug.js @@ -2,9 +2,7 @@ const EventListener = require('../modules/listeners/listener'); module.exports = class DebugEventListener extends EventListener { constructor(client) { - super(client, { - event: 'debug' - }); + super(client, { event: 'debug' }); } async execute(data) { diff --git a/src/listeners/error.js b/src/listeners/error.js index 1309bf7..ddfe695 100644 --- a/src/listeners/error.js +++ b/src/listeners/error.js @@ -2,9 +2,7 @@ const EventListener = require('../modules/listeners/listener'); module.exports = class ErrorEventListener extends EventListener { constructor(client) { - super(client, { - event: 'error' - }); + super(client, { event: 'error' }); } async execute(error) { diff --git a/src/listeners/guildCreate.js b/src/listeners/guildCreate.js index df930d5..355ec00 100644 --- a/src/listeners/guildCreate.js +++ b/src/listeners/guildCreate.js @@ -2,9 +2,7 @@ const EventListener = require('../modules/listeners/listener'); module.exports = class GuildCreateEventListener extends EventListener { constructor(client) { - super(client, { - event: 'guildCreate' - }); + super(client, { event: 'guildCreate' }); } async execute(guild) { diff --git a/src/listeners/guildDelete.js b/src/listeners/guildDelete.js index f4d9bd9..f98544d 100644 --- a/src/listeners/guildDelete.js +++ b/src/listeners/guildDelete.js @@ -2,9 +2,7 @@ const EventListener = require('../modules/listeners/listener'); module.exports = class GuildDeleteEventListener extends EventListener { constructor(client) { - super(client, { - event: 'guildDelete' - }); + super(client, { event: 'guildDelete' }); } async execute(guild) { diff --git a/src/listeners/guildMemberRemove.js b/src/listeners/guildMemberRemove.js index 7de5c04..e698d3f 100644 --- a/src/listeners/guildMemberRemove.js +++ b/src/listeners/guildMemberRemove.js @@ -2,9 +2,7 @@ const EventListener = require('../modules/listeners/listener'); module.exports = class GuildMemberRemoveEventListener extends EventListener { constructor(client) { - super(client, { - event: 'guildMemberRemove' - }); + super(client, { event: 'guildMemberRemove' }); } async execute(member) { diff --git a/src/listeners/message.js b/src/listeners/message.js index 2f2973a..872085d 100644 --- a/src/listeners/message.js +++ b/src/listeners/message.js @@ -5,9 +5,7 @@ const { footer } = require('../utils/discord'); module.exports = class MessageEventListener extends EventListener { constructor(client) { - super(client, { - event: 'message' - }); + super(client, { event: 'message' }); } async execute(message) { @@ -16,11 +14,7 @@ module.exports = class MessageEventListener extends EventListener { const settings = await message.guild.getSettings(); const i18n = this.client.i18n.getLocale(settings.locale); - const t_row = await this.client.db.models.Ticket.findOne({ - where: { - id: message.channel.id - } - }); + const t_row = await this.client.db.models.Ticket.findOne({ where: { id: message.channel.id } }); if (t_row) { if (settings.log_messages && !message.system) this.client.tickets.archives.addMessage(message); // add the message to the archives (if it is in a ticket channel) @@ -33,22 +27,14 @@ module.exports = class MessageEventListener extends EventListener { } else { if (message.author.bot) return; - const p_row = await this.client.db.models.Panel.findOne({ - where: { - channel: message.channel.id - } - }); + const p_row = await this.client.db.models.Panel.findOne({ where: { channel: message.channel.id } }); if (p_row && typeof p_row.categories === 'string') { // handle reaction-less panel await message.delete(); - const cat_row = await this.client.db.models.Category.findOne({ - where: { - id: p_row.categories - } - }); + const cat_row = await this.client.db.models.Category.findOne({ where: { id: p_row.categories } }); const tickets = await this.client.db.models.Ticket.findAndCountAll({ where: { diff --git a/src/listeners/messageDelete.js b/src/listeners/messageDelete.js index d43b4bf..0bc1ff9 100644 --- a/src/listeners/messageDelete.js +++ b/src/listeners/messageDelete.js @@ -2,9 +2,7 @@ const EventListener = require('../modules/listeners/listener'); module.exports = class MessageDeleteEventListener extends EventListener { constructor(client) { - super(client, { - event: 'messageDelete' - }); + super(client, { event: 'messageDelete' }); } async execute(message) { diff --git a/src/listeners/messageReactionAdd.js b/src/listeners/messageReactionAdd.js index 6c02725..60e9720 100644 --- a/src/listeners/messageReactionAdd.js +++ b/src/listeners/messageReactionAdd.js @@ -5,9 +5,7 @@ const { footer } = require('../utils/discord'); module.exports = class MessageReactionAddEventListener extends EventListener { constructor(client) { - super(client, { - event: 'messageReactionAdd' - }); + super(client, { event: 'messageReactionAdd' }); } async execute(r, u) { @@ -49,34 +47,20 @@ module.exports = class MessageReactionAddEventListener extends EventListener { }); } - const t_row = await this.client.db.models.Ticket.findOne({ - where: { - id: channel.id - } - }); + const t_row = await this.client.db.models.Ticket.findOne({ where: { id: channel.id } }); if (t_row && t_row.opening_message === r.message.id) { if (r.emoji.name === '🙌' && await member.isStaff()) { // ticket claiming - await t_row.update({ - claimed_by: member.user.id - }); + await t_row.update({ claimed_by: member.user.id }); - await channel.updateOverwrite(member.user.id, { - VIEW_CHANNEL: true, - }, `Ticket claimed by ${member.user.tag}`); + await channel.updateOverwrite(member.user.id, { VIEW_CHANNEL: true }, `Ticket claimed by ${member.user.tag}`); - const cat_row = await this.client.db.models.Category.findOne({ - where: { - id: t_row.category - } - }); + const cat_row = await this.client.db.models.Category.findOne({ where: { id: t_row.category } }); for (const role of cat_row.roles) { - await channel.updateOverwrite(role, { - VIEW_CHANNEL: false, - }, `Ticket claimed by ${member.user.tag}`); + await channel.updateOverwrite(role, { VIEW_CHANNEL: false }, `Ticket claimed by ${member.user.tag}`); } this.client.log.info(`${member.user.tag} has claimed "${channel.name}" in "${guild.name}"`); @@ -93,11 +77,7 @@ module.exports = class MessageReactionAddEventListener extends EventListener { await r.users.remove(u.id); } } else { - const p_row = await this.client.db.models.Panel.findOne({ - where: { - message: r.message.id - } - }); + const p_row = await this.client.db.models.Panel.findOne({ where: { message: r.message.id } }); if (p_row && typeof p_row.categories !== 'string') { // panels @@ -106,11 +86,7 @@ module.exports = class MessageReactionAddEventListener extends EventListener { const category_id = p_row.categories[r.emoji.name]; if (!category_id) return; - const cat_row = await this.client.db.models.Category.findOne({ - where: { - id: category_id - } - }); + const cat_row = await this.client.db.models.Category.findOne({ where: { id: category_id } }); const tickets = await this.client.db.models.Ticket.findAndCountAll({ where: { diff --git a/src/listeners/messageReactionRemove.js b/src/listeners/messageReactionRemove.js index 159fe03..cb82f51 100644 --- a/src/listeners/messageReactionRemove.js +++ b/src/listeners/messageReactionRemove.js @@ -4,9 +4,7 @@ const { MessageEmbed } = require('discord.js'); module.exports = class MessageReactionRemoveEventListener extends EventListener { constructor(client) { - super(client, { - event: 'messageReactionRemove' - }); + super(client, { event: 'messageReactionRemove' }); } async execute(r, u) { @@ -38,34 +36,22 @@ module.exports = class MessageReactionRemoveEventListener extends EventListener const channel = r.message.channel; const member = await guild.members.fetch(u.id); - const t_row = await this.client.db.models.Ticket.findOne({ - where: { - id: channel.id - } - }); + const t_row = await this.client.db.models.Ticket.findOne({ where: { id: channel.id } }); if (t_row && t_row.opening_message === r.message.id) { if (r.emoji.name === '🙌' && await member.isStaff()) { // ticket claiming - await t_row.update({ - claimed_by: null - }); + await t_row.update({ claimed_by: null }); await channel.permissionOverwrites .get(member.user.id) ?.delete(`Ticket released by ${member.user.tag}`); - const cat_row = await this.client.db.models.Category.findOne({ - where: { - id: t_row.category - } - }); + const cat_row = await this.client.db.models.Category.findOne({ where: { id: t_row.category } }); for (const role of cat_row.roles) { - await channel.updateOverwrite(role, { - VIEW_CHANNEL: true, - }, `Ticket released by ${member.user.tag}`); + await channel.updateOverwrite(role, { VIEW_CHANNEL: true }, `Ticket released by ${member.user.tag}`); } this.client.log.info(`${member.user.tag} has released "${channel.name}" in "${guild.name}"`); diff --git a/src/listeners/messageUpdate.js b/src/listeners/messageUpdate.js index f501f49..8ab7b18 100644 --- a/src/listeners/messageUpdate.js +++ b/src/listeners/messageUpdate.js @@ -2,9 +2,7 @@ const EventListener = require('../modules/listeners/listener'); module.exports = class MessageUpdateEventListener extends EventListener { constructor(client) { - super(client, { - event: 'messageUpdate' - }); + super(client, { event: 'messageUpdate' }); } async execute(oldm, newm) { diff --git a/src/listeners/rateLimit.js b/src/listeners/rateLimit.js index 7722418..29053e0 100644 --- a/src/listeners/rateLimit.js +++ b/src/listeners/rateLimit.js @@ -2,9 +2,7 @@ const EventListener = require('../modules/listeners/listener'); module.exports = class RateLimitEventListener extends EventListener { constructor(client) { - super(client, { - event: 'rateLimit' - }); + super(client, { event: 'rateLimit' }); } async execute(limit) { diff --git a/src/listeners/warn.js b/src/listeners/warn.js index e3e7854..f1020e9 100644 --- a/src/listeners/warn.js +++ b/src/listeners/warn.js @@ -2,9 +2,7 @@ const EventListener = require('../modules/listeners/listener'); module.exports = class WarnEventListener extends EventListener { constructor(client) { - super(client, { - event: 'warn' - }); + super(client, { event: 'warn' }); } async execute(warning) { diff --git a/src/logger.js b/src/logger.js index be31221..2fb156e 100644 --- a/src/logger.js +++ b/src/logger.js @@ -2,60 +2,38 @@ const { path } = require('./utils/fs'); const config = require('../user/config'); const Logger = require('leekslazylogger-fastify'); module.exports = new Logger({ - name: 'Discord Tickets by eartharoid', debug: config.debug, - logToFile: config.logs.enabled, - splitFile: config.logs.split, directory: path('./logs/'), keepFor: config.logs.keep_for, - timestamp: 'YYYY-MM-DD HH:mm:ss', levels: { - _logger: { - format: '&f&!7{timestamp}&r [LOGGER] {text}' - }, - basic: { - format: '&f&!7{timestamp} {text}' - }, - console: { - format: '&f&!7{timestamp} [INFO] {text}' - }, - info: { - format: '&f&!7{timestamp}&r &3[INFO] &b{text}' - }, - success: { - format: '&f&!7{timestamp}&r &2[SUCCESS] &a{text}' - }, - debug: { - format: '&f&!7{timestamp}&r &1[DEBUG] &9{text}' - }, - notice: { - format: '&f&!7{timestamp}&r &0&!6[NOTICE] {text}' - }, - warn: { - format: '&f&!7{timestamp}&r &6[WARN] &e{text}' - }, - error: { - format: '&f&!7{timestamp}&r &4[ERROR] &c{text}' - }, + _logger: { format: '&f&!7{timestamp}&r [LOGGER] {text}' }, + basic: { format: '&f&!7{timestamp} {text}' }, commands: { - type: 'info', - format: '&f&!7{timestamp}&r &3[INFO] &d(COMMANDS)&r {text}' - }, - plugins: { - type: 'info', - format: '&f&!7{timestamp}&r &3[INFO] &d(PLUGINS)&r {text}' - }, - tickets: { - type: 'info', - format: '&f&!7{timestamp}&r &3[INFO] &d(TICKETS)&r {text}' + format: '&f&!7{timestamp}&r &3[INFO] &d(COMMANDS)&r {text}', + type: 'info' }, + console: { format: '&f&!7{timestamp} [INFO] {text}' }, + debug: { format: '&f&!7{timestamp}&r &1[DEBUG] &9{text}' }, + error: { format: '&f&!7{timestamp}&r &4[ERROR] &c{text}' }, http: { - type: 'info', - format: '&f&!7{timestamp}&r &3[INFO] &d(HTTP)&r {text}' + format: '&f&!7{timestamp}&r &3[INFO] &d(HTTP)&r {text}', + type: 'info' }, + info: { format: '&f&!7{timestamp}&r &3[INFO] &b{text}' }, + notice: { format: '&f&!7{timestamp}&r &0&!6[NOTICE] {text}' }, + plugins: { + format: '&f&!7{timestamp}&r &3[INFO] &d(PLUGINS)&r {text}', + type: 'info' + }, + success: { format: '&f&!7{timestamp}&r &2[SUCCESS] &a{text}' }, + warn: { format: '&f&!7{timestamp}&r &6[WARN] &e{text}' }, ws: { - type: 'info', - format: '&f&!7{timestamp}&r &3[INFO] &d(WS)&r {text}' + format: '&f&!7{timestamp}&r &3[INFO] &d(WS)&r {text}', + type: 'info' } - } + }, + logToFile: config.logs.enabled, + name: 'Discord Tickets by eartharoid', + splitFile: config.logs.split, + timestamp: 'YYYY-MM-DD HH:mm:ss' }); \ No newline at end of file diff --git a/src/modules/commands/command.js b/src/modules/commands/command.js index 0dc118a..9403341 100644 --- a/src/modules/commands/command.js +++ b/src/modules/commands/command.js @@ -1,12 +1,14 @@ -// eslint-disable-next-line no-unused-vars -const { MessageEmbed, Message } = require('discord.js'); +const { + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); /** * A command */ module.exports = class Command { /** - * + * * @typedef CommandArgument * @property {string} name - The argument's name * @property {string} description - The argument's description @@ -37,7 +39,7 @@ module.exports = class Command { } /** - * The name of the command + * The name of the command * @type {string} */ this.name = data.name; @@ -53,7 +55,7 @@ module.exports = class Command { /** * The command description * @type {string} - */ + */ this.description = data.description; /** @@ -61,12 +63,12 @@ module.exports = class Command { * @type {boolean} * @default false */ - this.staff_only = data.staff_only === true ? true : false; + this.staff_only = data.staff_only === true; /** * Array of permissions needed for a user to use this command * @type {string[]} - */ + */ this.permissions = data.permissions ?? []; /** @@ -74,9 +76,9 @@ module.exports = class Command { * @type {boolean} * @default false */ - this.process_args = data.process_args === true ? true : false; + this.process_args = data.process_args === true; - /** + /** * The command options * @type {CommandArgument[]} */ @@ -86,7 +88,7 @@ module.exports = class Command { * True if command is internal, false if it is from a plugin * @type {boolean} */ - this.internal = data.internal === true ? true : false; + this.internal = data.internal === true; if (!this.internal) { /** @@ -155,7 +157,7 @@ module.exports = class Command { this.args.forEach(arg => addArgs(embed, arg)); return await channel.send(embed); - + } }; \ No newline at end of file diff --git a/src/modules/commands/manager.js b/src/modules/commands/manager.js index cb07a29..78b15fa 100644 --- a/src/modules/commands/manager.js +++ b/src/modules/commands/manager.js @@ -1,5 +1,10 @@ -// eslint-disable-next-line no-unused-vars -const { Collection, Client, Message, MessageEmbed } = require('discord.js'); + +const { + Client, // eslint-disable-line no-unused-vars + Collection, + Message, // eslint-disable-line no-unused-vars + MessageEmbed +} = require('discord.js'); const fs = require('fs'); const { path } = require('../../utils/fs'); @@ -13,7 +18,7 @@ const parseArgs = require('command-line-args'); module.exports = class CommandManager { /** * Create a CommandManager instance - * @param {import('../..').Bot} client + * @param {import('../..').Bot} client */ constructor(client) { /** The Discord Client */ @@ -49,15 +54,13 @@ module.exports = class CommandManager { if (is_internal) { const plugin = this.client.plugins.plugins.find(p => p.commands.includes(cmd.name)); - if (plugin) - this.client.log.commands(`The "${plugin.name}" plugin has overridden the internal "${cmd.name}" command`); - else - this.client.log.commands(`An unknown plugin has overridden the internal "${cmd.name}" command`); + if (plugin) this.client.log.commands(`The "${plugin.name}" plugin has overridden the internal "${cmd.name}" command`); + else this.client.log.commands(`An unknown plugin has overridden the internal "${cmd.name}" command`); if(cmd.internal) return; - } - else if (exists) + } else if (exists) { throw new Error(`A non-internal command with the name "${cmd.name}" already exists`); - + } + this.commands.set(cmd.name, cmd); this.client.log.commands(`Loaded "${cmd.name}" command`); } @@ -114,7 +117,7 @@ module.exports = class CommandManager { 'MANAGE_CHANNELS', 'MANAGE_MESSAGES', 'READ_MESSAGE_HISTORY', - 'SEND_MESSAGES', + 'SEND_MESSAGES' ]; if (!bot_permissions.has(required_bot_permissions)) { @@ -182,10 +185,10 @@ module.exports = class CommandManager { return await cmd.sendUsage(message.channel, cmd_name); } } - + try { this.client.log.commands(`Executing "${cmd.name}" command (invoked by ${message.author.tag})`); - await cmd.execute(message, args); // execute the command + await cmd.execute(message, args); // execute the command } catch (e) { this.client.log.warn(`An error occurred whilst executing the ${cmd.name} command`); this.client.log.error(e); diff --git a/src/modules/listeners/listener.js b/src/modules/listeners/listener.js index a596099..f7202d6 100644 --- a/src/modules/listeners/listener.js +++ b/src/modules/listeners/listener.js @@ -1,9 +1,9 @@ module.exports = class EventListener { /** - * - * @param {import("../..").Bot} client - * @param {*} data + * + * @param {import("../..").Bot} client + * @param {*} data */ constructor(client, data) { this.client = client; diff --git a/src/modules/listeners/loader.js b/src/modules/listeners/loader.js index 2c1cd9c..b0c601c 100644 --- a/src/modules/listeners/loader.js +++ b/src/modules/listeners/loader.js @@ -7,7 +7,7 @@ const { path } = require('../../utils/fs'); module.exports = class ListenerLoader { /** * Create a ListenerLoader instance - * @param {import('../..').Bot} client + * @param {import('../..').Bot} client */ constructor(client) { /** The Discord Client */ @@ -23,10 +23,8 @@ module.exports = class ListenerLoader { file = require(`../../listeners/${file}`); const listener = new file(this.client); const 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)); + 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); diff --git a/src/modules/plugins/manager.js b/src/modules/plugins/manager.js index 9e938e6..6f74a49 100644 --- a/src/modules/plugins/manager.js +++ b/src/modules/plugins/manager.js @@ -9,12 +9,12 @@ const Plugin = require('./plugin'); module.exports = class PluginManager { /** * Create a PluginManager instance - * @param {import('../..').Bot} client + * @param {import('../..').Bot} client */ constructor(client) { /** The Discord Client */ this.client = client; - + /** * A discord.js Collection (Map) of loaded plugins * @type {Collection} @@ -29,8 +29,7 @@ module.exports = class PluginManager { } handleError(id) { - if (!this.official.includes(id)) - this.client.log.notice(`"${id}" is NOT an official plugin, please do not ask for help with it in the Discord Tickets support server, seek help from the plugin author instead.`); + if (!this.official.includes(id)) this.client.log.notice(`"${id}" is NOT an official plugin, please do not ask for help with it in the Discord Tickets support server, seek help from the plugin author instead.`); } /** @@ -56,17 +55,17 @@ module.exports = class PluginManager { } const about = { - id, - version, author, - description + description, + id, + version }; try { plugin = new (plugin(Plugin))(this.client, about); this.plugins.set(id, plugin); this.client.log.plugins(`Loading "${plugin.name}" v${version} by ${author}`); - plugin.preload(); + plugin.preload(); } catch (e) { this.handleError(id); this.client.log.warn(`An error occurred whilst loading the "${id}" plugin`); diff --git a/src/modules/plugins/plugin.js b/src/modules/plugins/plugin.js index c39f62c..d8df69f 100644 --- a/src/modules/plugins/plugin.js +++ b/src/modules/plugins/plugin.js @@ -40,31 +40,31 @@ module.exports = class Plugin { */ this.name = options.name ?? id; - /** + /** * An array of commands from this plugin * @type {string[]} */ this.commands = options.commands; - /** + /** * The unique ID of the plugin (NPM package name) * @type {string} */ this.id = id; - /** + /** * The version of the plugin (NPM package version) * @type {string} */ this.version = version; - /** + /** * The plugin author's name (NPM package author) * @type {(undefined|string)} */ this.author = author; - /** + /** * The plugin description (NPM package description) * @type {string} */ diff --git a/src/modules/structures.js b/src/modules/structures.js index 5789881..ac5167f 100644 --- a/src/modules/structures.js +++ b/src/modules/structures.js @@ -5,6 +5,5 @@ module.exports = () => { const files = fs.readdirSync(path('./src/structures')) .filter(file => file.endsWith('.js')); - for (const file of files) - require(`../structures/${file}`); + for (const file of files) require(`../structures/${file}`); }; \ No newline at end of file diff --git a/src/modules/tickets/archives.js b/src/modules/tickets/archives.js index 9567a4b..8278c37 100644 --- a/src/modules/tickets/archives.js +++ b/src/modules/tickets/archives.js @@ -20,26 +20,22 @@ module.exports = class TicketArchives { try { // await this.client.db.transaction(async t => { const t_row = await this.client.db.models.Ticket.findOne({ - where: { - id: message.channel.id - }, + where: { id: message.channel.id } /* transaction: t */ }); if (t_row) { await this.client.db.models.Message.create({ - id: message.id, - ticket: t_row.id, author: message.author.id, + createdAt: new Date(message.createdTimestamp), data: this.encrypt(JSON.stringify({ + attachments: [...message.attachments.values()], content: message.content, - embeds: message.embeds.map(embed => { - return { embed }; - }), - attachments: [...message.attachments.values()] + embeds: message.embeds.map(embed => ({ embed })) })), - createdAt: new Date(message.createdTimestamp) - }, /* { transaction: t } */); + id: message.id, + ticket: t_row.id + } /* { transaction: t } */); await this.updateEntities(message); } @@ -54,19 +50,15 @@ module.exports = class TicketArchives { try { // await this.client.db.transaction(async t => { const m_row = await this.client.db.models.Message.findOne({ - where: { - id: message.id - }, + where: { id: message.id } /* transaction: t */ }); if (m_row) { m_row.data = this.encrypt(JSON.stringify({ + attachments: [...message.attachments.values()], content: message.content, - embeds: message.embeds.map(embed => { - return { embed }; - }), - attachments: [...message.attachments.values()] + embeds: message.embeds.map(embed => ({ embed })) })); if (message.editedTimestamp) { @@ -87,9 +79,7 @@ module.exports = class TicketArchives { try { // await this.client.db.transaction(async t => { const msg = await this.client.db.models.Message.findOne({ - where: { - id: message.id - }, + where: { id: message.id } /* transaction: t */ }); @@ -130,27 +120,27 @@ module.exports = class TicketArchives { try { // await this.client.db.transaction(async t => { const u_model_data = { - user: member.user.id, - ticket: ticket_id + ticket: ticket_id, + user: member.user.id }; const [u_row] = await this.client.db.models.UserEntity.findOrCreate({ - where: u_model_data, defaults: { ...u_model_data, role: member.roles.highest.id }, + where: u_model_data /* transaction: t */ }); await u_row.update({ avatar: member.user.avatar, - username: this.encrypt(member.user.username), + bot: member.user.bot, discriminator: member.user.discriminator, display_name: this.encrypt(member.displayName), role: member.roles.highest.id, - bot: member.user.bot - }, /* { transaction: t } */); + username: this.encrypt(member.user.username) + } /* { transaction: t } */); return u_row; // }); @@ -168,14 +158,12 @@ module.exports = class TicketArchives { ticket: ticket_id }; const [c_row] = await this.client.db.models.ChannelEntity.findOrCreate({ - where: c_model_data, defaults: c_model_data, + where: c_model_data /* transaction: t */ }); - await c_row.update({ - name: this.encrypt(channel.name) - }, /* { transaction: t } */); + await c_row.update({ name: this.encrypt(channel.name) } /* { transaction: t } */); return c_row; // }); @@ -193,15 +181,15 @@ module.exports = class TicketArchives { ticket: ticket_id }; const [r_row] = await this.client.db.models.RoleEntity.findOrCreate({ - where: r_model_data, defaults: r_model_data, + where: r_model_data /* transaction: t */ }); await r_row.update({ - name: this.encrypt(role.name), - colour: role.color === 0 ? '7289DA' : int2hex(role.color) // 7289DA = 7506394 - }, /* { transaction: t } */); + colour: role.color === 0 ? '7289DA' : int2hex(role.color), // 7289DA = 7506394 + name: this.encrypt(role.name) + } /* { transaction: t } */); return r_row; // }); diff --git a/src/modules/tickets/manager.js b/src/modules/tickets/manager.js index 851ebc8..bb065a5 100644 --- a/src/modules/tickets/manager.js +++ b/src/modules/tickets/manager.js @@ -1,3 +1,4 @@ +/* eslint-disable max-lines */ const EventEmitter = require('events'); const TicketArchives = require('./archives'); const { MessageEmbed } = require('discord.js'); @@ -25,30 +26,20 @@ module.exports = class TicketManager extends EventEmitter { * @param {string} guild_id - ID of the guild to create the ticket in * @param {string} creator_id - ID of the ticket creator (user) * @param {string} category_id - ID of the ticket category - * @param {string} [topic] - The ticket topic + * @param {string} [topic] - The ticket topic */ async create(guild_id, creator_id, category_id, topic) { if (!topic) topic = ''; - const cat_row = await this.client.db.models.Category.findOne({ - where: { - id: category_id - } - }); + const cat_row = await this.client.db.models.Category.findOne({ where: { id: category_id } }); + + if (!cat_row) throw new Error('Ticket category does not exist'); - if (!cat_row) - throw new Error('Ticket category does not exist'); - const cat_channel = await this.client.channels.fetch(category_id); - if (cat_channel.children.size >= 50) - throw new Error('Ticket category has reached child channel limit (50)'); + if (cat_channel.children.size >= 50) throw new Error('Ticket category has reached child channel limit (50)'); - const number = (await this.client.db.models.Ticket.count({ - where: { - guild: guild_id - } - })) + 1; + const number = (await this.client.db.models.Ticket.count({ where: { guild: guild_id } })) + 1; const guild = this.client.guilds.cache.get(guild_id); const creator = await guild.members.fetch(creator_id); @@ -57,25 +48,25 @@ module.exports = class TicketManager extends EventEmitter { .replace(/{+\s?num(ber)?\s?}+/gi, number); const t_channel = await guild.channels.create(name, { - type: 'text', - topic: `${creator}${topic.length > 0 ? ` | ${topic}` : ''}`, parent: category_id, - reason: `${creator.user.tag} requested a new ticket channel` + reason: `${creator.user.tag} requested a new ticket channel`, + topic: `${creator}${topic.length > 0 ? ` | ${topic}` : ''}`, + type: 'text' }); t_channel.updateOverwrite(creator_id, { - VIEW_CHANNEL: true, + ATTACH_FILES: true, READ_MESSAGE_HISTORY: true, SEND_MESSAGES: true, - ATTACH_FILES: true + VIEW_CHANNEL: true }, `Ticket channel created by ${creator.user.tag}`); const t_row = await this.client.db.models.Ticket.create({ - id: t_channel.id, - number, - guild: guild_id, category: category_id, creator: creator_id, + guild: guild_id, + id: t_channel.id, + number, topic: topic.length === 0 ? null : this.client.cryptr.encrypt(topic) }); @@ -115,9 +106,7 @@ module.exports = class TicketManager extends EventEmitter { const sent = await t_channel.send(creator.user.toString(), embed); await sent.pin({ reason: 'Ticket opening message' }); - await t_row.update({ - opening_message: sent.id - }); + await t_row.update({ opening_message: sent.id }); const pinned = t_channel.messages.cache.last(); @@ -147,17 +136,13 @@ module.exports = class TicketManager extends EventEmitter { .setFooter(footer(settings.footer, i18n('collector_expires_in', 120)), guild.iconURL()) ); - const collector_filter = (message) => message.author.id === t_row.creator; + const collector_filter = message => message.author.id === t_row.creator; - const collector = t_channel.createMessageCollector(collector_filter, { - time: 120000 - }); + const collector = t_channel.createMessageCollector(collector_filter, { time: 120000 }); - collector.on('collect', async (message) => { + collector.on('collect', async message => { topic = message.content; - await t_row.update({ - topic: this.client.cryptr.encrypt(topic) - }); + await t_row.update({ topic: this.client.cryptr.encrypt(topic) }); await t_channel.setTopic(`${creator} | ${topic}`, { reason: 'User updated ticket topic' }); await sent.edit( new MessageEmbed() @@ -225,9 +210,9 @@ module.exports = class TicketManager extends EventEmitter { const close = async () => { const pinned = await channel.messages.fetchPinned(); await t_row.update({ - open: false, closed_by: closer_id || null, closed_reason: reason ? this.client.cryptr.encrypt(reason) : null, + open: false, pinned_messages: [...pinned.keys()] }); @@ -276,11 +261,7 @@ module.exports = class TicketManager extends EventEmitter { if (channel) { const creator = await guild.members.fetch(t_row.creator); - const cat_row = await this.client.db.models.Category.findOne({ - where: { - id: t_row.category - } - }); + const cat_row = await this.client.db.models.Category.findOne({ where: { id: t_row.category } }); if (creator && cat_row.survey) { const survey = await this.client.db.models.Survey.findOne({ @@ -302,13 +283,9 @@ module.exports = class TicketManager extends EventEmitter { await r_collector_message.react('✅'); - const collector_filter = (reaction, user) => { - return user.id === creator.user.id && reaction.emoji.name === '✅'; - }; + const collector_filter = (reaction, user) => user.id === creator.user.id && reaction.emoji.name === '✅'; - const r_collector = r_collector_message.createReactionCollector(collector_filter, { - time: 60000 - }); + const r_collector = r_collector_message.createReactionCollector(collector_filter, { time: 60000 }); r_collector.on('collect', async () => { r_collector.stop(); @@ -325,7 +302,11 @@ module.exports = class TicketManager extends EventEmitter { ); try { - const collected = await channel.awaitMessages(filter, { max: 1, time: 60000, errors: ['time'] }); + const collected = await channel.awaitMessages(filter, { + errors: ['time'], + max: 1, + time: 60000 + }); answers.push(collected.first().content); } catch (collected) { return await close(); @@ -351,7 +332,7 @@ module.exports = class TicketManager extends EventEmitter { }); - r_collector.on('end', async (collected) => { + r_collector.on('end', async collected => { if (collected.size === 0) { await close(); } @@ -367,7 +348,7 @@ module.exports = class TicketManager extends EventEmitter { } /** - * + * * @param {(string|number)} ticket_id - ID or number of the ticket * @param {string} [guild_id] - The ID of the ticket's guild (used if a ticket number is provided instead of ID) */ @@ -375,16 +356,12 @@ module.exports = class TicketManager extends EventEmitter { let t_row; if (this.client.channels.resolve(ticket_id)) { - t_row = await this.client.db.models.Ticket.findOne({ - where: { - id: ticket_id - } - }); + t_row = await this.client.db.models.Ticket.findOne({ where: { id: ticket_id } }); } else { t_row = await this.client.db.models.Ticket.findOne({ where: { - number: ticket_id, - guild: guild_id + guild: guild_id, + number: ticket_id } }); } diff --git a/src/structures/guild.js b/src/structures/guild.js index 1b32fb3..392464e 100644 --- a/src/structures/guild.js +++ b/src/structures/guild.js @@ -1,25 +1,21 @@ const { Structures } = require('discord.js'); -Structures.extend('Guild', Guild => { - return class extends Guild { - constructor(client, data) { - super(client, data); - } +Structures.extend('Guild', Guild => class extends Guild { + constructor(client, data) { + super(client, data); + } - async deleteSettings() { - const row = await this.settings; - return await row.destroy(); - } + async deleteSettings() { + const row = await this.settings; + return await row.destroy(); + } - async getSettings() { - const data = { - id: this.id - }; - const [settings] = await this.client.db.models.Guild.findOrCreate({ - defaults: data, - where: data - }); - return settings; - } - }; + async getSettings() { + const data = { id: this.id }; + const [settings] = await this.client.db.models.Guild.findOrCreate({ + defaults: data, + where: data + }); + return settings; + } }); \ No newline at end of file diff --git a/src/structures/guild_member.js b/src/structures/guild_member.js index 6539170..ae53569 100644 --- a/src/structures/guild_member.js +++ b/src/structures/guild_member.js @@ -1,20 +1,14 @@ const { Structures } = require('discord.js'); -Structures.extend('GuildMember', GuildMember => { - return class extends GuildMember { - constructor(client, data, guild) { - super(client, data, guild); - } +Structures.extend('GuildMember', GuildMember => class extends GuildMember { + constructor(client, data, guild) { + super(client, data, guild); + } - async isStaff() { - const guild_categories = await this.client.db.models.Category.findAll({ - where: { - guild: this.guild.id - } - }); - - return guild_categories.some(cat => cat.roles.some(r => this.roles.cache.has(r))); - } + async isStaff() { + const guild_categories = await this.client.db.models.Category.findAll({ where: { guild: this.guild.id } }); + + return guild_categories.some(cat => cat.roles.some(r => this.roles.cache.has(r))); + } - }; }); \ No newline at end of file diff --git a/src/updater.js b/src/updater.js index dccdd69..58e8357 100644 --- a/src/updater.js +++ b/src/updater.js @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ const fetch = require('node-fetch'); const boxen = require('boxen'); const link = require('terminal-link'); @@ -26,11 +27,11 @@ module.exports = async client => { console.log( boxen(format(lines.join('\n')), { - padding: 1, - margin: 1, align: 'center', borderColor: 'yellow', - borderStyle: 'round' + borderStyle: 'round', + margin: 1, + padding: 1 }) ); } diff --git a/src/utils/discord.js b/src/utils/discord.js index d18ae04..55b59ae 100644 --- a/src/utils/discord.js +++ b/src/utils/discord.js @@ -4,9 +4,9 @@ let current_presence = -1; module.exports = { /** - * - * @param {string} text - * @param {string} [additional] + * + * @param {string} text + * @param {string} [additional] * @returns {string} */ footer: (text, additional) => { @@ -20,16 +20,17 @@ module.exports = { selectPresence: () => { const length = config.presence.presences.length; if (length === 0) return {}; - + let num; - if (length === 1) + if (length === 1) { num = 0; - else if (config.presence.randomise) + } else if (config.presence.randomise) { num = Math.floor(Math.random() * length); - else { + } else { current_presence = current_presence + 1; // ++ doesn't work on negative numbers - if (current_presence === length) + if (current_presence === length) { current_presence = 0; + } num = current_presence; } @@ -48,5 +49,5 @@ module.exports = { }, status }; - }, + } }; \ No newline at end of file diff --git a/src/utils/emoji.js b/src/utils/emoji.js index c41ef92..8ee6000 100644 --- a/src/utils/emoji.js +++ b/src/utils/emoji.js @@ -25,7 +25,7 @@ module.exports = { W: '🇼', X: '🇽', Y: '🇾', - Z: '🇿', + Z: '🇿' }, numbers: { 0: '0️⃣', @@ -38,6 +38,6 @@ module.exports = { 7: '7️⃣', 8: '8️⃣', 9: '9️⃣', - 10: '🔟', + 10: '🔟' } }; \ No newline at end of file diff --git a/src/utils/fs.js b/src/utils/fs.js index e069d83..5f76ab3 100644 --- a/src/utils/fs.js +++ b/src/utils/fs.js @@ -6,5 +6,5 @@ module.exports = { * @param {string} path - A path relative to the root of the project (like "./user/config.js") * @returns {string} absolute path */ - path: path => join(__dirname, '../../', path), + path: path => join(__dirname, '../../', path) }; \ No newline at end of file diff --git a/src/utils/index.js b/src/utils/index.js index 84148a9..f702860 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,10 +1,10 @@ module.exports = { - int2hex: (int) => int.toString(16).toUpperCase(), + int2hex: int => int.toString(16).toUpperCase(), some: async (array, func) => { for (const element of array) { if (await func(element)) return true; } return false; }, - wait: (time) => new Promise(res => setTimeout(res, time)), + wait: time => new Promise(res => setTimeout(res, time)) }; \ No newline at end of file