wrapper related

This commit is contained in:
Erik 2022-03-26 22:16:56 +02:00
parent 0d50e925e6
commit 8e1e5c6c24
Signed by: Navy.gif
GPG Key ID: 811EC0CD80E7E5FB
2 changed files with 105 additions and 38 deletions

View File

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

View File

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