This commit is contained in:
Isaac 2021-02-16 22:34:20 +00:00
parent cf8dff2a5b
commit 5fdfb121c7
No known key found for this signature in database
GPG Key ID: 279D1F53391CED07
17 changed files with 257 additions and 32 deletions

1
.gitignore vendored
View File

@ -8,4 +8,5 @@ site/
.env .env
user/config.js user/config.js
user/database.sqlite user/database.sqlite
user/plugins/*/
*.code-workspace *.code-workspace

View File

@ -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 # 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=... https://discord.com/oauth2/authorize?permissions=8&scope=applications.commands%20bot&client_id=...
`npm i --production`

View File

@ -5,3 +5,4 @@ DB_HOST=
DB_NAME= DB_NAME=
DB_USER= DB_USER=
DB_PASS= DB_PASS=
DB_TABLE_PREFIX=dsctickets_

View File

@ -32,10 +32,12 @@
"discord.js": "^12.5.1", "discord.js": "^12.5.1",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"keyv": "^4.0.3", "keyv": "^4.0.3",
"leeks.js": "^0.0.9",
"leekslazylogger": "^2.0.7", "leekslazylogger": "^2.0.7",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"sequelize": "^6.5.0", "sequelize": "^6.5.0",
"terminal-link": "^2.1.1" "terminal-link": "^2.1.1",
"yarpm": "^1.1.1"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^7.20.0", "eslint": "^7.20.0",

View File

@ -3,10 +3,12 @@ dependencies:
discord.js: 12.5.1 discord.js: 12.5.1
dotenv: 8.2.0 dotenv: 8.2.0
keyv: 4.0.3 keyv: 4.0.3
leeks.js: 0.0.9
leekslazylogger: 2.0.7 leekslazylogger: 2.0.7
node-fetch: 2.6.1 node-fetch: 2.6.1
sequelize: 6.5.0_fb66e8c649bde1be622cc06164c9e22d sequelize: 6.5.0_fb66e8c649bde1be622cc06164c9e22d
terminal-link: 2.1.1 terminal-link: 2.1.1
yarpm: 1.1.1
devDependencies: devDependencies:
eslint: 7.20.0 eslint: 7.20.0
mariadb: 2.5.2 mariadb: 2.5.2
@ -576,6 +578,10 @@ packages:
node: '>= 0.8' node: '>= 0.8'
resolution: resolution:
integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 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: /concat-map/0.0.1:
resolution: resolution:
integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
@ -605,7 +611,6 @@ packages:
path-key: 3.1.1 path-key: 3.1.1
shebang-command: 2.0.0 shebang-command: 2.0.0
which: 2.0.2 which: 2.0.2
dev: true
engines: engines:
node: '>= 8' node: '>= 8'
resolution: resolution:
@ -1897,7 +1902,6 @@ packages:
resolution: resolution:
integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
/path-key/3.1.1: /path-key/3.1.1:
dev: true
engines: engines:
node: '>=8' node: '>=8'
resolution: resolution:
@ -2332,13 +2336,11 @@ packages:
/shebang-command/2.0.0: /shebang-command/2.0.0:
dependencies: dependencies:
shebang-regex: 3.0.0 shebang-regex: 3.0.0
dev: true
engines: engines:
node: '>=8' node: '>=8'
resolution: resolution:
integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
/shebang-regex/3.0.0: /shebang-regex/3.0.0:
dev: true
engines: engines:
node: '>=8' node: '>=8'
resolution: resolution:
@ -2771,7 +2773,6 @@ packages:
/which/2.0.2: /which/2.0.2:
dependencies: dependencies:
isexe: 2.0.0 isexe: 2.0.0
dev: true
engines: engines:
node: '>= 8' node: '>= 8'
hasBin: true hasBin: true
@ -2881,12 +2882,21 @@ packages:
/yallist/4.0.0: /yallist/4.0.0:
resolution: resolution:
integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 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: specifiers:
'@eartharoid/i18n': ^0.0.1 '@eartharoid/i18n': ^0.0.1
discord.js: ^12.5.1 discord.js: ^12.5.1
dotenv: ^8.2.0 dotenv: ^8.2.0
eslint: ^7.20.0 eslint: ^7.20.0
keyv: ^4.0.3 keyv: ^4.0.3
leeks.js: ^0.0.9
leekslazylogger: ^2.0.7 leekslazylogger: ^2.0.7
mariadb: ^2.5.2 mariadb: ^2.5.2
mysql2: ^2.2.5 mysql2: ^2.2.5
@ -2898,3 +2908,4 @@ specifiers:
sqlite3: ^5.0.2 sqlite3: ^5.0.2
tedious: ^11.0.3 tedious: ^11.0.3
terminal-link: ^2.1.1 terminal-link: ^2.1.1
yarpm: ^1.1.1

28
src/banner.js Normal file
View File

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

View File

@ -19,7 +19,7 @@ module.exports = {
dialect: 'mariadb', dialect: 'mariadb',
package: ['mariadb'] package: ['mariadb']
}, },
postgre: { postgre: { // this is wrong
name: 'PostgreSQL', name: 'PostgreSQL',
dialect: 'postgres', dialect: 'postgres',
packages: ['pg', 'pg-hstore'] packages: ['pg', 'pg-hstore']

View File

@ -14,22 +14,23 @@ module.exports = async (log) => {
DB_HOST, DB_HOST,
DB_USER, DB_USER,
DB_PASS, DB_PASS,
DB_NAME DB_NAME,
DB_TABLE_PREFIX
} = process.env; } = process.env;
let type = (DB_TYPE || 'sqlite').toLowerCase(); let type = (DB_TYPE || 'sqlite').toLowerCase();
if (!supported.includes(type)) { if (!supported.includes(type)) {
log.report('Invalid database type'); log.error(new Error(`DB_TYPE (${type}) is not a valid type`));
throw new Error(`DB_TYPE (${type}) is not a valid type`); return process.exit();
} }
try { try {
types[type].packages.forEach(pkg => require(pkg)); types[type].packages.forEach(pkg => require(pkg));
} catch { } catch {
log.report('Specified database type is not installed');
let required = types[type].packages.map(i => `"${i}"`).join(' and '); 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; let sequelize;
@ -56,6 +57,7 @@ module.exports = async (log) => {
} catch (error) { } catch (error) {
log.warn('Unable to connect to database'); log.warn('Unable to connect to database');
log.error(error); log.error(error);
return process.exit();
} }
/* let models = {}; /* let models = {};
@ -70,25 +72,23 @@ module.exports = async (log) => {
const Guild = sequelize.define('Guild', { const Guild = sequelize.define('Guild', {
id: { id: {
type: DataTypes.CHAR(18), type: DataTypes.CHAR(18),
primaryKey: true primaryKey: true,
}, allowNull: false,
prefix: {
type: DataTypes.STRING, // STRING(255) = VARCHAR(255)
defaultValue: config.defaults.prefix
}, },
locale: { locale: {
type: DataTypes.STRING, type: DataTypes.STRING,
defaultValue: config.defaults.locale defaultValue: config.defaults.locale
} }
}, { }, {
tableName: 'guilds' tableName: DB_TABLE_PREFIX + 'guilds'
}); });
const Ticket = sequelize.define('Ticket', { const Ticket = sequelize.define('Ticket', {
id: { id: {
type: DataTypes.CHAR(18), type: DataTypes.CHAR(18),
primaryKey: true primaryKey: true,
allowNull: false,
}, },
guild: { guild: {
type: DataTypes.STRING, 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 // eslint-disable-next-line no-unused-vars
const Message = sequelize.define('Message', { const Message = sequelize.define('Message', {
id: { id: {
type: DataTypes.CHAR(18), type: DataTypes.CHAR(18),
primaryKey: true primaryKey: true,
allowNull: false,
}, },
ticket: { ticket: {
type: DataTypes.STRING, type: DataTypes.STRING,
@ -117,7 +118,7 @@ module.exports = async (log) => {
}, },
} }
}, { }, {
tableName: 'messages' tableName: DB_TABLE_PREFIX + 'messages'
}); });
sequelize.sync(); sequelize.sync();

View File

@ -36,12 +36,28 @@ require('dotenv').config({
const config = require('../user/config'); const config = require('../user/config');
require('./banner')();
const Logger = require('leekslazylogger'); const Logger = require('leekslazylogger');
const log = new Logger({ const log = new Logger({
name: 'DiscordTickets by eartharoid', name: 'DiscordTickets by eartharoid',
debug: config.debug, debug: config.debug,
logToFile: config.logs.enabled, 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 terminalLink = require('terminal-link');
const I18n = require('@eartharoid/i18n'); 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 { class Bot extends Client {
constructor() { constructor() {
super({ super({
autoReconnect: true, partials: [
'MESSAGE',
'CHANNEL',
'REACTION'
],
ws: {
intents: Intents.NON_PRIVILEGED,
}
}); });
Object.assign(this, { Object.assign(this, {
@ -75,10 +103,17 @@ class Bot extends Client {
i18n: new I18n(path('./src/locales'), 'en-GB') i18n: new I18n(path('./src/locales'), 'en-GB')
}); });
(async () => {
this.listeners = require('./modules/listeners')(this);
this.commands = new CommandManager(this);
this.plugins = await require('./modules/plugins')(this);
this.log.info('Connecting to Discord API'); this.log.info('Connecting to Discord API');
this.login(); this.login();
})();
} }
} }
new Bot(); new Bot();

View File

@ -0,0 +1,8 @@
module.exports = {
event: 'messageReactionAdd',
execute: (client, r, u) => {
client.log.info('messageReactionAdd');
console.log(r);
console.log(u);
}
};

6
src/listeners/ready.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
event: 'ready',
execute: client => {
client.log.success(`Connected to Discord as ${client.user.tag}`);
}
};

41
src/modules/commands.js Normal file
View File

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

13
src/modules/listeners.js Normal file
View File

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

35
src/modules/plugins.js Normal file
View File

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

17
src/structures/guild.js Normal file
View File

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

View File

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

View File

@ -29,20 +29,19 @@ module.exports = {
}, },
presences: [ presences: [
{ {
activity: '%snew | %shelp', activity: '/new | /help',
type: 'PLAYING' type: 'PLAYING'
}, },
{ {
activity: 'with tickets | %shelp', activity: 'with tickets | /help',
type: 'PLAYING' type: 'PLAYING'
}, },
{ {
activity: 'for new tickets | %shelp', activity: 'for new tickets | /help',
type: 'WATCHING' type: 'WATCHING'
}, },
], ],
defaults: { defaults: {
prefix: '-',
colour: '#009999', colour: '#009999',
locale: 'en-GB' locale: 'en-GB'
}, },