From 5fdfb121c7c37741b7da5c811b903a900d0bdc6f Mon Sep 17 00:00:00 2001 From: Isaac Date: Tue, 16 Feb 2021 22:34:20 +0000 Subject: [PATCH] things --- .gitignore | 1 + README.md | 2 ++ example.env | 3 +- package.json | 4 ++- pnpm-lock.yaml | 21 ++++++++++---- src/banner.js | 28 ++++++++++++++++++ src/database/dialects.js | 2 +- src/database/index.js | 31 ++++++++++---------- src/index.js | 45 +++++++++++++++++++++++++---- src/listeners/messageReactionAdd.js | 8 +++++ src/listeners/ready.js | 6 ++++ src/modules/commands.js | 41 ++++++++++++++++++++++++++ src/modules/listeners.js | 13 +++++++++ src/modules/plugins.js | 35 ++++++++++++++++++++++ src/structures/guild.js | 17 +++++++++++ src/structures/textchannel.js | 25 ++++++++++++++++ user/example.config.js | 7 ++--- 17 files changed, 257 insertions(+), 32 deletions(-) create mode 100644 src/banner.js create mode 100644 src/listeners/messageReactionAdd.js create mode 100644 src/listeners/ready.js create mode 100644 src/modules/commands.js create mode 100644 src/modules/listeners.js create mode 100644 src/modules/plugins.js create mode 100644 src/structures/guild.js create mode 100644 src/structures/textchannel.js diff --git a/.gitignore b/.gitignore index 6c80c60..499b35b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ site/ .env user/config.js user/database.sqlite +user/plugins/*/ *.code-workspace diff --git a/README.md b/README.md index 1a0864d..d6f12bc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # Please download from [releases](https://github.com/eartharoid/DiscordTickets/releases) or [v2 branch](https://github.com/eartharoid/DiscordTickets/tree/v2) - master branch is currently a work in progress https://discord.com/oauth2/authorize?permissions=8&scope=applications.commands%20bot&client_id=... + +`npm i --production` \ No newline at end of file diff --git a/example.env b/example.env index a341eef..2b1f03f 100644 --- a/example.env +++ b/example.env @@ -4,4 +4,5 @@ DB_TYPE=sqlite DB_HOST= DB_NAME= DB_USER= -DB_PASS= \ No newline at end of file +DB_PASS= +DB_TABLE_PREFIX=dsctickets_ \ No newline at end of file diff --git a/package.json b/package.json index 4d5be2a..aa358e6 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,12 @@ "discord.js": "^12.5.1", "dotenv": "^8.2.0", "keyv": "^4.0.3", + "leeks.js": "^0.0.9", "leekslazylogger": "^2.0.7", "node-fetch": "^2.6.1", "sequelize": "^6.5.0", - "terminal-link": "^2.1.1" + "terminal-link": "^2.1.1", + "yarpm": "^1.1.1" }, "devDependencies": { "eslint": "^7.20.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5eacdf2..f43a122 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3,10 +3,12 @@ dependencies: discord.js: 12.5.1 dotenv: 8.2.0 keyv: 4.0.3 + leeks.js: 0.0.9 leekslazylogger: 2.0.7 node-fetch: 2.6.1 sequelize: 6.5.0_fb66e8c649bde1be622cc06164c9e22d terminal-link: 2.1.1 + yarpm: 1.1.1 devDependencies: eslint: 7.20.0 mariadb: 2.5.2 @@ -576,6 +578,10 @@ packages: node: '>= 0.8' resolution: integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + /command-exists/1.2.9: + dev: false + resolution: + integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== /concat-map/0.0.1: resolution: integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= @@ -605,7 +611,6 @@ packages: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true engines: node: '>= 8' resolution: @@ -1897,7 +1902,6 @@ packages: resolution: integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= /path-key/3.1.1: - dev: true engines: node: '>=8' resolution: @@ -2332,13 +2336,11 @@ packages: /shebang-command/2.0.0: dependencies: shebang-regex: 3.0.0 - dev: true engines: node: '>=8' resolution: integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== /shebang-regex/3.0.0: - dev: true engines: node: '>=8' resolution: @@ -2771,7 +2773,6 @@ packages: /which/2.0.2: dependencies: isexe: 2.0.0 - dev: true engines: node: '>= 8' hasBin: true @@ -2881,12 +2882,21 @@ packages: /yallist/4.0.0: resolution: integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + /yarpm/1.1.1: + dependencies: + command-exists: 1.2.9 + cross-spawn: 7.0.3 + dev: false + hasBin: true + resolution: + integrity: sha512-A3gVdtyld+gYcVmKScvJqS2oT/i9xdsb/SqDsY9c0+BeYdYBUJrRfr4pD7UP+5uXEneJ0BL0rC/6rd1fnlYEcg== specifiers: '@eartharoid/i18n': ^0.0.1 discord.js: ^12.5.1 dotenv: ^8.2.0 eslint: ^7.20.0 keyv: ^4.0.3 + leeks.js: ^0.0.9 leekslazylogger: ^2.0.7 mariadb: ^2.5.2 mysql2: ^2.2.5 @@ -2898,3 +2908,4 @@ specifiers: sqlite3: ^5.0.2 tedious: ^11.0.3 terminal-link: ^2.1.1 + yarpm: ^1.1.1 diff --git a/src/banner.js b/src/banner.js new file mode 100644 index 0000000..49139d7 --- /dev/null +++ b/src/banner.js @@ -0,0 +1,28 @@ +const link = require('terminal-link'); +const leeks = require('leeks.js'); + +const { version, homepage } = require('../package.json'); + +module.exports = () => { + console.log(leeks.colours.cyan(` +######## #### ###### ###### ####### ######## ######## +## ## ## ## ## ## ## ## ## ## ## ## ## +## ## ## ## ## ## ## ## ## ## ## +## ## ## ###### ## ## ## ######## ## ## +## ## ## ## ## ## ## ## ## ## ## +## ## ## ## ## ## ## ## ## ## ## ## ## +######## #### ###### ###### ####### ## ## ######## + +######## #### ###### ## ## ######## ######## ###### + ## ## ## ## ## ## ## ## ## ## + ## ## ## ## ## ## ## ## + ## ## ## ##### ###### ## ###### + ## ## ## ## ## ## ## ## + ## ## ## ## ## ## ## ## ## ## + ## #### ###### ## ## ######## ## ###### +`)); + console.log(leeks.colours.cyanBright(`DiscordTickets bot v${version} by eartharoid`)); + console.log(leeks.colours.cyanBright(homepage + '\n')); + console.log(leeks.colours.cyanBright(`Please ${link('donate', 'https://ko-fi.com/eartharoid')} if you find this bot useful`)); + console.log('\n\n'); +}; \ No newline at end of file diff --git a/src/database/dialects.js b/src/database/dialects.js index 0eb4f31..05a4353 100644 --- a/src/database/dialects.js +++ b/src/database/dialects.js @@ -19,7 +19,7 @@ module.exports = { dialect: 'mariadb', package: ['mariadb'] }, - postgre: { + postgre: { // this is wrong name: 'PostgreSQL', dialect: 'postgres', packages: ['pg', 'pg-hstore'] diff --git a/src/database/index.js b/src/database/index.js index f22b477..1699287 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -14,22 +14,23 @@ module.exports = async (log) => { DB_HOST, DB_USER, DB_PASS, - DB_NAME + DB_NAME, + DB_TABLE_PREFIX } = process.env; let type = (DB_TYPE || 'sqlite').toLowerCase(); if (!supported.includes(type)) { - log.report('Invalid database type'); - throw new Error(`DB_TYPE (${type}) is not a valid type`); + log.error(new Error(`DB_TYPE (${type}) is not a valid type`)); + return process.exit(); } try { types[type].packages.forEach(pkg => require(pkg)); } catch { - log.report('Specified database type is not installed'); let required = types[type].packages.map(i => `"${i}"`).join(' and '); - throw new Error(`Please install the package(s) for your selected database type: ${required}`); + log.error(new Error(`Please install the package(s) for your selected database type: ${required}`)); + return process.exit(); } let sequelize; @@ -56,6 +57,7 @@ module.exports = async (log) => { } catch (error) { log.warn('Unable to connect to database'); log.error(error); + return process.exit(); } /* let models = {}; @@ -70,25 +72,23 @@ module.exports = async (log) => { const Guild = sequelize.define('Guild', { id: { type: DataTypes.CHAR(18), - primaryKey: true - }, - prefix: { - type: DataTypes.STRING, // STRING(255) = VARCHAR(255) - defaultValue: config.defaults.prefix + primaryKey: true, + allowNull: false, }, locale: { type: DataTypes.STRING, defaultValue: config.defaults.locale } }, { - tableName: 'guilds' + tableName: DB_TABLE_PREFIX + 'guilds' }); const Ticket = sequelize.define('Ticket', { id: { type: DataTypes.CHAR(18), - primaryKey: true + primaryKey: true, + allowNull: false, }, guild: { type: DataTypes.STRING, @@ -99,14 +99,15 @@ module.exports = async (log) => { }, } }, { - tableName: 'tickets' + tableName: DB_TABLE_PREFIX + 'tickets' }); // eslint-disable-next-line no-unused-vars const Message = sequelize.define('Message', { id: { type: DataTypes.CHAR(18), - primaryKey: true + primaryKey: true, + allowNull: false, }, ticket: { type: DataTypes.STRING, @@ -117,7 +118,7 @@ module.exports = async (log) => { }, } }, { - tableName: 'messages' + tableName: DB_TABLE_PREFIX + 'messages' }); sequelize.sync(); diff --git a/src/index.js b/src/index.js index 1ea1ed7..d59d47f 100644 --- a/src/index.js +++ b/src/index.js @@ -36,12 +36,28 @@ require('dotenv').config({ const config = require('../user/config'); +require('./banner')(); + const Logger = require('leekslazylogger'); const log = new Logger({ name: 'DiscordTickets by eartharoid', debug: config.debug, logToFile: config.logs.enabled, - keepFor: config.logs.keep_for + keepFor: config.logs.keep_for, + custom: { + listeners: { + title: 'info', + prefix: 'listeners' + }, + commands: { + title: 'info', + prefix: 'commands' + }, + plugins: { + title: 'info', + prefix: 'plugins' + } + } }); @@ -60,12 +76,24 @@ log.report = error => { const terminalLink = require('terminal-link'); const I18n = require('@eartharoid/i18n'); +const { CommandManager } = require('./modules/commands'); + +const { + Client, + Intents +} = require('discord.js'); -const { Client } = require('discord.js'); class Bot extends Client { constructor() { super({ - autoReconnect: true, + partials: [ + 'MESSAGE', + 'CHANNEL', + 'REACTION' + ], + ws: { + intents: Intents.NON_PRIVILEGED, + } }); Object.assign(this, { @@ -75,10 +103,17 @@ class Bot extends Client { i18n: new I18n(path('./src/locales'), 'en-GB') }); - this.log.info('Connecting to Discord API'); + (async () => { + this.listeners = require('./modules/listeners')(this); + this.commands = new CommandManager(this); + this.plugins = await require('./modules/plugins')(this); - this.login(); + this.log.info('Connecting to Discord API'); + + this.login(); + })(); } + } new Bot(); diff --git a/src/listeners/messageReactionAdd.js b/src/listeners/messageReactionAdd.js new file mode 100644 index 0000000..25d9e47 --- /dev/null +++ b/src/listeners/messageReactionAdd.js @@ -0,0 +1,8 @@ +module.exports = { + event: 'messageReactionAdd', + execute: (client, r, u) => { + client.log.info('messageReactionAdd'); + console.log(r); + console.log(u); + } +}; \ No newline at end of file diff --git a/src/listeners/ready.js b/src/listeners/ready.js new file mode 100644 index 0000000..79458fb --- /dev/null +++ b/src/listeners/ready.js @@ -0,0 +1,6 @@ +module.exports = { + event: 'ready', + execute: client => { + client.log.success(`Connected to Discord as ${client.user.tag}`); + } +}; \ No newline at end of file diff --git a/src/modules/commands.js b/src/modules/commands.js new file mode 100644 index 0000000..e38d279 --- /dev/null +++ b/src/modules/commands.js @@ -0,0 +1,41 @@ +const fs = require('fs'); +const { join } = require('path'); +const { path } = require('../utils/fs'); + +class CommandManager { + constructor(client) { + this.client = client; + this.commands = new Map(); + } + + load(command) { + + } + + unload(command) { + + } + + reload(command) { + + } + + get(command) { + + } + + get list() { + return this.commands; + } +} + +class Command { + constructor(client) { + + } +} + +module.exports = { + CommandManager, + Command +}; \ No newline at end of file diff --git a/src/modules/listeners.js b/src/modules/listeners.js new file mode 100644 index 0000000..f53474f --- /dev/null +++ b/src/modules/listeners.js @@ -0,0 +1,13 @@ +const fs = require('fs'); +const { path } = require('../utils/fs'); + +module.exports = client => { + const files = fs.readdirSync(path('./src/listeners')) + .filter(file => file.endsWith('.js')); + + for (const file of files) { + const listener = require(`../listeners/${file}`); + // client.on(listener.event, ...args => listener.execute(client, ...args)); + client.on(listener.event, args => listener.execute(client, args)); + } +}; \ No newline at end of file diff --git a/src/modules/plugins.js b/src/modules/plugins.js new file mode 100644 index 0000000..fa16356 --- /dev/null +++ b/src/modules/plugins.js @@ -0,0 +1,35 @@ +const yarpm = require('yarpm'); +const fs = require('fs'); +const { join } = require('path'); +const { path } = require('../utils/fs'); + +module.exports = async client => { + const plugins = {}; + const dirs = fs.readdirSync(path('./user/plugins')); + + for (const dir of dirs) { + let package_path = path(`./user/plugins/${dir}/package.json`); + if (!fs.existsSync(package_path)) continue; + + let package = require(`../../user/plugins/${dir}/package.json`); + let main = require(join(`../../user/plugins/${dir}/`, package.main)); + + plugins[package.name] = package; + client.log.plugins(`Loading ${package.name} v${package.version} by ${package.author}`); + + if (package.dependencies && Object.keys(package.dependencies).length >= 1) { + client.log.plugins(`Installing dependencies for ${package.name}`); + let deps = Object.keys(package.dependencies) + .map(d => `${d}@${package.dependencies[d]}`) + .join(' '); + + await yarpm(['install', '--no-save', deps], { + stdout: process.stdout + }); + await main(client); + } else { + await main(client); + } + + } +}; \ No newline at end of file diff --git a/src/structures/guild.js b/src/structures/guild.js new file mode 100644 index 0000000..ec9f6b4 --- /dev/null +++ b/src/structures/guild.js @@ -0,0 +1,17 @@ +const { Structures } = require('discord.js'); + +Structures.extend('Guild', Guild => { + return class extends Guild { + constructor(client, data) { + super(client, data); + } + + get settings() { + return this.client.db.Guild.findOne({ + where: { + id: this.id + } + }); + } + }; +}); \ No newline at end of file diff --git a/src/structures/textchannel.js b/src/structures/textchannel.js new file mode 100644 index 0000000..3fc415b --- /dev/null +++ b/src/structures/textchannel.js @@ -0,0 +1,25 @@ +const { Structures } = require('discord.js'); + +Structures.extend('TextChannel', TextChannel => { + return class extends TextChannel { + constructor(client, data) { + super(client, data); + } + + get isTicket() { + return !!this.client.db.Ticket.findOne({ + where: { + id: this.id + } + }); + } + + get ticket() { + return new class { + constructor(channel) { + this.channel = channel; + } + }(this); + } + }; +}); \ No newline at end of file diff --git a/user/example.config.js b/user/example.config.js index cb5f2fe..635b097 100644 --- a/user/example.config.js +++ b/user/example.config.js @@ -29,20 +29,19 @@ module.exports = { }, presences: [ { - activity: '%snew | %shelp', + activity: '/new | /help', type: 'PLAYING' }, { - activity: 'with tickets | %shelp', + activity: 'with tickets | /help', type: 'PLAYING' }, { - activity: 'for new tickets | %shelp', + activity: 'for new tickets | /help', type: 'WATCHING' }, ], defaults: { - prefix: '-', colour: '#009999', locale: 'en-GB' },