wrapper related
This commit is contained in:
parent
0d50e925e6
commit
8e1e5c6c24
@ -1,14 +1,15 @@
|
||||
const { Client } = require('discord.js');
|
||||
const { Client, Collection } = require('discord.js');
|
||||
const chalk = require('chalk');
|
||||
|
||||
const { Logger, Intercom, EventHooker, LocaleLoader, Registry, Dispatcher, Resolver } = require('./client/');
|
||||
const { Intercom, EventHooker, LocaleLoader, Registry, Dispatcher, Resolver, ModerationManager, RateLimiter } = require('./client/');
|
||||
const { Observer, Command, Setting, Inhibitor } = require('./interfaces/');
|
||||
const { Logger } = require('../utilities');
|
||||
const StorageManager = require('./storage/StorageManager.js');
|
||||
|
||||
const { DefaultGuild } = require('../constants/');
|
||||
const { DefaultGuild, DefaultUser } = require('../constants/');
|
||||
|
||||
const options = require('../../options.json');
|
||||
const RateLimiter = require('./client/RateLimiter');
|
||||
const { GuildWrapper, UserWrapper } = require('./client/wrappers');
|
||||
|
||||
const Constants = {
|
||||
ComponentTypes: {
|
||||
@ -29,7 +30,7 @@ class DiscordClient extends Client {
|
||||
...options.discord.clientOptions
|
||||
});
|
||||
|
||||
this.logger = new Logger(this);
|
||||
this.logger = new Logger({ name: 'Client' });
|
||||
this.eventHooker = new EventHooker(this);
|
||||
this.intercom = new Intercom(this);
|
||||
this.dispatcher = new Dispatcher(this);
|
||||
@ -38,12 +39,16 @@ class DiscordClient extends Client {
|
||||
this.registry = new Registry(this);
|
||||
this.resolver = new Resolver(this);
|
||||
this.rateLimiter = new RateLimiter(this);
|
||||
this.moderationManager = new ModerationManager(this);
|
||||
|
||||
// Originally used for evals, but being replaced by the wrappers collections
|
||||
this.wrapperClasses = {
|
||||
...require('./client/wrappers')
|
||||
};
|
||||
this.guildWrappers = new Collection();
|
||||
this.userWrappers = new Collection();
|
||||
|
||||
this._defaultConfig = null;
|
||||
this._defaultConfig = {};
|
||||
this._activity = 0;
|
||||
this._options = options;
|
||||
this._built = false;
|
||||
@ -58,6 +63,14 @@ class DiscordClient extends Client {
|
||||
|
||||
this._loadEevents();
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
this.logger.error(`Uncaught exception:\n${err.stack || err}`);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (err) => {
|
||||
this.logger.error(`Unhandled rejection:\n${err.stack || err}`);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async build() {
|
||||
@ -85,17 +98,31 @@ class DiscordClient extends Client {
|
||||
this.logger.info(`Built client in ${Date.now()-beforeTime}ms.`);
|
||||
|
||||
await super.login();
|
||||
await this.ready();
|
||||
|
||||
this.emit('built');
|
||||
this._built = true;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
defaultConfig() {
|
||||
if(this._defaultConfig) return this._defaultConfig;
|
||||
const settings = this.registry.components.filter((c) => c._type === 'setting');
|
||||
let def = DefaultGuild;
|
||||
// Wait until the client is actually ready, i.e. all structures from discord are created
|
||||
ready() {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
if (this._built) return resolve();
|
||||
this.once('ready', () => {
|
||||
this._createWrappers();
|
||||
this._built = true;
|
||||
this.emit('built');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
defaultConfig(type) {
|
||||
if(this._defaultConfig[type]) return this._defaultConfig[type];
|
||||
const settings = this.registry.components.filter((c) => c._type === 'setting' && c.resolve === type);
|
||||
let def = type === 'GUILD' ? DefaultGuild : DefaultUser;
|
||||
for(const setting of settings.values()) {
|
||||
if(setting.default !== null) {
|
||||
def = {
|
||||
@ -104,7 +131,7 @@ class DiscordClient extends Client {
|
||||
};
|
||||
}
|
||||
}
|
||||
this._defaultConfig = def;
|
||||
this._defaultConfig[type] = def;
|
||||
return def;
|
||||
}
|
||||
|
||||
@ -140,7 +167,7 @@ class DiscordClient extends Client {
|
||||
|
||||
this.eventHooker.hook('ready', () => {
|
||||
const guilds = this.guilds.cache.size;
|
||||
this.logger.info(`Client connected to ${chalk.bold(this.user.tag)} with ${chalk.bold(`${guilds} guild${guilds === 1 ? '' : 's'}`)}.`);
|
||||
this.logger.status(`Client ready, connected to ${chalk.bold(this.user.tag)} with ${chalk.bold(`${guilds} guild${guilds === 1 ? '' : 's'}`)}.`);
|
||||
});
|
||||
|
||||
this.eventHooker.hook('componentUpdate', ({ component, type }) => {
|
||||
@ -149,10 +176,12 @@ class DiscordClient extends Client {
|
||||
|
||||
this.eventHooker.hook('guildCreate', (guild) => {
|
||||
this.logger.debug(`${chalk.bold('[GUILD]')} Joined guild ${chalk.bold(guild.name)} (${guild.id}).`);
|
||||
this.guildWrappers.set(guild.id, new GuildWrapper(this, guild));
|
||||
});
|
||||
|
||||
this.eventHooker.hook('guildDelete', (guild) => {
|
||||
this.logger.debug(`${chalk.bold('[GUILD]')} Left guild ${chalk.bold(guild.name)} (${guild.id}).`);
|
||||
this.guildWrappers.delete(guild.id);
|
||||
});
|
||||
|
||||
this.eventHooker.hook('shardDisconect', () => {
|
||||
@ -177,6 +206,39 @@ class DiscordClient extends Client {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_createWrappers() {
|
||||
|
||||
this.guilds.cache.forEach((guild) => {
|
||||
this.guildWrappers.set(guild.id, new GuildWrapper(this, guild));
|
||||
});
|
||||
this.logger.info(`Created guild wrappers`);
|
||||
|
||||
}
|
||||
|
||||
getGuildWrapper(id) {
|
||||
|
||||
if (this.guildWrappers.has(id)) return this.guildWrappers.get(id);
|
||||
|
||||
const wrapper = new GuildWrapper(this, this.guilds.cache.get(id));
|
||||
this.guildWrappers.set(id, wrapper);
|
||||
return wrapper;
|
||||
|
||||
}
|
||||
|
||||
async getUserWrapper(id) {
|
||||
|
||||
if (this.userWrappers.has(id)) return this.userWrappers.get(id);
|
||||
|
||||
const user = await this.users.fetch(id);
|
||||
const wrapper = new UserWrapper(this, user);
|
||||
this.userWrappers.set(id, wrapper);
|
||||
return wrapper;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = DiscordClient;
|
||||
|
@ -1,11 +1,11 @@
|
||||
const { stripIndents } = require('common-tags');
|
||||
const { User } = require('discord.js');
|
||||
const { User, GuildMember } = require('discord.js');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
|
||||
const { Emojis, Constants } = require('../../constants');
|
||||
const Util = require('../../Util.js');
|
||||
const { Util, Logger } = require('../../utilities');
|
||||
const { Warn, Unmute, Mute, Kick, Softban, Unban, Ban, Addrole, Removerole, Lockdown, Unlockdown } = require('../components/infractions');
|
||||
const Logger = require('./Logger');
|
||||
|
||||
const Constant = {
|
||||
MaxTargets: 10, //10+(10*premium-tier), theoretical max = 40
|
||||
Infractions: {
|
||||
@ -36,7 +36,7 @@ class ModerationManager {
|
||||
|
||||
this.client = client;
|
||||
this.callbacks = new Collection();
|
||||
this.logger = new Logger(this);
|
||||
this.logger = new Logger({ name: 'ModMngr' });
|
||||
|
||||
}
|
||||
|
||||
@ -189,39 +189,45 @@ class ModerationManager {
|
||||
|
||||
}
|
||||
|
||||
async handleAutomod(Infraction, info) {
|
||||
|
||||
}
|
||||
|
||||
async _handleTarget(Infraction, target, info) {
|
||||
const { guild, reason, force } = info;
|
||||
const { autoModeration, moderationPoints } = guild._settings;
|
||||
|
||||
const { reason, force, wrapper } = info;
|
||||
const { automod, modpoints } = wrapper._settings;
|
||||
const { type } = Infraction;
|
||||
const { guild } = wrapper;
|
||||
const targetWrapper = target instanceof User || target instanceof GuildMember ?
|
||||
await this.client.getUserWrapper(target.id) :
|
||||
target; // TODO: Channel wrapper if necessary
|
||||
|
||||
let points = 0,
|
||||
expiration = 0;
|
||||
if (moderationPoints.enabled) {
|
||||
points = info.points || moderationPoints.points[type];
|
||||
expiration = info.expiration || moderationPoints.expirations[type];
|
||||
for (const [phrase, amount] of Object.entries(moderationPoints.associations)) {
|
||||
if (modpoints.enabled) {
|
||||
points = info.points || modpoints.points[type];
|
||||
expiration = info.expiration || modpoints.expirations[type];
|
||||
for (const [phrase, amount] of Object.entries(modpoints.associations)) {
|
||||
if (reason.toLowerCase().includes(phrase)) points = amount;
|
||||
}
|
||||
}
|
||||
|
||||
const verify = async (infraction, escalated = false) => {
|
||||
|
||||
let verification = infraction.verify(info.executor, target, info.channel);
|
||||
if (verification instanceof Promise) verification = await verification;
|
||||
const verification = await infraction.verify(info.executor, target, info.channel);
|
||||
|
||||
if (verification.error) return verification;
|
||||
|
||||
if (infraction.targetType === 'USER') {
|
||||
const userTarget = target instanceof User ? target : target.user;
|
||||
const oldPoints = await userTarget.totalPoints(guild);
|
||||
|
||||
const oldPoints = await targetWrapper.totalPoints(guild);
|
||||
const newPoints = oldPoints + infraction.points;
|
||||
if (autoModeration.enabled && points > 0 && !force && !escalated) {
|
||||
if (automod.enabled && points > 0 && !force && !escalated) {
|
||||
let result = null;
|
||||
for (let [threshold, action] of Object.entries(autoModeration.thresholds)) { //eslint-disable-line prefer-const
|
||||
for (let [threshold, action] of Object.entries(automod.thresholds)) { //eslint-disable-line prefer-const
|
||||
threshold = parseInt(threshold);
|
||||
if (oldPoints >= threshold) {
|
||||
if (autoModeration.usePrevious) {
|
||||
if (automod.usePrevious) {
|
||||
result = {
|
||||
threshold,
|
||||
...action
|
||||
@ -255,7 +261,7 @@ class ModerationManager {
|
||||
type,
|
||||
message: info.message || null,
|
||||
arguments: info.arguments,
|
||||
guild: info.guild,
|
||||
guild: info.wrapper,
|
||||
channel: info.channel,
|
||||
executor: info.executor,
|
||||
reason: info.reason,
|
||||
@ -276,11 +282,11 @@ class ModerationManager {
|
||||
message: info.message || null,
|
||||
arguments: info.arguments,
|
||||
type: escalationClass.type,
|
||||
guild: info.guild,
|
||||
guild: info.wrapper,
|
||||
channel: info.channel,
|
||||
executor: info.executor,
|
||||
reason: stripIndents`${reason}
|
||||
*${guild.format('INFRACTION_AUTOMODESCALATION')}*`,
|
||||
*${wrapper.format('INFRACTION_AUTOMODESCALATION')}*`,
|
||||
duration: info.duration,
|
||||
data: info.data,
|
||||
points,
|
||||
@ -294,7 +300,7 @@ class ModerationManager {
|
||||
if (response.error) return response;
|
||||
|
||||
if (response.infraction.targetType === 'USER') {
|
||||
response.infraction.totalPoints = await response.infraction.target.totalPoints(guild, {
|
||||
response.infraction.totalPoints = await targetWrapper.totalPoints(guild, {
|
||||
points, expiration, timestamp: response.infraction.timestamp
|
||||
});
|
||||
}
|
||||
@ -324,8 +330,7 @@ class ModerationManager {
|
||||
for (const arg of Object.values(message.arguments)) {
|
||||
// console.log(arg, targets);
|
||||
if (actions[arg.name]) {
|
||||
let action = actions[arg.name](message, arg, targets);
|
||||
if (action instanceof Promise) action = await action;
|
||||
const action = await actions[arg.name](message, arg, targets);
|
||||
responses[arg.name] = action;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user