mute command, local storage class, and additional improvements
parent
c627367577
commit
9c119691a4
|
@ -12,3 +12,4 @@ build/config.yaml
|
||||||
# Build/Distribution Files
|
# Build/Distribution Files
|
||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
|
localstorage
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import eris from 'eris';
|
import eris from 'eris';
|
||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { Collection, Command, Util, ServerManagement, Event } from '.';
|
import { Collection, Command, LocalStorage, Util, ServerManagement, Event } from '.';
|
||||||
import { Member, MemberInterface, Moderation, ModerationInterface, PagerNumber, PagerNumberInterface, Rank, RankInterface, Redirect, RedirectInterface } from '../models';
|
import { Member, MemberInterface, Moderation, ModerationInterface, PagerNumber, PagerNumberInterface, Rank, RankInterface, Redirect, RedirectInterface } from '../models';
|
||||||
|
|
||||||
export default class Client extends eris.Client {
|
export default class Client extends eris.Client {
|
||||||
|
@ -17,14 +17,14 @@ export default class Client extends eris.Client {
|
||||||
|
|
||||||
public serverManagement: ServerManagement;
|
public serverManagement: ServerManagement;
|
||||||
|
|
||||||
public db: { Member: mongoose.Model<MemberInterface>, Moderation: mongoose.Model<ModerationInterface>, PagerNumber: mongoose.Model<PagerNumberInterface>, Rank: mongoose.Model<RankInterface>, Redirect: mongoose.Model<RedirectInterface> };
|
public db: { Member: mongoose.Model<MemberInterface>, Moderation: mongoose.Model<ModerationInterface>, PagerNumber: mongoose.Model<PagerNumberInterface>, Rank: mongoose.Model<RankInterface>, Redirect: mongoose.Model<RedirectInterface>, local: LocalStorage };
|
||||||
|
|
||||||
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.events = new Collection<Event>();
|
this.events = new Collection<Event>();
|
||||||
this.intervals = new Collection<NodeJS.Timeout>();
|
this.intervals = new Collection<NodeJS.Timeout>();
|
||||||
this.db = { Member, Moderation, PagerNumber, Rank, Redirect };
|
this.db = { Member, Moderation, PagerNumber, Rank, Redirect, local: new LocalStorage(this) };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadDatabase() {
|
public async loadDatabase() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Member, Message, TextableChannel } from 'eris';
|
import { Guild, Member, Message, TextableChannel } from 'eris';
|
||||||
import { Client } from '.';
|
import { Client } from '.';
|
||||||
|
|
||||||
export default class Command {
|
export default class Command {
|
||||||
|
@ -54,6 +54,10 @@ export default class Command {
|
||||||
this.aliases = [];
|
this.aliases = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get mainGuild() {
|
||||||
|
return this.client.guilds.get(this.client.config.guildID);
|
||||||
|
}
|
||||||
|
|
||||||
public checkPermissions(member: Member): boolean {
|
public checkPermissions(member: Member): boolean {
|
||||||
if (member.id === '278620217221971968' || member.id === '253600545972027394') return true;
|
if (member.id === '278620217221971968' || member.id === '253600545972027394') return true;
|
||||||
switch (this.permissions) {
|
switch (this.permissions) {
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/* eslint-disable no-constant-condition */
|
||||||
|
import { promises as fs, constants } from 'fs';
|
||||||
|
import { Client } from '.';
|
||||||
|
|
||||||
|
type JSONData = [{key: string, value: any}?];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistant local JSON-based storage.
|
||||||
|
* Auto-locking system to prevent corrupted data.
|
||||||
|
* @author Matthew <matthew@staff.libraryofcode.org>
|
||||||
|
*/
|
||||||
|
export default class LocalStorage {
|
||||||
|
private client: Client;
|
||||||
|
|
||||||
|
protected storagePath: string;
|
||||||
|
|
||||||
|
private locked: boolean = false;
|
||||||
|
|
||||||
|
constructor(client: Client, storagePath = `${__dirname}/../../localstorage`) {
|
||||||
|
this.client = client;
|
||||||
|
this.storagePath = storagePath;
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async init() {
|
||||||
|
try {
|
||||||
|
await fs.access(`${this.storagePath}/1.json`, constants.F_OK);
|
||||||
|
} catch {
|
||||||
|
const setup = [];
|
||||||
|
await fs.writeFile(`${this.storagePath}/1.json`, JSON.stringify(setup), { encoding: 'utf8' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves one data from the store.
|
||||||
|
* If the store has multiple entries for the same key, this function will only return the first entry.
|
||||||
|
* ```ts
|
||||||
|
* await LocalStorage.get<type>('data-key');
|
||||||
|
* ```
|
||||||
|
* @param key The key for the data entry.
|
||||||
|
*/
|
||||||
|
public async get<T>(key: string): Promise<T> {
|
||||||
|
while (true) {
|
||||||
|
if (!this.locked) break;
|
||||||
|
}
|
||||||
|
this.locked = true;
|
||||||
|
|
||||||
|
const file = await fs.readFile(`${this.storagePath}/1.json`, { encoding: 'utf8' });
|
||||||
|
this.locked = false;
|
||||||
|
const json: JSONData = JSON.parse(file);
|
||||||
|
const result = json.filter((data) => data.key === key);
|
||||||
|
if (!result[0]) return null;
|
||||||
|
return result[0].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves multiple data keys/values from the store.
|
||||||
|
* This function will return all of the values matching the key you provided exactly. Use `LocalStorage.get();` if possible.
|
||||||
|
* ```ts
|
||||||
|
* await LocalStorage.get<type>('data-key');
|
||||||
|
* @param key The key for the data entry.
|
||||||
|
*/
|
||||||
|
public async getMany<T>(key: string): Promise<{key: string, value: T}[]> {
|
||||||
|
while (true) {
|
||||||
|
if (!this.locked) break;
|
||||||
|
}
|
||||||
|
this.locked = true;
|
||||||
|
|
||||||
|
const file = await fs.readFile(`${this.storagePath}/1.json`, { encoding: 'utf8' });
|
||||||
|
this.locked = false;
|
||||||
|
const json: JSONData = JSON.parse(file);
|
||||||
|
const result = json.filter((data) => data.key === key);
|
||||||
|
if (result.length < 1) return null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a key/value pair and creates a new data entry.
|
||||||
|
* @param key The key for the data entry.
|
||||||
|
* @param value The value for the data entry, can be anything that is valid JSON.
|
||||||
|
* @param options.override [DEPRECATED] By default, this function will error if the key you're trying to set already exists. Set this option to true to override that setting.
|
||||||
|
* ```ts
|
||||||
|
* await LocalStorage.set('data-key', 'test');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
public async set(key: string, value: any): Promise<void> {
|
||||||
|
while (true) {
|
||||||
|
if (!this.locked) break;
|
||||||
|
}
|
||||||
|
this.locked = true;
|
||||||
|
|
||||||
|
const file = await fs.readFile(`${this.storagePath}/1.json`, { encoding: 'utf8' });
|
||||||
|
const json: JSONData = JSON.parse(file);
|
||||||
|
json.push({ key, value });
|
||||||
|
await fs.writeFile(`${this.storagePath}/1.json`, JSON.stringify(json), { encoding: 'utf8' });
|
||||||
|
this.locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the data for the specified key.
|
||||||
|
* **Warning:** This function will delete ALL matching entries.
|
||||||
|
* ```ts
|
||||||
|
* await LocalStorage.del('data-key');
|
||||||
|
* ```
|
||||||
|
* @param key The key for the data entry.
|
||||||
|
*/
|
||||||
|
public async del(key: string): Promise<void> {
|
||||||
|
while (true) {
|
||||||
|
if (!this.locked) break;
|
||||||
|
}
|
||||||
|
this.locked = true;
|
||||||
|
|
||||||
|
const file = await fs.readFile(`${this.storagePath}/1.json`, { encoding: 'utf8' });
|
||||||
|
const json: JSONData = JSON.parse(file);
|
||||||
|
const filtered = json.filter((data) => data.key !== key);
|
||||||
|
await fs.writeFile(`${this.storagePath}/1.json`, JSON.stringify(filtered), { encoding: 'utf8' });
|
||||||
|
this.locked = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -111,6 +111,85 @@ export default class Moderation {
|
||||||
return mod.save();
|
return mod.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async mute(user: User, moderator: Member, duration: number, reason?: string): Promise<ModerationInterface> {
|
||||||
|
if (reason && reason.length > 512) throw new Error('Mute reason cannot be longer than 512 characters');
|
||||||
|
const member = await this.client.getRESTGuildMember(this.client.config.guildID, user.id);
|
||||||
|
if (!member) throw new Error('Cannot find member.');
|
||||||
|
await member.addRole('478373942638149643', `Muted by ${moderator.username}#${moderator.discriminator}`);
|
||||||
|
const logID = randomBytes(2).toString('hex');
|
||||||
|
const mod = new ModerationModel({
|
||||||
|
userID: user.id,
|
||||||
|
logID,
|
||||||
|
moderatorID: moderator.id,
|
||||||
|
reason: reason || null,
|
||||||
|
type: 2,
|
||||||
|
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;
|
||||||
|
await this.client.db.local.set(`muted-${member.id}`, true);
|
||||||
|
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle(`Case ${logID} | Mute`);
|
||||||
|
embed.setColor('#ffff00');
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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 unmute(userID: string, moderator: Member, reason?: string): Promise<ModerationInterface> {
|
||||||
|
const member = await this.client.getRESTGuildMember(this.client.config.guildID, userID);
|
||||||
|
if (!member) {
|
||||||
|
await this.client.db.local.del(`muted-${userID}`);
|
||||||
|
throw new Error('Member doesn\'t exist.');
|
||||||
|
}
|
||||||
|
await member.removeRole('478373942638149643');
|
||||||
|
const logID = randomBytes(2).toString('hex');
|
||||||
|
const mod = new ModerationModel({
|
||||||
|
userID,
|
||||||
|
logID,
|
||||||
|
moderatorID: moderator.id,
|
||||||
|
reason: reason || null,
|
||||||
|
type: 1,
|
||||||
|
date: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.client.db.local.del(`muted-${member.id}`);
|
||||||
|
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle(`Case ${logID} | Unmute`);
|
||||||
|
embed.setColor('#1abc9c');
|
||||||
|
embed.setAuthor(member.user.username, member.user.avatarURL);
|
||||||
|
embed.setThumbnail(member.user.avatarURL);
|
||||||
|
embed.addField('User', `<@${member.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();
|
||||||
|
}
|
||||||
|
|
||||||
public async kick(user: Member|User, moderator: Member, reason?: string): Promise<ModerationInterface> {
|
public async kick(user: Member|User, moderator: Member, reason?: string): Promise<ModerationInterface> {
|
||||||
if (reason && reason.length > 512) throw new Error('Kick reason cannot be longer than 512 characters');
|
if (reason && reason.length > 512) throw new Error('Kick reason cannot be longer than 512 characters');
|
||||||
await this.client.guilds.get(this.client.config.guildID).kickMember(user.id, reason);
|
await this.client.guilds.get(this.client.config.guildID).kickMember(user.id, reason);
|
||||||
|
|
|
@ -2,6 +2,7 @@ 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 Event } from './Event';
|
export { default as Event } from './Event';
|
||||||
|
export { default as LocalStorage } from './LocalStorage';
|
||||||
export { default as Moderation } from './Moderation';
|
export { default as Moderation } from './Moderation';
|
||||||
export { default as RichEmbed } from './RichEmbed';
|
export { default as RichEmbed } from './RichEmbed';
|
||||||
export { default as Route } from './Route';
|
export { default as Route } from './Route';
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default class AddRank extends Command {
|
||||||
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
if (!args[1]) return this.error(message.channel, 'Permissions are required.');
|
if (!args[1]) return this.error(message.channel, 'Permissions are required.');
|
||||||
if (!args[2]) return this.error(message.channel, 'A description is required');
|
if (!args[2]) return this.error(message.channel, 'A description is required');
|
||||||
const role = this.client.util.resolveRole(args[0], this.client.guilds.get(this.client.config.guildID));
|
const role = this.client.util.resolveRole(args[0], this.mainGuild);
|
||||||
if (!role) return this.error(message.channel, 'The role you specified doesn\'t appear to exist.');
|
if (!role) return this.error(message.channel, 'The role you specified doesn\'t appear to exist.');
|
||||||
|
|
||||||
const check = await this.client.db.Rank.findOne({ roleID: role.id });
|
const check = await this.client.db.Rank.findOne({ roleID: role.id });
|
||||||
|
|
|
@ -16,7 +16,7 @@ export default class Ban extends Command {
|
||||||
public async run(message: Message, args: string[]) {
|
public async run(message: Message, args: string[]) {
|
||||||
try {
|
try {
|
||||||
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
const member = this.client.util.resolveMember(args[0], message.guild);
|
const member = this.client.util.resolveMember(args[0], this.mainGuild);
|
||||||
let user: User;
|
let user: User;
|
||||||
if (!member) {
|
if (!member) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default class DelRank extends Command {
|
||||||
public async run(message: Message, args: string[]) {
|
public async run(message: Message, args: string[]) {
|
||||||
try {
|
try {
|
||||||
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
const role = this.client.util.resolveRole(args[0], this.client.guilds.get(this.client.config.guildID));
|
const role = this.client.util.resolveRole(args[0], this.mainGuild);
|
||||||
if (!role) return this.error(message.channel, 'The role you specified doesn\'t appear to exist.');
|
if (!role) return this.error(message.channel, 'The role you specified doesn\'t appear to exist.');
|
||||||
|
|
||||||
const check = await this.client.db.Rank.findOne({ roleID: role.id });
|
const check = await this.client.db.Rank.findOne({ roleID: role.id });
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default class Game extends Command {
|
||||||
let member: Member;
|
let member: Member;
|
||||||
if (!args[0]) member = message.member;
|
if (!args[0]) member = message.member;
|
||||||
else {
|
else {
|
||||||
member = this.client.util.resolveMember(args.join(' '), message.guild);
|
member = this.client.util.resolveMember(args.join(' '), this.mainGuild);
|
||||||
if (!member) {
|
if (!member) {
|
||||||
return this.error(message.channel, 'Member not found.');
|
return this.error(message.channel, 'Member not found.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,12 @@ export { default as help } from './help';
|
||||||
export { default as info } from './info';
|
export { default as info } from './info';
|
||||||
export { default as kick } from './kick';
|
export { default as kick } from './kick';
|
||||||
export { default as listredirects } from './listredirects';
|
export { default as listredirects } from './listredirects';
|
||||||
|
export { default as mute } from './mute';
|
||||||
export { default as npm } from './npm';
|
export { default as npm } from './npm';
|
||||||
export { default as page } from './page';
|
export { default as page } from './page';
|
||||||
export { default as ping } from './ping';
|
export { default as ping } from './ping';
|
||||||
export { default as rank } from './rank';
|
export { default as rank } from './rank';
|
||||||
export { default as roleinfo } from './roleinfo';
|
export { default as roleinfo } from './roleinfo';
|
||||||
export { default as unban } from './unban';
|
export { default as unban } from './unban';
|
||||||
|
export { default as unmute } from './unmute';
|
||||||
export { default as whois } from './whois';
|
export { default as whois } from './whois';
|
||||||
|
|
|
@ -18,7 +18,7 @@ export default class Kick extends Command {
|
||||||
let user: Member = this.client.util.resolveMember(args[0], message.guild);
|
let user: Member = this.client.util.resolveMember(args[0], message.guild);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
try {
|
try {
|
||||||
user = await this.client.getRESTGuildMember(this.client.config.guildID, args[0]);
|
user = await this.client.getRESTGuildMember(this.mainGuild.id, args[0]);
|
||||||
} catch {
|
} catch {
|
||||||
return this.error(message.channel, 'Cannot find user.');
|
return this.error(message.channel, 'Cannot find user.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import moment, { unitOfTime } from 'moment';
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import { Client, Command } from '../class';
|
||||||
|
|
||||||
|
export default class Mute extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'mute';
|
||||||
|
this.description = 'Mutes a member.';
|
||||||
|
this.usage = 'mute <member> [time] [reason]';
|
||||||
|
this.permissions = 2;
|
||||||
|
this.guildOnly = true;
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(message: Message, args: string[]) {
|
||||||
|
try {
|
||||||
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
|
const member = this.client.util.resolveMember(args[0], this.mainGuild);
|
||||||
|
if (!member) return this.error(message.channel, 'Cannot find user.');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res1 = await this.client.db.local.get<boolean>(`muted-${member.id}`);
|
||||||
|
if (res1 || this.mainGuild.members.get(member.id).roles.includes('478373942638149643')) return this.error(message.channel, 'This user is already muted.');
|
||||||
|
} catch {} // eslint-disable-line no-empty
|
||||||
|
if (member && !this.client.util.moderation.checkPermissions(member, message.member)) return this.error(message.channel, 'Permission Denied.');
|
||||||
|
message.delete();
|
||||||
|
|
||||||
|
let momentMilliseconds: number;
|
||||||
|
let reason: string;
|
||||||
|
if (args.length > 1) {
|
||||||
|
const lockLength = args[1].match(/[a-z]+|[^a-z]+/gi);
|
||||||
|
const length = Number(lockLength[0]);
|
||||||
|
const unit = lockLength[1] as unitOfTime.Base;
|
||||||
|
momentMilliseconds = moment.duration(length, unit).asMilliseconds();
|
||||||
|
reason = momentMilliseconds ? args.slice(2).join(' ') : args.slice(1).join(' ');
|
||||||
|
if (reason.length > 512) return this.error(message.channel, 'Mute reasons cannot be longer than 512 characters.');
|
||||||
|
}
|
||||||
|
await this.client.util.moderation.mute(member.user, message.member, momentMilliseconds, reason);
|
||||||
|
return this.success(message.channel, `${member.user.username}#${member.user.discriminator} has been muted.`);
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,7 +65,7 @@ export default class Page extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
public logPage(sender: { number: string, user?: string }, recipient: { number: string, user?: string }, type: 'discord' | 'email', code: string): void {
|
public logPage(sender: { number: string, user?: string }, recipient: { number: string, user?: string }, type: 'discord' | 'email', code: string): void {
|
||||||
const chan = <TextableChannel> this.client.guilds.get(this.client.config.guildID).channels.get('722636436716781619');
|
const chan = <TextableChannel> this.mainGuild.channels.get('722636436716781619');
|
||||||
chan.createMessage(`***[${type.toUpperCase()}] \`${sender.number} (${sender.user ? sender.user : ''})\` sent a page to \`${recipient.number} (${recipient.user ? recipient.user : ''})\` with code \`${code}\`.***`);
|
chan.createMessage(`***[${type.toUpperCase()}] \`${sender.number} (${sender.user ? sender.user : ''})\` sent a page to \`${recipient.number} (${recipient.user ? recipient.user : ''})\` with code \`${code}\`.***`);
|
||||||
this.client.util.signale.log(`PAGE (${type.toUpperCase()})| TO: ${recipient.number}, FROM: ${sender.number}, CODE: ${code}`);
|
this.client.util.signale.log(`PAGE (${type.toUpperCase()})| TO: ${recipient.number}, FROM: ${sender.number}, CODE: ${code}`);
|
||||||
}
|
}
|
||||||
|
@ -119,8 +119,8 @@ export default class Page extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id of recipientEntry.discordIDs) {
|
for (const id of recipientEntry.discordIDs) {
|
||||||
const recipient = this.client.guilds.get(this.client.config.guildID).members.get(recipientEntry.individualAssignID);
|
const recipient = this.mainGuild.members.get(recipientEntry.individualAssignID);
|
||||||
const sender = this.client.guilds.get(this.client.config.guildID).members.get(senderEntry.individualAssignID);
|
const sender = this.mainGuild.members.get(senderEntry.individualAssignID);
|
||||||
const chan = await this.client.getDMChannel(id);
|
const chan = await this.client.getDMChannel(id);
|
||||||
if (!chan) continue;
|
if (!chan) continue;
|
||||||
if (!recipient || !sender) {
|
if (!recipient || !sender) {
|
||||||
|
@ -131,8 +131,8 @@ export default class Page extends Command {
|
||||||
chan.createMessage(`${options?.emergencyNumber ? `[SEN#${options.emergencyNumber}] ` : ''}__**Page**__\n**Recipient PN:** ${recipientNumber}\n**Sender PN:** ${senderNumber} (${sender ? `${sender.username}#${sender.discriminator}` : ''})\n**Initial Command:** https://discordapp.com/channels/${message.guild.id}/${message.channel.id}/${message.id} (<#${message.channel.id}>)\n\n**Pager Code:** ${code} (${this.local.codeDict.get(code)})${txt ? `\n**Message:** ${txt}` : ''}`);
|
chan.createMessage(`${options?.emergencyNumber ? `[SEN#${options.emergencyNumber}] ` : ''}__**Page**__\n**Recipient PN:** ${recipientNumber}\n**Sender PN:** ${senderNumber} (${sender ? `${sender.username}#${sender.discriminator}` : ''})\n**Initial Command:** https://discordapp.com/channels/${message.guild.id}/${message.channel.id}/${message.id} (<#${message.channel.id}>)\n\n**Pager Code:** ${code} (${this.local.codeDict.get(code)})${txt ? `\n**Message:** ${txt}` : ''}`);
|
||||||
}
|
}
|
||||||
for (const email of recipientEntry.emailAddresses) {
|
for (const email of recipientEntry.emailAddresses) {
|
||||||
const recipient = this.client.guilds.get(this.client.config.guildID).members.get(recipientEntry.individualAssignID);
|
const recipient = this.mainGuild.members.get(recipientEntry.individualAssignID);
|
||||||
const sender = this.client.guilds.get(this.client.config.guildID).members.get(senderEntry.individualAssignID);
|
const sender = this.mainGuild.members.get(senderEntry.individualAssignID);
|
||||||
if (!recipient || !sender) {
|
if (!recipient || !sender) {
|
||||||
this.logPage({ number: senderNumber, user: 'N/A' }, { number: recipientNumber, user: 'N/A' }, 'email', code);
|
this.logPage({ number: senderNumber, user: 'N/A' }, { number: recipientNumber, user: 'N/A' }, 'email', code);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Message, Role } from 'eris';
|
import { Message, Role } from 'eris';
|
||||||
|
import { createPaginationEmbed } from 'eris-pagination';
|
||||||
import { Client, Command, RichEmbed } from '../class';
|
import { Client, Command, RichEmbed } from '../class';
|
||||||
|
|
||||||
export default class Rank extends Command {
|
export default class Rank extends Command {
|
||||||
|
@ -16,9 +17,7 @@ export default class Rank extends Command {
|
||||||
try {
|
try {
|
||||||
if (!args[0]) {
|
if (!args[0]) {
|
||||||
const roles = await this.client.db.Rank.find();
|
const roles = await this.client.db.Rank.find();
|
||||||
const embed = new RichEmbed();
|
const rankArray: [{ name: string, value: string }?] = [];
|
||||||
embed.setTitle('Ranks');
|
|
||||||
embed.setDescription(`Use \`${this.client.config.prefix}rank <rank name>\` to join/leave the rank.`);
|
|
||||||
for (const rank of roles.sort((a, b) => a.name.localeCompare(b.name))) {
|
for (const rank of roles.sort((a, b) => a.name.localeCompare(b.name))) {
|
||||||
let perms: string;
|
let perms: string;
|
||||||
if (rank.permissions.includes('0')) {
|
if (rank.permissions.includes('0')) {
|
||||||
|
@ -26,17 +25,26 @@ export default class Rank extends Command {
|
||||||
} else {
|
} else {
|
||||||
const rolesArray: Role[] = [];
|
const rolesArray: Role[] = [];
|
||||||
rank.permissions.forEach((r) => {
|
rank.permissions.forEach((r) => {
|
||||||
rolesArray.push(this.client.guilds.get(this.client.config.guildID).roles.get(r));
|
rolesArray.push(this.mainGuild.roles.get(r));
|
||||||
});
|
});
|
||||||
perms = rolesArray.map((r) => message.guild.roles.get(r.id)).sort((a, b) => b.position - a.position).map((r) => `<@&${r.id}>`).join(', ');
|
perms = rolesArray.map((r) => message.guild.roles.get(r.id)).sort((a, b) => b.position - a.position).map((r) => `<@&${r.id}>`).join(', ');
|
||||||
}
|
}
|
||||||
let hasRank = false;
|
let hasRank = false;
|
||||||
if (message.member.roles.includes(rank.roleID)) hasRank = true;
|
if (message.member.roles.includes(rank.roleID)) hasRank = true;
|
||||||
embed.addField(rank.name, `${hasRank ? '*You have this role.*\n' : ''}__Description:__ ${rank.description}\n__Permissions:__ ${perms}`);
|
rankArray.push({ name: rank.name, value: `${hasRank ? '*You have this role.*\n' : ''}__Description:__ ${rank.description}\n__Permissions:__ ${perms}` });
|
||||||
}
|
}
|
||||||
|
const ranksSplit = this.client.util.splitFields(rankArray);
|
||||||
|
const cmdPages: RichEmbed[] = [];
|
||||||
|
ranksSplit.forEach((split) => {
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle('Ranks');
|
||||||
|
embed.setDescription(`Use \`${this.client.config.prefix}rank <rank name>\` to join/leave the rank.`);
|
||||||
embed.setFooter(`Requested by: ${message.author.username}#${message.author.discriminator} | ${this.client.user.username}`, message.author.avatarURL);
|
embed.setFooter(`Requested by: ${message.author.username}#${message.author.discriminator} | ${this.client.user.username}`, message.author.avatarURL);
|
||||||
embed.setTimestamp();
|
embed.setTimestamp();
|
||||||
return message.channel.createMessage({ embed });
|
split.forEach((c) => embed.addField(c.name, c.value));
|
||||||
|
});
|
||||||
|
if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });
|
||||||
|
return createPaginationEmbed(message, cmdPages);
|
||||||
}
|
}
|
||||||
const role = this.client.util.resolveRole(args.join(' '), this.client.guilds.get(this.client.config.guildID));
|
const role = this.client.util.resolveRole(args.join(' '), this.client.guilds.get(this.client.config.guildID));
|
||||||
if (!role) return this.error(message.channel, 'The role you specified doesn\'t exist.');
|
if (!role) return this.error(message.channel, 'The role you specified doesn\'t exist.');
|
||||||
|
|
|
@ -17,10 +17,7 @@ export default class Roleinfo extends Command {
|
||||||
try {
|
try {
|
||||||
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
|
|
||||||
let role: Role = message.guild.roles.find((r: Role) => r.id === args[0]);
|
const role = this.client.util.resolveRole(args[0], this.mainGuild);
|
||||||
if (!role) { // if it's a role name
|
|
||||||
role = message.guild.roles.find((r: Role) => r.name.toLowerCase().includes(args.join(' ').toLowerCase()));
|
|
||||||
}
|
|
||||||
if (!role) return this.error(message.channel, 'Could not find role.');
|
if (!role) return this.error(message.channel, 'Could not find role.');
|
||||||
|
|
||||||
const perms = role.permissions;
|
const perms = role.permissions;
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import { Client, Command } from '../class';
|
||||||
|
|
||||||
|
export default class Unmute extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'unmute';
|
||||||
|
this.description = 'Unmutes a member.';
|
||||||
|
this.usage = 'unmute <member> [reason]';
|
||||||
|
this.permissions = 2;
|
||||||
|
this.guildOnly = true;
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(message: Message, args: string[]) {
|
||||||
|
try {
|
||||||
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
|
const member = this.client.util.resolveMember(args[0], this.mainGuild);
|
||||||
|
if (!member) return this.error(message.channel, 'Cannot find user.');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res1 = await this.client.db.local.get<boolean>(`muted-${member.id}`);
|
||||||
|
if (!res1 || !this.mainGuild.members.get(member.id).roles.includes('478373942638149643')) return this.error(message.channel, 'This user is already unmuted.');
|
||||||
|
} catch {} // eslint-disable-line no-empty
|
||||||
|
if (member && !this.client.util.moderation.checkPermissions(member, message.member)) return this.error(message.channel, 'Permission Denied.');
|
||||||
|
message.delete();
|
||||||
|
|
||||||
|
await this.client.util.moderation.unmute(member.user.id, message.member, args.slice(1).join(' '));
|
||||||
|
return this.success(message.channel, `${member.user.username}#${member.user.discriminator} has been unmuted.`);
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,7 +64,7 @@ export default class Whois extends Command {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
embed.addField('Status', member.status === 'dnd' ? 'Do Not Disturb' : this.capsFirstLetter(member.status) || 'Unknown', true);
|
embed.addField('Status', member.status === 'dnd' ? 'Do Not Disturb' : this.capsFirstLetter(member.status) || 'Offline', true);
|
||||||
// const platform = member.bot && member.status !== 'offline' ? 'API/WebSocket' : Object.entries(message.member.clientStatus).filter((a) => a[1] !== 'offline').map((a) => this.capsFirstLetter(a[0])).join(', ');
|
// const platform = member.bot && member.status !== 'offline' ? 'API/WebSocket' : Object.entries(message.member.clientStatus).filter((a) => a[1] !== 'offline').map((a) => this.capsFirstLetter(a[0])).join(', ');
|
||||||
// if (platform) embed.addField('Platform', platform, true);
|
// if (platform) embed.addField('Platform', platform, true);
|
||||||
embed.addField('Joined At', `${moment(new Date(member.joinedAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true);
|
embed.addField('Joined At', `${moment(new Date(member.joinedAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true);
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Member } from 'eris';
|
||||||
|
import { Client, Event } from '../class';
|
||||||
|
|
||||||
|
export default class GuildMemberAdd extends Event {
|
||||||
|
public client: Client;
|
||||||
|
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.event = 'guildMemberAdd';
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(member: Member) {
|
||||||
|
try {
|
||||||
|
const search = await this.client.db.local.get<boolean>(`muted-${member.user.id}`);
|
||||||
|
if (search === true) {
|
||||||
|
member.addRole('478373942638149643');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.client.util.handleError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,8 +11,21 @@ export default function checkLock(client: Client): NodeJS.Timeout {
|
||||||
if (moderation.expiration.processed) return;
|
if (moderation.expiration.processed) return;
|
||||||
if (new Date() > moderation.expiration.date) {
|
if (new Date() > moderation.expiration.date) {
|
||||||
await moderation.updateOne({ 'expiration.processed': true });
|
await moderation.updateOne({ 'expiration.processed': true });
|
||||||
const moderator = client.guilds.get(client.config.guildID).members.get(moderation.moderatorID);
|
// const moderator = client.guilds.get(client.config.guildID).members.get(moderation.moderatorID);
|
||||||
await client.util.moderation.unban(moderation.userID, moderator);
|
const system = client.guilds.get(client.config.guildID).members.get(client.user.id);
|
||||||
|
switch (moderation.type) {
|
||||||
|
case 5:
|
||||||
|
await client.util.moderation.unban(moderation.userID, system);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
console.log(await client.db.local.get<boolean>(`muted-${moderation.userID}`));
|
||||||
|
if (await client.db.local.get<boolean>(`muted-${moderation.userID}`) === true) {
|
||||||
|
await client.util.moderation.unmute(moderation.userID, system);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
client.util.signale.complete(`Released member ${moderation.userID} | Queue date at ${moderation.expiration.date.toLocaleString('en-us')}`);
|
client.util.signale.complete(`Released member ${moderation.userID} | Queue date at ${moderation.expiration.date.toLocaleString('en-us')}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,7 +15,7 @@ export interface ModerationInterface extends Document {
|
||||||
*/
|
*/
|
||||||
type: 0 | 1 | 2 | 3 | 4 | 5
|
type: 0 | 1 | 2 | 3 | 4 | 5
|
||||||
date: Date,
|
date: Date,
|
||||||
expiration: {
|
expiration?: {
|
||||||
date: Date,
|
date: Date,
|
||||||
processed: boolean
|
processed: boolean
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue