changes to class & add Moderation class on Util
parent
7449aedd92
commit
dc09c42923
|
@ -1,24 +1,47 @@
|
||||||
import eris from 'eris';
|
import eris from 'eris';
|
||||||
|
import mongoose from 'mongoose';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { Collection, Command, Util } from '.';
|
import { Collection, Command, Util } from '.';
|
||||||
|
import { Moderation, ModerationInterface } from '../models';
|
||||||
|
|
||||||
export default class Client extends eris.Client {
|
export default class Client extends eris.Client {
|
||||||
public config: { token: string, prefix: string, guildID: string };
|
public config: { token: string, prefix: string, guildID: string, mongoDB: string };
|
||||||
|
|
||||||
public commands: Collection<Command>;
|
public commands: Collection<Command>;
|
||||||
|
|
||||||
|
public intervals: Collection<NodeJS.Timeout>;
|
||||||
|
|
||||||
public util: Util;
|
public util: Util;
|
||||||
|
|
||||||
|
public db: { moderation: mongoose.Model<ModerationInterface> };
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
constructor(token: string, options?: eris.ClientOptions) {
|
constructor(token: string, options?: eris.ClientOptions) {
|
||||||
super(token, options);
|
super(token, options);
|
||||||
this.commands = new Collection<Command>();
|
this.commands = new Collection<Command>();
|
||||||
|
this.intervals = new Collection<NodeJS.Timeout>();
|
||||||
|
this.db = { moderation: Moderation };
|
||||||
|
}
|
||||||
|
|
||||||
|
public async loadDatabase() {
|
||||||
|
await mongoose.connect(this.config.mongoDB, { useNewUrlParser: true, useUnifiedTopology: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadPlugins() {
|
public loadPlugins() {
|
||||||
this.util = new Util(this);
|
this.util = new Util(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async loadIntervals() {
|
||||||
|
const intervalFiles = await fs.readdir(`${__dirname}/../intervals`);
|
||||||
|
intervalFiles.forEach((file) => {
|
||||||
|
const intervalName = file.split('.')[0];
|
||||||
|
if (file === 'index.js') return;
|
||||||
|
const interval: NodeJS.Timeout = (require(`${__dirname}/../intervals/${file}`).default)(this);
|
||||||
|
this.intervals.add(intervalName, interval);
|
||||||
|
this.util.signale.success(`Successfully loaded interval: ${intervalName}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async loadEvents() {
|
public async loadEvents() {
|
||||||
const evtFiles = await fs.readdir(`${__dirname}/../events`);
|
const evtFiles = await fs.readdir(`${__dirname}/../events`);
|
||||||
evtFiles.forEach((file) => {
|
evtFiles.forEach((file) => {
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* eslint-disable no-bitwise */
|
||||||
|
import { Member } from 'eris';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
import moment, { unitOfTime } from 'moment';
|
||||||
|
import { Client, RichEmbed } from '.';
|
||||||
|
import { Moderation as ModerationModel, ModerationInterface } from '../models';
|
||||||
|
import { moderation as channels } from '../configs/channels.json';
|
||||||
|
|
||||||
|
export default class Moderation {
|
||||||
|
public client: Client;
|
||||||
|
|
||||||
|
public logChannels: {
|
||||||
|
modlogs: string
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(client: Client) {
|
||||||
|
this.client = client;
|
||||||
|
this.logChannels.modlogs = channels.modlogs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public checkPermissions(member: Member, moderator: Member): boolean {
|
||||||
|
if (member.id === moderator.id) return false;
|
||||||
|
if (member.roles.some((r) => ['662163685439045632', '455972169449734144', '453689940140883988'].includes(r))) return false;
|
||||||
|
const bit = member.permission.allow;
|
||||||
|
if ((bit | 8) === bit) return false;
|
||||||
|
if ((bit | 20) === bit) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts some sort of time based duration to milliseconds based on length.
|
||||||
|
* @param time The time, examples: 2h, 1m, 1w
|
||||||
|
*/
|
||||||
|
public convertTimeDurationToMilliseconds(time: string): number {
|
||||||
|
const lockLength = time.match(/[a-z]+|[^a-z]+/gi);
|
||||||
|
const length = Number(lockLength[0]);
|
||||||
|
const unit = lockLength[1] as unitOfTime.Base;
|
||||||
|
return moment.duration(length, unit).asMilliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ban(member: Member, moderator: Member, duration: number, reason?: string): Promise<ModerationInterface> {
|
||||||
|
await member.ban(7, reason);
|
||||||
|
const logID = uuid();
|
||||||
|
const mod = new ModerationModel({
|
||||||
|
userID: member.id,
|
||||||
|
logID,
|
||||||
|
moderatorID: moderator.id,
|
||||||
|
reason: reason ?? null,
|
||||||
|
type: 5,
|
||||||
|
date: new Date(),
|
||||||
|
});
|
||||||
|
const now: number = Date.now();
|
||||||
|
let date: Date;
|
||||||
|
let processed = true;
|
||||||
|
if (duration > 0) {
|
||||||
|
date = new Date(now + duration);
|
||||||
|
processed = false;
|
||||||
|
} else date = null;
|
||||||
|
const expiration = { date, processed };
|
||||||
|
mod.expiration = expiration;
|
||||||
|
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle(`Case ${logID} | Ban`);
|
||||||
|
embed.setAuthor(member.user.username, member.user.avatarURL);
|
||||||
|
embed.setThumbnail(member.user.avatarURL);
|
||||||
|
embed.addField('User', `<@${member.id}>`, true);
|
||||||
|
embed.addField('Moderator', `<@${moderator.id}>`, true);
|
||||||
|
if (reason) {
|
||||||
|
embed.addField('Reason', reason, true);
|
||||||
|
}
|
||||||
|
if (date) {
|
||||||
|
embed.addField('Expiration', moment(date).calendar(), true);
|
||||||
|
}
|
||||||
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
embed.setTimestamp();
|
||||||
|
this.client.createMessage(this.logChannels.modlogs, { embed });
|
||||||
|
return mod.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async unban(userID: string, moderator: Member, reason?: string): Promise<ModerationInterface> {
|
||||||
|
this.client.unbanGuildMember(this.client.config.guildID, userID, reason);
|
||||||
|
const user = await this.client.getRESTUser(userID);
|
||||||
|
if (!user) throw new Error('Cannot get user.');
|
||||||
|
const logID = uuid();
|
||||||
|
const mod = new ModerationModel({
|
||||||
|
userID,
|
||||||
|
logID,
|
||||||
|
moderatorID: moderator.id,
|
||||||
|
reason: reason ?? null,
|
||||||
|
type: 4,
|
||||||
|
date: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle(`Case ${logID} | Unban`);
|
||||||
|
embed.setAuthor(user.username, user.avatarURL);
|
||||||
|
embed.setThumbnail(user.avatarURL);
|
||||||
|
embed.addField('User', `<@${user.id}>`, true);
|
||||||
|
embed.addField('Moderator', `<@${moderator.id}>`, true);
|
||||||
|
if (reason) {
|
||||||
|
embed.addField('Reason', reason, true);
|
||||||
|
}
|
||||||
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
embed.setTimestamp();
|
||||||
|
this.client.createMessage(this.logChannels.modlogs, { embed });
|
||||||
|
return mod.save();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,18 @@
|
||||||
import signale from 'signale';
|
import signale from 'signale';
|
||||||
import { Member, Message, Guild, PrivateChannel, GroupChannel, Role, AnyGuildChannel } from 'eris';
|
import { Member, Message, Guild, PrivateChannel, GroupChannel, Role, AnyGuildChannel } from 'eris';
|
||||||
import { Client, Command, RichEmbed } from '.';
|
import { Client, Command, Moderation, RichEmbed } from '.';
|
||||||
import { statusMessages as emotes } from '../configs/emotes.json';
|
import { statusMessages as emotes } from '../configs/emotes.json';
|
||||||
|
|
||||||
export default class Util {
|
export default class Util {
|
||||||
public client: Client;
|
public client: Client;
|
||||||
|
|
||||||
|
public moderation: Moderation;
|
||||||
|
|
||||||
public signale: signale.Signale;
|
public signale: signale.Signale;
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
this.moderation = new Moderation(this.client);
|
||||||
this.signale = signale;
|
this.signale = signale;
|
||||||
this.signale.config({
|
this.signale.config({
|
||||||
displayDate: true,
|
displayDate: true,
|
||||||
|
@ -49,7 +52,7 @@ export default class Util {
|
||||||
|
|
||||||
public resolveGuildChannel(query: string, { channels }: Guild): AnyGuildChannel | undefined {
|
public resolveGuildChannel(query: string, { channels }: Guild): AnyGuildChannel | undefined {
|
||||||
let queries = query.split(' ').slice(0, 10).join(' ');
|
let queries = query.split(' ').slice(0, 10).join(' ');
|
||||||
const nchannels = channels.map(c => c).sort((a: AnyGuildChannel, b: AnyGuildChannel) => a.type - b.type);
|
const nchannels = channels.map((c) => c).sort((a: AnyGuildChannel, b: AnyGuildChannel) => a.type - b.type);
|
||||||
let channel = nchannels.find((c) => (c.id === queries || c.name === queries || c.name.toLowerCase() === queries.toLowerCase() || c.name.toLowerCase().startsWith(queries.toLowerCase())));
|
let channel = nchannels.find((c) => (c.id === queries || c.name === queries || c.name.toLowerCase() === queries.toLowerCase() || c.name.toLowerCase().startsWith(queries.toLowerCase())));
|
||||||
if (!channel && queries.split(' ').length > 0) {
|
if (!channel && queries.split(' ').length > 0) {
|
||||||
while (!channel && queries.split(' ').length > 1) {
|
while (!channel && queries.split(' ').length > 1) {
|
||||||
|
@ -84,7 +87,9 @@ export default class Util {
|
||||||
queries = queries.split(' ').slice(0, queries.length - 1).join(' ');
|
queries = queries.split(' ').slice(0, queries.length - 1).join(' ');
|
||||||
// eslint-disable-next-line no-loop-func
|
// eslint-disable-next-line no-loop-func
|
||||||
member = members.find((m) => m.mention.replace('!', '') === queries.replace('!', '') || `${m.username}#${m.discriminator}` === query || m.username === queries || m.id === queries || m.nick === queries) // Exact match for mention, username+discrim, username and user ID
|
member = members.find((m) => m.mention.replace('!', '') === queries.replace('!', '') || `${m.username}#${m.discriminator}` === query || m.username === queries || m.id === queries || m.nick === queries) // Exact match for mention, username+discrim, username and user ID
|
||||||
|
// eslint-disable-next-line no-loop-func
|
||||||
|| members.find((m) => `${m.username.toLowerCase()}#${m.discriminator}` === queries.toLowerCase() || m.username.toLowerCase() === queries.toLowerCase() || (m.nick && m.nick.toLowerCase() === queries.toLowerCase())) // Case insensitive match for username+discrim, username
|
|| members.find((m) => `${m.username.toLowerCase()}#${m.discriminator}` === queries.toLowerCase() || m.username.toLowerCase() === queries.toLowerCase() || (m.nick && m.nick.toLowerCase() === queries.toLowerCase())) // Case insensitive match for username+discrim, username
|
||||||
|
// eslint-disable-next-line no-loop-func
|
||||||
|| members.find((m) => m.username.toLowerCase().startsWith(queries.toLowerCase()) || (m.nick && m.nick.toLowerCase().startsWith(queries.toLowerCase())));
|
|| members.find((m) => m.username.toLowerCase().startsWith(queries.toLowerCase()) || (m.nick && m.nick.toLowerCase().startsWith(queries.toLowerCase())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,4 +124,23 @@ export default class Util {
|
||||||
this.signale.error(err);
|
this.signale.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public splitString(string: string, length: number): string[] {
|
||||||
|
if (!string) return [];
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
if (Array.isArray(string)) string = string.join('\n');
|
||||||
|
if (string.length <= length) return [string];
|
||||||
|
const arrayString: string[] = [];
|
||||||
|
let str: string = '';
|
||||||
|
let pos: number;
|
||||||
|
while (string.length > 0) {
|
||||||
|
pos = string.length > length ? string.lastIndexOf('\n', length) : string.length;
|
||||||
|
if (pos > length) pos = length;
|
||||||
|
str = string.substr(0, pos);
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
string = string.substr(pos);
|
||||||
|
arrayString.push(str);
|
||||||
|
}
|
||||||
|
return arrayString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export { default as Client } from './Client';
|
export { default as Client } from './Client';
|
||||||
export { default as Collection } from './Collection';
|
export { default as Collection } from './Collection';
|
||||||
export { default as Command } from './Command';
|
export { default as Command } from './Command';
|
||||||
|
export { default as Moderation } from './Moderation';
|
||||||
export { default as RichEmbed } from './RichEmbed';
|
export { default as RichEmbed } from './RichEmbed';
|
||||||
export { default as Util } from './Util';
|
export { default as Util } from './Util';
|
||||||
|
|
Loading…
Reference in New Issue