initial files
This commit is contained in:
commit
856f2dc0a7
208
.eslintrc.js
Normal file
208
.eslintrc.js
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
module.exports = {
|
||||||
|
'env': {
|
||||||
|
'commonjs': true,
|
||||||
|
'es2021': true,
|
||||||
|
'node': true
|
||||||
|
},
|
||||||
|
'extends': 'eslint:recommended',
|
||||||
|
'parserOptions': {
|
||||||
|
'ecmaVersion': 12
|
||||||
|
},
|
||||||
|
'rules': {
|
||||||
|
"accessor-pairs": "warn",
|
||||||
|
"array-callback-return": "warn",
|
||||||
|
"arrow-parens": "warn",
|
||||||
|
"arrow-spacing": "warn",
|
||||||
|
"block-scoped-var": "warn",
|
||||||
|
"block-spacing": "warn",
|
||||||
|
"brace-style": "warn",
|
||||||
|
"callback-return": "warn",
|
||||||
|
"camelcase": "warn",
|
||||||
|
"comma-dangle": "warn",
|
||||||
|
"comma-spacing": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"after": true,
|
||||||
|
"before": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comma-style": "warn",
|
||||||
|
"computed-property-spacing": [
|
||||||
|
"warn",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"consistent-this": "warn",
|
||||||
|
"dot-notation": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"allowKeywords": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"eol-last": [
|
||||||
|
"warn",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"eqeqeq": "warn",
|
||||||
|
"func-call-spacing": "warn",
|
||||||
|
"func-name-matching": "warn",
|
||||||
|
"func-names": "warn",
|
||||||
|
"func-style": "warn",
|
||||||
|
"function-paren-newline": "warn",
|
||||||
|
"generator-star-spacing": "warn",
|
||||||
|
"grouped-accessor-pairs": "warn",
|
||||||
|
"guard-for-in": "warn",
|
||||||
|
"handle-callback-err": "warn",
|
||||||
|
"id-blacklist": "warn",
|
||||||
|
"id-match": "warn",
|
||||||
|
"implicit-arrow-linebreak": "warn",
|
||||||
|
"indent": [
|
||||||
|
"warn",
|
||||||
|
4,
|
||||||
|
{
|
||||||
|
"SwitchCase": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"init-declarations": "warn",
|
||||||
|
"jsx-quotes": "warn",
|
||||||
|
"key-spacing": "warn",
|
||||||
|
"linebreak-style": [
|
||||||
|
"warn",
|
||||||
|
"windows"
|
||||||
|
],
|
||||||
|
"lines-around-comment": "warn",
|
||||||
|
"lines-around-directive": "warn",
|
||||||
|
"lines-between-class-members": [
|
||||||
|
"warn",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"max-classes-per-file": "warn",
|
||||||
|
"max-nested-callbacks": "warn",
|
||||||
|
"new-parens": "warn",
|
||||||
|
"no-alert": "warn",
|
||||||
|
"no-array-constructor": "warn",
|
||||||
|
"no-bitwise": "warn",
|
||||||
|
"no-buffer-constructor": "warn",
|
||||||
|
"no-caller": "warn",
|
||||||
|
"no-console": "warn",
|
||||||
|
"no-div-regex": "warn",
|
||||||
|
"no-dupe-else-if": "warn",
|
||||||
|
"no-duplicate-imports": "warn",
|
||||||
|
"no-else-return": "warn",
|
||||||
|
"no-empty-function": "warn",
|
||||||
|
"no-eq-null": "warn",
|
||||||
|
"no-eval": "warn",
|
||||||
|
"no-extend-native": "warn",
|
||||||
|
"no-extra-bind": "warn",
|
||||||
|
"no-extra-label": "warn",
|
||||||
|
"no-extra-parens": "warn",
|
||||||
|
"no-floating-decimal": "warn",
|
||||||
|
"no-implicit-coercion": "warn",
|
||||||
|
"no-implicit-globals": "warn",
|
||||||
|
"no-implied-eval": "warn",
|
||||||
|
"no-import-assign": "warn",
|
||||||
|
"no-invalid-this": "warn",
|
||||||
|
"no-iterator": "warn",
|
||||||
|
"no-label-var": "warn",
|
||||||
|
// "no-labels": "warn",
|
||||||
|
"no-lone-blocks": "warn",
|
||||||
|
"no-loop-func": "warn",
|
||||||
|
"no-mixed-requires": "warn",
|
||||||
|
"no-multi-assign": "warn",
|
||||||
|
"no-multi-spaces": "warn",
|
||||||
|
"no-multi-str": "warn",
|
||||||
|
"no-multiple-empty-lines": "warn",
|
||||||
|
"no-native-reassign": "warn",
|
||||||
|
"no-negated-in-lhs": "warn",
|
||||||
|
"no-nested-ternary": "warn",
|
||||||
|
"no-new": "warn",
|
||||||
|
"no-new-func": "warn",
|
||||||
|
"no-new-object": "warn",
|
||||||
|
"no-new-require": "warn",
|
||||||
|
"no-new-wrappers": "warn",
|
||||||
|
"no-octal-escape": "warn",
|
||||||
|
"no-path-concat": "warn",
|
||||||
|
"no-process-exit": "warn",
|
||||||
|
"no-proto": "warn",
|
||||||
|
"no-restricted-globals": "warn",
|
||||||
|
"no-restricted-imports": "warn",
|
||||||
|
"no-restricted-modules": "warn",
|
||||||
|
"no-restricted-properties": "warn",
|
||||||
|
"no-restricted-syntax": "warn",
|
||||||
|
"no-return-assign": "warn",
|
||||||
|
"no-return-await": "warn",
|
||||||
|
"no-script-url": "warn",
|
||||||
|
"no-self-compare": "warn",
|
||||||
|
"no-sequences": "warn",
|
||||||
|
"no-setter-return": "warn",
|
||||||
|
"no-spaced-func": "warn",
|
||||||
|
"no-tabs": "warn",
|
||||||
|
"no-template-curly-in-string": "warn",
|
||||||
|
"no-throw-literal": "warn",
|
||||||
|
"no-undef-init": "warn",
|
||||||
|
"no-unmodified-loop-condition": "warn",
|
||||||
|
"no-unneeded-ternary": "warn",
|
||||||
|
"no-unused-expressions": "warn",
|
||||||
|
"no-use-before-define": "warn",
|
||||||
|
"no-useless-call": "warn",
|
||||||
|
"no-useless-computed-key": "warn",
|
||||||
|
"no-useless-concat": "warn",
|
||||||
|
"no-useless-constructor": "warn",
|
||||||
|
"no-useless-rename": "warn",
|
||||||
|
"no-useless-return": "warn",
|
||||||
|
"no-var": "warn",
|
||||||
|
"no-void": "warn",
|
||||||
|
"no-whitespace-before-property": "warn",
|
||||||
|
"nonblock-statement-body-position": "warn",
|
||||||
|
"object-curly-spacing": [
|
||||||
|
"warn",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"object-shorthand": "warn",
|
||||||
|
"one-var-declaration-per-line": "warn",
|
||||||
|
"operator-assignment": "warn",
|
||||||
|
"padding-line-between-statements": "warn",
|
||||||
|
"prefer-arrow-callback": "warn",
|
||||||
|
"prefer-const": "warn",
|
||||||
|
"prefer-destructuring": "warn",
|
||||||
|
"prefer-exponentiation-operator": "warn",
|
||||||
|
"prefer-numeric-literals": "warn",
|
||||||
|
"prefer-object-spread": "warn",
|
||||||
|
"prefer-promise-reject-errors": "warn",
|
||||||
|
"prefer-regex-literals": "warn",
|
||||||
|
"prefer-rest-params": "warn",
|
||||||
|
"prefer-spread": "warn",
|
||||||
|
"require-jsdoc": "warn",
|
||||||
|
"require-unicode-regexp": "warn",
|
||||||
|
"rest-spread-spacing": "warn",
|
||||||
|
"semi": "warn",
|
||||||
|
"semi-spacing": "warn",
|
||||||
|
"semi-style": [
|
||||||
|
"warn",
|
||||||
|
"last"
|
||||||
|
],
|
||||||
|
"space-before-blocks": "warn",
|
||||||
|
"space-in-parens": [
|
||||||
|
"warn",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"switch-colon-spacing": "warn",
|
||||||
|
"symbol-description": "warn",
|
||||||
|
"template-curly-spacing": [
|
||||||
|
"warn",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"template-tag-spacing": "warn",
|
||||||
|
"unicode-bom": [
|
||||||
|
"warn",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"vars-on-top": "warn",
|
||||||
|
"wrap-iife": "warn",
|
||||||
|
"wrap-regex": "warn",
|
||||||
|
"yield-star-spacing": "warn",
|
||||||
|
"yoda": [
|
||||||
|
"warn",
|
||||||
|
"never"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Env
|
||||||
|
config.js
|
||||||
|
|
||||||
|
# Node bs
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Logs & cache
|
||||||
|
logs
|
||||||
|
modmail_cache
|
5
index.js
Normal file
5
index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const Options = require('./config');
|
||||||
|
const { Client } = require('./structure');
|
||||||
|
|
||||||
|
const client = new Client(Options);
|
||||||
|
client.init();
|
77
logger/Logger.js
Normal file
77
logger/Logger.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
const { createLogger, format, transports: { Console }, config } = require('winston');
|
||||||
|
const moment = require('moment');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
|
||||||
|
const { DiscordWebhook, FileExtension } = require('./transports/index.js');
|
||||||
|
|
||||||
|
const Constants = {
|
||||||
|
Colors: {
|
||||||
|
error: 'red',
|
||||||
|
warn: 'yellow',
|
||||||
|
info: 'blue',
|
||||||
|
verbose: 'cyan',
|
||||||
|
debug: 'magenta',
|
||||||
|
silly: 'magentaBright'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
|
||||||
|
constructor(client, options) {
|
||||||
|
this.client = client;
|
||||||
|
this.options = options;
|
||||||
|
|
||||||
|
const transports = [
|
||||||
|
new FileExtension({ filename: `logs/${this.date.split(' ')[0]}.log`, level: 'debug' }), //Will NOT log "silly" logs, could change in future.
|
||||||
|
new FileExtension({ filename: `logs/errors/${this.date.split(' ')[0]}-error.log`, level: 'error' }),
|
||||||
|
new Console({ level: 'silly' }) //Will log EVERYTHING.
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!options.webhook.disabled) transports.push(new DiscordWebhook({ level: 'error', ...options.webhook })); //Broadcast errors to a discord webhook.
|
||||||
|
|
||||||
|
this.logger = createLogger({
|
||||||
|
levels: config.npm.levels,
|
||||||
|
format:
|
||||||
|
format.cli({
|
||||||
|
colors: Constants.Colors
|
||||||
|
}),
|
||||||
|
transports
|
||||||
|
});
|
||||||
|
|
||||||
|
//TODO: Add proper date-oriented filenames and add a daily rotation file (?).
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
write(type = 'silly', string = '') {
|
||||||
|
|
||||||
|
const color = Constants.Colors[type];
|
||||||
|
const header = `${chalk[color](`[${this.date}][modmail]`)}`;
|
||||||
|
|
||||||
|
|
||||||
|
this.logger.log(type, `${header} : ${string}`);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get date() {
|
||||||
|
return moment().format("YYYY-MM-DD hh:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
info(message) {
|
||||||
|
this.write('info', message);
|
||||||
|
}
|
||||||
|
|
||||||
|
warn(message) {
|
||||||
|
this.write('warn', message);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(message) {
|
||||||
|
this.write('error', message);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(message) {
|
||||||
|
this.write('debug', message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Logger;
|
3
logger/index.js
Normal file
3
logger/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
Logger: require('./Logger')
|
||||||
|
};
|
50
logger/transports/DiscordWebhook.js
Normal file
50
logger/transports/DiscordWebhook.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
const Transport = require('winston-transport');
|
||||||
|
const { WebhookClient } = require('discord.js');
|
||||||
|
const os = require('os');
|
||||||
|
const { username } = os.userInfo();
|
||||||
|
|
||||||
|
//eslint-disable-next-line no-control-regex
|
||||||
|
const regex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/gu;
|
||||||
|
|
||||||
|
class DiscordWebhook extends Transport {
|
||||||
|
constructor(opts) {
|
||||||
|
super(opts);
|
||||||
|
|
||||||
|
this.webhookClient = new WebhookClient(
|
||||||
|
opts.id,
|
||||||
|
opts.token
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
log(info, callback) {
|
||||||
|
setImmediate(() => {
|
||||||
|
this.emit('logged', info);
|
||||||
|
});
|
||||||
|
|
||||||
|
const message = info.message.replace(regex, '')
|
||||||
|
//.replace(new RegExp(options.bot.token, 'gu'), '<redacted>')
|
||||||
|
.replace(new RegExp(username, 'gu'), '<redacted>');
|
||||||
|
|
||||||
|
const developers = [
|
||||||
|
'nolan',
|
||||||
|
'navy',
|
||||||
|
'sema'
|
||||||
|
];
|
||||||
|
const random = developers[Math.floor(Math.random() * developers.length)];
|
||||||
|
|
||||||
|
const embed = {
|
||||||
|
color: 0xe88388,
|
||||||
|
timestamp: new Date(),
|
||||||
|
description: `\`\`\`${message}\`\`\``,
|
||||||
|
footer: {
|
||||||
|
text: `probably ${random}'s fault`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.webhookClient.send('', { embeds: [embed] });
|
||||||
|
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DiscordWebhook;
|
119
logger/transports/FileExtension.js
Normal file
119
logger/transports/FileExtension.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
const { transports: { File } } = require('winston');
|
||||||
|
const diagnostics = require('diagnostics');
|
||||||
|
const debug = diagnostics('winston:file');
|
||||||
|
const { MESSAGE } = require('triple-beam');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
|
const regex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
|
||||||
|
|
||||||
|
class FileExtension extends File {
|
||||||
|
|
||||||
|
constructor(opts) {
|
||||||
|
super(opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
log(info, callback = () => {}) {
|
||||||
|
// Remark: (jcrugzz) What is necessary about this callback(null, true) now
|
||||||
|
// when thinking about 3.x? Should silent be handled in the base
|
||||||
|
// TransportStream _write method?
|
||||||
|
if (this.silent) {
|
||||||
|
callback();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output stream buffer is full and has asked us to wait for the drain event
|
||||||
|
if (this._drain) {
|
||||||
|
this._stream.once('drain', () => {
|
||||||
|
this._drain = false;
|
||||||
|
this.log(info, callback);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this._rotate) {
|
||||||
|
this._stream.once('rotate', () => {
|
||||||
|
this._rotate = false;
|
||||||
|
this.log(info, callback);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the raw string and append the expected EOL.
|
||||||
|
const output = `${info[MESSAGE]}${this.eol}`.replace(regex, '');
|
||||||
|
const bytes = Buffer.byteLength(output);
|
||||||
|
|
||||||
|
// After we have written to the PassThrough check to see if we need
|
||||||
|
// to rotate to the next file.
|
||||||
|
//
|
||||||
|
// Remark: This gets called too early and does not depict when data
|
||||||
|
// has been actually flushed to disk.
|
||||||
|
function logged() {
|
||||||
|
this._size += bytes;
|
||||||
|
this._pendingSize -= bytes;
|
||||||
|
|
||||||
|
debug('logged %s %s', this._size, output);
|
||||||
|
this.emit('logged', info);
|
||||||
|
|
||||||
|
// Do not attempt to rotate files while opening
|
||||||
|
if (this._opening) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if we need to end the stream and create a new one.
|
||||||
|
if (!this._needsNewFile()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End the current stream, ensure it flushes and create a new one.
|
||||||
|
// This could potentially be optimized to not run a stat call but its
|
||||||
|
// the safest way since we are supporting `maxFiles`.
|
||||||
|
this._rotate = true;
|
||||||
|
this._endStream(() => this._rotateFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of the pending bytes being written while files are opening
|
||||||
|
// in order to properly rotate the PassThrough this._stream when the file
|
||||||
|
// eventually does open.
|
||||||
|
this._pendingSize += bytes;
|
||||||
|
if (this._opening
|
||||||
|
&& !this.rotatedWhileOpening
|
||||||
|
&& this._needsNewFile(this._size + this._pendingSize)) {
|
||||||
|
this.rotatedWhileOpening = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const written = this._stream.write(output, logged.bind(this));
|
||||||
|
if (!written) {
|
||||||
|
this._drain = true;
|
||||||
|
this._stream.once('drain', () => {
|
||||||
|
this._drain = false;
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
callback(); // eslint-disable-line callback-return
|
||||||
|
}
|
||||||
|
|
||||||
|
debug('written', written, this._drain);
|
||||||
|
|
||||||
|
this.finishIfEnding();
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
get date() {
|
||||||
|
return moment().format("MM-DD-YYYY hh:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const Constants = {
|
||||||
|
Colors: {
|
||||||
|
error: 'red',
|
||||||
|
warn: 'yellow',
|
||||||
|
info: 'blue',
|
||||||
|
verbose: 'cyan',
|
||||||
|
debug: 'magenta',
|
||||||
|
silly: 'magentaBright'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = FileExtension;
|
4
logger/transports/index.js
Normal file
4
logger/transports/index.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
DiscordWebhook: require('./DiscordWebhook.js'),
|
||||||
|
FileExtension: require('./FileExtension.js')
|
||||||
|
};
|
25
package.json
Normal file
25
package.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "modmail",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"author": "Navy <navydotgif@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"private": false,
|
||||||
|
"description": "Modmail bot with eventual integration with Galactic Bot's API",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node index.js",
|
||||||
|
"dev": "nodemon index.js"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^7.28.0",
|
||||||
|
"nodemon": "^2.0.7"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^4.1.1",
|
||||||
|
"diagnostics": "^2.0.2",
|
||||||
|
"discord.js": "^12.5.3",
|
||||||
|
"moment": "^2.29.1",
|
||||||
|
"winston": "^3.3.3",
|
||||||
|
"winston-transport": "^4.4.0"
|
||||||
|
}
|
||||||
|
}
|
50
structure/Client.js
Normal file
50
structure/Client.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
const { Client } = require('discord.js');
|
||||||
|
|
||||||
|
const { Logger } = require('../logger');
|
||||||
|
const Modmail = require('./Modmail');
|
||||||
|
const Registry = require('./Registry');
|
||||||
|
|
||||||
|
class ModmailClient extends Client {
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
|
|
||||||
|
super(options.clientOptions);
|
||||||
|
|
||||||
|
this._options = options;
|
||||||
|
this._ready = false;
|
||||||
|
|
||||||
|
this.logger = new Logger(this, options.loggerOptions);
|
||||||
|
this.modmail = new Modmail(this);
|
||||||
|
this.registry = new Registry(this);
|
||||||
|
|
||||||
|
this.on('ready', () => {
|
||||||
|
this.logger.info(`Client ready, logged in as ${this.user.tag}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
|
||||||
|
this.logger.info(`Logging in`);
|
||||||
|
await this.login(this._options.discordToken);
|
||||||
|
this.logger.info(`Starting up modmail`);
|
||||||
|
this.modmail.init();
|
||||||
|
this.registry.loadCommands();
|
||||||
|
|
||||||
|
this.on('message', this.handleMessage.bind(this));
|
||||||
|
|
||||||
|
this._ready = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleMessage(message) {
|
||||||
|
|
||||||
|
if (!message.guild) return this.modmail.handleUser(message);
|
||||||
|
|
||||||
|
const { channel, guild } = message;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ModmailClient;
|
21
structure/Command.js
Normal file
21
structure/Command.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
class Command {
|
||||||
|
|
||||||
|
constructor(client, options) {
|
||||||
|
|
||||||
|
Object.entries(options).forEach(([key, val]) => {
|
||||||
|
this[key] = val;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.name) throw new Error(`Missing name for command`);
|
||||||
|
|
||||||
|
this.client = client;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute() {
|
||||||
|
throw new Error(`Missing execute in ${this.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Command;
|
35
structure/Modmail.js
Normal file
35
structure/Modmail.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
class Modmail {
|
||||||
|
|
||||||
|
constructor(client) {
|
||||||
|
|
||||||
|
this.client = client;
|
||||||
|
this.mainServer = null;
|
||||||
|
this.bansServer = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
|
||||||
|
const { bansGuild, mainGuild } = this.client._options;
|
||||||
|
|
||||||
|
this.mainServer = this.client.guilds.cache.get(mainGuild);
|
||||||
|
if (!this.mainServer) throw new Error(`Missing main server: ${mainGuild} is not a valid server ID`);
|
||||||
|
|
||||||
|
this.bansServer = this.client.guilds.cache.get(bansGuild) || null;
|
||||||
|
this.client.logger.warn(`Missing bans server: ${bansGuild} is not a valid server ID`);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleUser(message) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleServer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Modmail;
|
40
structure/Registry.js
Normal file
40
structure/Registry.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
const { Collection } = require("discord.js");
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
class Registry {
|
||||||
|
|
||||||
|
constructor(client) {
|
||||||
|
|
||||||
|
this.client = client;
|
||||||
|
|
||||||
|
this.commands = new Collection();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCommands() {
|
||||||
|
|
||||||
|
const commandsDir = path.join(process.cwd(), 'structure', 'commands');
|
||||||
|
const files = fs.readdirSync(commandsDir);
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
|
||||||
|
const commandPath = path.join(commandsDir, file);
|
||||||
|
const commandClass = require(commandPath);
|
||||||
|
|
||||||
|
if (typeof commandClass !== 'function') {
|
||||||
|
delete require.cache[commandPath];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const command = new commandClass(this.client);
|
||||||
|
if (this.commands.has(command.name)) this.client.logger(`Command by name ${command.name} already exists, skipping duplicate at path ${commandPath}`);
|
||||||
|
else this.commands.set(command.name, command);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Registry;
|
13
structure/commands/Ping.js
Normal file
13
structure/commands/Ping.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const Command = require('../Command');
|
||||||
|
|
||||||
|
class Ping extends Command {
|
||||||
|
|
||||||
|
constructor(client) {
|
||||||
|
super(client, {
|
||||||
|
name: 'ping'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Ping;
|
3
structure/index.js
Normal file
3
structure/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
Client: require('./Client.js')
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user