mirror of
https://github.com/Hessenuk/DiscordTickets.git
synced 2025-09-02 00:31:27 +03:00
Improve plugins, make settings server separate
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
const { MessageEmbed } = require('discord.js');
|
||||
const {
|
||||
Command,
|
||||
OptionTypes
|
||||
} = require('../modules/commands');
|
||||
const { OptionTypes } = require('../modules/commands/helpers');
|
||||
const Command = require('../modules/commands/command');
|
||||
|
||||
module.exports = class NewCommand extends Command {
|
||||
constructor(client) {
|
||||
|
@@ -64,10 +64,9 @@ const log = require('./logger');
|
||||
|
||||
const { selectPresence } = require('./utils/discord');
|
||||
const I18n = require('@eartharoid/i18n');
|
||||
const { CommandManager } = require('./modules/commands');
|
||||
const CommandManager = require('./modules/commands/manager');
|
||||
const PluginManager = require('./modules/plugins/manager');
|
||||
const TicketManager = require('./modules/tickets');
|
||||
const { PluginManager } = require('./modules/plugins');
|
||||
const SettingsServer = require('./server');
|
||||
|
||||
require('./modules/structures')(); // load extended structures before creating the client
|
||||
|
||||
@@ -122,9 +121,6 @@ class Bot extends Client {
|
||||
this.plugins = new PluginManager(this);
|
||||
this.plugins.load(); // load plugins
|
||||
|
||||
/** SettingsServer internal plugin instance */
|
||||
this.server = new SettingsServer(this);
|
||||
|
||||
this.log.info('Connecting to Discord API...');
|
||||
|
||||
this.login();
|
||||
|
@@ -5,7 +5,6 @@ const fs = require('fs');
|
||||
const { join } = require('path');
|
||||
const { path } = require('../../utils/fs');
|
||||
const { createMessage, flags } = require('../../utils/discord');
|
||||
const Plugin = require('../plugins/plugin');
|
||||
|
||||
/**
|
||||
* A command
|
||||
|
@@ -1,6 +1,4 @@
|
||||
module.exports = {
|
||||
CommandManager: require('./manager'),
|
||||
Command: require('./command'),
|
||||
OptionTypes: {
|
||||
SUB_COMMAND: 1,
|
||||
SUB_COMMAND_GROUP: 2,
|
||||
@@ -15,5 +13,5 @@ module.exports = {
|
||||
Pong: 1,
|
||||
ChannelMessageWithSource: 4,
|
||||
DeferredChannelMessageWithSource: 5,
|
||||
},
|
||||
}
|
||||
};
|
@@ -182,7 +182,7 @@ module.exports = class CommandManager {
|
||||
// if (typeof res === 'object' || typeof res === 'string')
|
||||
// cmd.sendResponse(interaction, res, res.secret);
|
||||
} catch (e) {
|
||||
this.client.log.warn(`[COMMANDS] An error occurred whilst executed the ${cmd} command`);
|
||||
this.client.log.warn(`(COMMANDS) An error occurred whilst executed the ${cmd_name} command`);
|
||||
this.client.log.error(e);
|
||||
}
|
||||
|
||||
|
@@ -1,4 +0,0 @@
|
||||
module.exports = {
|
||||
PluginManager: require('./manager'),
|
||||
Plugin: require('./plugin')
|
||||
};
|
@@ -3,10 +3,6 @@ const { Collection, Client } = require('discord.js');
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const Plugin = require('./plugin');
|
||||
|
||||
const fs = require('fs');
|
||||
const { join } = require('path');
|
||||
const { path } = require('../../utils/fs');
|
||||
|
||||
/**
|
||||
* Manages the loading of plugins
|
||||
*/
|
||||
@@ -24,17 +20,22 @@ module.exports = class PluginManager {
|
||||
|
||||
/** Array of official plugins to be used to check if a plugin is official */
|
||||
this.official = [
|
||||
'dsctickets.settings-server',
|
||||
'dsctickets.portal'
|
||||
];
|
||||
}
|
||||
|
||||
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.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register and load a plugin
|
||||
* @param {Boolean} npm Installed by NPM?
|
||||
* @param {Plugin} Main The Plugin class
|
||||
* @param {Object} pkg Contents of package.json
|
||||
* @param {Plugin} plugin - the Plugin class
|
||||
* @param {Object} pkg - contents of package.json
|
||||
*/
|
||||
register(npm, Main, pkg) {
|
||||
register(plugin, pkg) {
|
||||
let {
|
||||
name: id,
|
||||
version,
|
||||
@@ -43,7 +44,7 @@ module.exports = class PluginManager {
|
||||
} = pkg;
|
||||
|
||||
if (this.plugins.has(id)) {
|
||||
this.client.log.warn(`[PLUGINS] A plugin with the ID "${id}" is already loaded, skipping`);
|
||||
this.client.log.warn(`(PLUGINS) A plugin with the ID "${id}" is already loaded, skipping`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,10 +52,6 @@ module.exports = class PluginManager {
|
||||
author = author.name || 'unknown';
|
||||
}
|
||||
|
||||
let loading = npm ? 'Loading' : 'Sideloading';
|
||||
|
||||
this.client.log.plugins(`${loading} "${id}" v${version} by ${author}`);
|
||||
|
||||
let about = {
|
||||
id,
|
||||
version,
|
||||
@@ -63,16 +60,13 @@ module.exports = class PluginManager {
|
||||
};
|
||||
|
||||
try {
|
||||
let plugin = new Main(this.client, about);
|
||||
plugin = new (plugin(Plugin))(this.client, about);
|
||||
this.plugins.set(id, plugin);
|
||||
plugin.preload();
|
||||
|
||||
this.client.log.plugins(`Loading "${plugin.name}" v${version} by ${author}`);
|
||||
plugin.preload();
|
||||
} catch (e) {
|
||||
if (npm) {
|
||||
this.client.log.warn(`An error occurred whilst loading "${id}"`);
|
||||
} else {
|
||||
this.client.log.warn(`An error occurred whilst sideloading "${id}"; have you manually installed its dependencies?`);
|
||||
}
|
||||
this.handleError(id);
|
||||
this.client.log.warn(`An error occurred whilst loading the "${id}" plugin`);
|
||||
this.client.log.error(e);
|
||||
process.exit();
|
||||
}
|
||||
@@ -80,27 +74,18 @@ module.exports = class PluginManager {
|
||||
|
||||
/** Automatically register and load plugins */
|
||||
load() {
|
||||
// normal plugins (NPM)
|
||||
this.client.config.plugins.forEach(plugin => {
|
||||
try {
|
||||
let main = require(plugin);
|
||||
let pkg = require(`${plugin}/package.json`);
|
||||
this.register(true, main, pkg);
|
||||
this.register(main, pkg);
|
||||
} catch (e) {
|
||||
this.handleError(plugin);
|
||||
this.client.log.warn(`An error occurred whilst loading ${plugin}; have you installed it?`);
|
||||
this.client.log.error(e);
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
// sideload plugins for development
|
||||
const dirs = fs.readdirSync(path('./user/plugins'));
|
||||
dirs.forEach(dir => {
|
||||
if (!fs.existsSync(path(`./user/plugins/${dir}/package.json`))) return;
|
||||
let pkg = require(`../../../user/plugins/${dir}/package.json`);
|
||||
let main = require(join(`../../../user/plugins/${dir}/`, pkg.main));
|
||||
this.register(false, main, pkg);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
@@ -1,6 +1,10 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
const { Client } = require('discord.js');
|
||||
|
||||
const Command = require('../commands/command');
|
||||
const {
|
||||
OptionTypes,
|
||||
ResponseTypes
|
||||
} = require('../commands/helpers');
|
||||
const fs = require('fs');
|
||||
const { join } = require('path');
|
||||
const { path } = require('../../utils/fs');
|
||||
@@ -24,8 +28,8 @@ module.exports = class Plugin {
|
||||
/** The PluginManager */
|
||||
this.manager = this.client.plugins;
|
||||
|
||||
// Object.assign(this, this.manager.plugins.get(id));
|
||||
// make JSDoc happy
|
||||
/** An official plugin? */
|
||||
this.official = this.manager.official.includes(this.id);
|
||||
|
||||
let {
|
||||
id,
|
||||
@@ -81,6 +85,12 @@ module.exports = class Plugin {
|
||||
name: clean,
|
||||
path: path(`./user/plugins/${clean}`)
|
||||
};
|
||||
|
||||
this.helpers = {
|
||||
Command,
|
||||
OptionTypes,
|
||||
ResponseTypes
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,79 +0,0 @@
|
||||
const { Plugin } = require('../modules/plugins');
|
||||
const fastify = require('fastify');
|
||||
const session = require('fastify-secure-session');
|
||||
const { randomBytes } = require('crypto');
|
||||
const fs = require('fs');
|
||||
const { path } = require('../utils/fs');
|
||||
|
||||
module.exports = class SettingsServer extends Plugin {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
id: 'internal.settings'
|
||||
}, {
|
||||
name: 'Settings server',
|
||||
commands: []
|
||||
});
|
||||
|
||||
this.fastify = fastify();
|
||||
|
||||
this.client.plugins.plugins.set(this.id, this);
|
||||
this.preload();
|
||||
}
|
||||
|
||||
async preload() {
|
||||
this.fastify.register(this.client.log.fastify(), {
|
||||
level: 'http',
|
||||
format: '&lSETTINGS:&r {status-colour}{status}&r {method} &7{route} {time-colour}({time})'
|
||||
});
|
||||
|
||||
this.fastify.register(session, {
|
||||
secret: randomBytes(48).toString('hex'),
|
||||
salt: randomBytes(8).toString('hex'),
|
||||
cookie: {
|
||||
path: '/',
|
||||
httpOnly: true ,
|
||||
},
|
||||
});
|
||||
|
||||
this.fastify.register(require('fastify-static'), {
|
||||
root: path('./src/server/public'),
|
||||
// prefix: '/public/',
|
||||
});
|
||||
|
||||
let host = process.env.HTTP_HOST;
|
||||
if (!host.endsWith('/')) host = host + '/';
|
||||
this.redirect_uri = encodeURI(`${host}auth/callback`);
|
||||
}
|
||||
|
||||
async load() {
|
||||
const routes = fs.readdirSync(path('./src/server/routes'))
|
||||
.filter(file => file.endsWith('.js'));
|
||||
for (const r of routes) {
|
||||
const {
|
||||
method,
|
||||
route,
|
||||
execute
|
||||
} = require(`./routes/${r}`);
|
||||
this.fastify[method](route, (...args) => execute(this, ...args));
|
||||
}
|
||||
|
||||
this.fastify.listen(process.env.HTTP_PORT || 8080, (err, host) => {
|
||||
if (err) throw err;
|
||||
this.client.log.info(`Settings server listening at ${host}`);
|
||||
});
|
||||
|
||||
this.io = require('socket.io')(process.env.HTTP_PORT || 8080);
|
||||
|
||||
this.io.on('connection', socket => {
|
||||
const events = fs.readdirSync(path('./src/server/socket'))
|
||||
.filter(file => file.endsWith('.js'));
|
||||
for (const e of events) {
|
||||
const {
|
||||
event,
|
||||
execute
|
||||
} = require(`./socket/${e}`);
|
||||
socket.on(event, (...args) => execute(this, ...args));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>DiscordTickets / Settings</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.1/socket.io.min.js'></script>
|
||||
<script>
|
||||
const socket = io('./');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1,47 +0,0 @@
|
||||
const fetch = require('node-fetch');
|
||||
const FormData = require('form-data');
|
||||
|
||||
module.exports = {
|
||||
method: 'get',
|
||||
route: '/auth/callback',
|
||||
execute: async (plugin, req, res) => {
|
||||
|
||||
if (!req.query.code) {
|
||||
res.status(400);
|
||||
return 'Bad Request: no code';
|
||||
}
|
||||
|
||||
if (req.query.state !== 'apollo') {
|
||||
res.status(400);
|
||||
return 'Bad Request: state mismatch';
|
||||
}
|
||||
|
||||
const data = new FormData();
|
||||
data.append('client_id', plugin.client.user.id);
|
||||
data.append('client_secret', process.env.DISCORD_SECRET);
|
||||
data.append('grant_type', 'authorization_code');
|
||||
data.append('redirect_uri', plugin.redirect_uri);
|
||||
data.append('scope', 'identify guild');
|
||||
data.append('code', req.query.code);
|
||||
|
||||
let {
|
||||
access_token,
|
||||
expires_in,
|
||||
refresh_token
|
||||
} = await (await fetch('https://discordapp.com/api/oauth2/token', {
|
||||
method: 'POST',
|
||||
body: data,
|
||||
})).json();
|
||||
|
||||
expires_in = expires_in * 1000;
|
||||
let expires_at = Date.now() + expires_in;
|
||||
|
||||
req.session.set('access_token', access_token);
|
||||
req.session.set('expires_in', expires_in);
|
||||
req.session.set('expires_at', expires_at);
|
||||
req.session.set('refresh_token', refresh_token);
|
||||
|
||||
res.redirect(307, '/settings');
|
||||
|
||||
}
|
||||
};
|
@@ -1,16 +0,0 @@
|
||||
module.exports = {
|
||||
method: 'get',
|
||||
route: '/auth/login',
|
||||
execute: async (plugin, req, res) => {
|
||||
|
||||
let url = new URL('https://discord.com/api/oauth2/authorize');
|
||||
url.searchParams.append('client_id', plugin.client.user.id);
|
||||
url.searchParams.append('redirect_uri', plugin.redirect_uri);
|
||||
url.searchParams.append('response_type', 'code');
|
||||
url.searchParams.append('scope', 'identify guilds');
|
||||
url.searchParams.append('state', 'apollo');
|
||||
|
||||
res.redirect(307, url);
|
||||
|
||||
}
|
||||
};
|
@@ -1,10 +0,0 @@
|
||||
module.exports = {
|
||||
method: 'get',
|
||||
route: '/auth/logout',
|
||||
execute: async (plugin, req, res) => {
|
||||
|
||||
req.session.delete();
|
||||
res.send('Logged out successfully');
|
||||
|
||||
}
|
||||
};
|
@@ -1,9 +0,0 @@
|
||||
module.exports = {
|
||||
method: 'get',
|
||||
route: '/',
|
||||
execute: async (plugin, req, res) => {
|
||||
|
||||
res.redirect(307, '/auth/login');
|
||||
|
||||
}
|
||||
};
|
@@ -1,23 +0,0 @@
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
module.exports = {
|
||||
method: 'get',
|
||||
route: '/settings',
|
||||
execute: async (plugin, req, res) => {
|
||||
|
||||
let expires_at = req.session.get('expires_at');
|
||||
if (!expires_at) res.redirect(307, '/auth/login');
|
||||
let expired = expires_at < Date.now();
|
||||
if (expired) res.redirect(307, '/auth/login');
|
||||
|
||||
let data = await (await fetch('https://discordapp.com/api/users/@me', {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${req.session.get('access_token')}`
|
||||
}
|
||||
})).json();
|
||||
|
||||
console.log(data);
|
||||
|
||||
return `Hello, ${data.username}`;
|
||||
}
|
||||
};
|
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
event: 'connect',
|
||||
execute: (plugin, data) => {
|
||||
plugin.client.log.ws('Client connected to settings socket');
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user