fix merge conflict
commit
eb5159806d
|
@ -1,5 +1,5 @@
|
|||
import locsh from './loc.sh/main';
|
||||
|
||||
export default {
|
||||
'loc.sh': locsh,
|
||||
};
|
||||
import locsh from './loc.sh/main';
|
||||
|
||||
export default {
|
||||
'loc.sh': locsh,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Server, ServerManagement } from '../../class';
|
||||
|
||||
export default (management: ServerManagement) => {
|
||||
const server = new Server(management, 3890, `${__dirname}/routes`);
|
||||
return server;
|
||||
};
|
||||
import { Server, ServerManagement } from '../../class';
|
||||
|
||||
export default (management: ServerManagement) => {
|
||||
const server = new Server(management, 3890, `${__dirname}/routes`);
|
||||
return server;
|
||||
};
|
||||
|
|
|
@ -1 +1 @@
|
|||
export { default as root } from './root';
|
||||
export { default as root } from './root';
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
import { Route, Server } from '../../../class';
|
||||
import { RedirectRaw } from '../../../models';
|
||||
|
||||
export default class Root extends Route {
|
||||
constructor(server: Server) {
|
||||
super(server);
|
||||
this.conf = {
|
||||
path: '/',
|
||||
};
|
||||
}
|
||||
|
||||
public bind() {
|
||||
this.router.get('/', (_req, res) => res.redirect('https://www.libraryofcode.org/'));
|
||||
|
||||
this.router.get('/:key', async (req, res) => {
|
||||
try {
|
||||
const link: RedirectRaw = await this.server.client.db.Redirect.findOne({ key: req.params.key }).lean().exec();
|
||||
if (!link) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.messages.NOT_FOUND });
|
||||
res.redirect(link.to);
|
||||
return await this.server.client.db.Redirect.updateOne({ key: req.params.key }, { $inc: { visitedCount: 1 } });
|
||||
} catch (err) {
|
||||
this.server.client.util.handleError(err);
|
||||
return res.status(500).json({ code: this.constants.codes.SERVER_ERROR, message: this.constants.messages.SERVER_ERROR });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
import { Route, Server } from '../../../class';
|
||||
import { RedirectRaw } from '../../../models';
|
||||
|
||||
export default class Root extends Route {
|
||||
constructor(server: Server) {
|
||||
super(server);
|
||||
this.conf = {
|
||||
path: '/',
|
||||
};
|
||||
}
|
||||
|
||||
public bind() {
|
||||
this.router.get('/', (_req, res) => res.redirect('https://www.libraryofcode.org/'));
|
||||
|
||||
this.router.get('/:key', async (req, res) => {
|
||||
try {
|
||||
const link: RedirectRaw = await this.server.client.db.Redirect.findOne({ key: req.params.key }).lean().exec();
|
||||
if (!link) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.messages.NOT_FOUND });
|
||||
res.redirect(link.to);
|
||||
return await this.server.client.db.Redirect.updateOne({ key: req.params.key }, { $inc: { visitedCount: 1 } });
|
||||
} catch (err) {
|
||||
this.server.client.util.handleError(err);
|
||||
return res.status(500).json({ code: this.constants.codes.SERVER_ERROR, message: this.constants.messages.SERVER_ERROR });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,69 +1,69 @@
|
|||
import eris from 'eris';
|
||||
import mongoose from 'mongoose';
|
||||
import { promises as fs } from 'fs';
|
||||
import { Collection, Command, Util, ServerManagement, Event } from '.';
|
||||
import { Member, MemberInterface, Moderation, ModerationInterface, PagerNumber, PagerNumberInterface, Redirect, RedirectInterface } from '../models';
|
||||
|
||||
export default class Client extends eris.Client {
|
||||
public config: { token: string, prefix: string, guildID: string, mongoDB: string, emailPass: string, };
|
||||
|
||||
public commands: Collection<Command>;
|
||||
|
||||
public events: Collection<Event>;
|
||||
|
||||
public intervals: Collection<NodeJS.Timeout>;
|
||||
|
||||
public util: Util;
|
||||
|
||||
public serverManagement: ServerManagement;
|
||||
|
||||
public db: { Member: mongoose.Model<MemberInterface>, Moderation: mongoose.Model<ModerationInterface>, PagerNumber: mongoose.Model<PagerNumberInterface>, Redirect: mongoose.Model<RedirectInterface> };
|
||||
|
||||
constructor(token: string, options?: eris.ClientOptions) {
|
||||
super(token, options);
|
||||
this.commands = new Collection<Command>();
|
||||
this.events = new Collection<Event>();
|
||||
this.intervals = new Collection<NodeJS.Timeout>();
|
||||
this.db = { Member, Moderation, PagerNumber, Redirect };
|
||||
}
|
||||
|
||||
public async loadDatabase() {
|
||||
await mongoose.connect(this.config.mongoDB, { useNewUrlParser: true, useUnifiedTopology: true, poolSize: 50 });
|
||||
}
|
||||
|
||||
public loadPlugins() {
|
||||
this.util = new Util(this);
|
||||
this.serverManagement = new ServerManagement(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(eventFiles: { [s: string]: typeof Event; } | ArrayLike<typeof Event>) {
|
||||
const evtFiles = Object.entries<typeof Event>(eventFiles);
|
||||
for (const [name, Ev] of evtFiles) {
|
||||
const event = new Ev(this);
|
||||
this.events.add(event.event, event);
|
||||
this.on(event.event, event.run);
|
||||
this.util.signale.success(`Successfully loaded event: ${name}`);
|
||||
delete require.cache[require.resolve(`${__dirname}/../events/${name}`)];
|
||||
}
|
||||
}
|
||||
|
||||
public async loadCommands(commandFiles: { [s: string]: typeof Command; } | ArrayLike<typeof Command>) {
|
||||
const cmdFiles = Object.values<typeof Command>(commandFiles);
|
||||
for (const Cmd of cmdFiles) {
|
||||
const command = new Cmd(this);
|
||||
this.commands.add(command.name, command);
|
||||
this.util.signale.success(`Successfully loaded command: ${command.name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
import eris from 'eris';
|
||||
import mongoose from 'mongoose';
|
||||
import { promises as fs } from 'fs';
|
||||
import { Collection, Command, Util, ServerManagement, Event } from '.';
|
||||
import { Member, MemberInterface, Moderation, ModerationInterface, PagerNumber, PagerNumberInterface, Rank, RankInterface, Redirect, RedirectInterface } from '../models';
|
||||
|
||||
export default class Client extends eris.Client {
|
||||
public config: { token: string, prefix: string, guildID: string, mongoDB: string, emailPass: string, };
|
||||
|
||||
public commands: Collection<Command>;
|
||||
|
||||
public events: Collection<Event>;
|
||||
|
||||
public intervals: Collection<NodeJS.Timeout>;
|
||||
|
||||
public util: Util;
|
||||
|
||||
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> };
|
||||
|
||||
constructor(token: string, options?: eris.ClientOptions) {
|
||||
super(token, options);
|
||||
this.commands = new Collection<Command>();
|
||||
this.events = new Collection<Event>();
|
||||
this.intervals = new Collection<NodeJS.Timeout>();
|
||||
this.db = { Member, Moderation, PagerNumber, Rank, Redirect };
|
||||
}
|
||||
|
||||
public async loadDatabase() {
|
||||
await mongoose.connect(this.config.mongoDB, { useNewUrlParser: true, useUnifiedTopology: true, poolSize: 50 });
|
||||
}
|
||||
|
||||
public loadPlugins() {
|
||||
this.util = new Util(this);
|
||||
this.serverManagement = new ServerManagement(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(eventFiles: { [s: string]: typeof Event; } | ArrayLike<typeof Event>) {
|
||||
const evtFiles = Object.entries<typeof Event>(eventFiles);
|
||||
for (const [name, Ev] of evtFiles) {
|
||||
const event = new Ev(this);
|
||||
this.events.add(event.event, event);
|
||||
this.on(event.event, event.run);
|
||||
this.util.signale.success(`Successfully loaded event: ${name}`);
|
||||
delete require.cache[require.resolve(`${__dirname}/../events/${name}`)];
|
||||
}
|
||||
}
|
||||
|
||||
public async loadCommands(commandFiles: { [s: string]: typeof Command; } | ArrayLike<typeof Command>) {
|
||||
const cmdFiles = Object.values<typeof Command>(commandFiles);
|
||||
for (const Cmd of cmdFiles) {
|
||||
const command = new Cmd(this);
|
||||
this.commands.add(command.name, command);
|
||||
this.util.signale.success(`Successfully loaded command: ${command.name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,153 +1,153 @@
|
|||
/**
|
||||
* Hold a bunch of something
|
||||
*/
|
||||
export default class Collection<V> extends Map<string, V> {
|
||||
baseObject: new (...args: any[]) => V;
|
||||
|
||||
/**
|
||||
* Creates an instance of Collection
|
||||
*/
|
||||
constructor(iterable: Iterable<[string, V]>|object = null) {
|
||||
if (iterable && iterable instanceof Array) {
|
||||
super(iterable);
|
||||
} else if (iterable && iterable instanceof Object) {
|
||||
super(Object.entries(iterable));
|
||||
} else {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map to array
|
||||
* ```js
|
||||
* [value, value, value]
|
||||
* ```
|
||||
*/
|
||||
toArray(): V[] {
|
||||
return [...this.values()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Map to object
|
||||
* ```js
|
||||
* { key: value, key: value, key: value }
|
||||
* ```
|
||||
*/
|
||||
toObject(): { [key: string]: V } {
|
||||
const obj: { [key: string]: V } = {};
|
||||
for (const [key, value] of this.entries()) {
|
||||
obj[key] = value;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an object
|
||||
*
|
||||
* If baseObject, add only if instance of baseObject
|
||||
*
|
||||
* If no baseObject, add
|
||||
* @param key The key of the object
|
||||
* @param value The object data
|
||||
* @param replace Whether to replace an existing object with the same key
|
||||
* @return The existing or newly created object
|
||||
*/
|
||||
add(key: string, value: V, replace: boolean = false): V {
|
||||
if (this.has(key) && !replace) {
|
||||
return this.get(key);
|
||||
}
|
||||
if (this.baseObject && !(value instanceof this.baseObject)) return null;
|
||||
|
||||
this.set(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first object to make the function evaluate true
|
||||
* @param func A function that takes an object and returns something
|
||||
* @return The first matching object, or `null` if no match
|
||||
*/
|
||||
find(func: Function): V {
|
||||
for (const item of this.values()) {
|
||||
if (func(item)) return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array with the results of applying the given function to each element
|
||||
* @param callbackfn A function that takes an object and returns something
|
||||
*/
|
||||
map<U>(callbackfn: (value?: V, index?: number, array?: V[]) => U): U[] {
|
||||
const arr = [];
|
||||
for (const item of this.values()) {
|
||||
arr.push(callbackfn(item));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the objects that make the function evaluate true
|
||||
* @param func A function that takes an object and returns true if it matches
|
||||
*/
|
||||
filter(func: (value: V) => boolean): V[] {
|
||||
const arr = [];
|
||||
for (const item of this.values()) {
|
||||
if (func(item)) {
|
||||
arr.push(item);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if at least one element passes the test implemented by the provided function. Returns true if yes, or false if not.
|
||||
* @param func A function that takes an object and returns true if it matches
|
||||
*/
|
||||
some(func: (value: V) => boolean) {
|
||||
for (const item of this.values()) {
|
||||
if (func(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an object
|
||||
* @param key The key of the object
|
||||
* @param value The updated object data
|
||||
*/
|
||||
update(key: string, value: V) {
|
||||
return this.add(key, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an object
|
||||
* @param key The key of the object
|
||||
* @returns The removed object, or `null` if nothing was removed
|
||||
*/
|
||||
remove(key: string): V {
|
||||
const item = this.get(key);
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
this.delete(key);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random object from the Collection
|
||||
* @returns The random object or `null` if empty
|
||||
*/
|
||||
random(): V {
|
||||
if (!this.size) {
|
||||
return null;
|
||||
}
|
||||
return Array.from(this.values())[Math.floor(Math.random() * this.size)];
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `[Collection<${this.baseObject.name}>]`;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Hold a bunch of something
|
||||
*/
|
||||
export default class Collection<V> extends Map<string, V> {
|
||||
baseObject: new (...args: any[]) => V;
|
||||
|
||||
/**
|
||||
* Creates an instance of Collection
|
||||
*/
|
||||
constructor(iterable: Iterable<[string, V]>|object = null) {
|
||||
if (iterable && iterable instanceof Array) {
|
||||
super(iterable);
|
||||
} else if (iterable && iterable instanceof Object) {
|
||||
super(Object.entries(iterable));
|
||||
} else {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map to array
|
||||
* ```js
|
||||
* [value, value, value]
|
||||
* ```
|
||||
*/
|
||||
toArray(): V[] {
|
||||
return [...this.values()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Map to object
|
||||
* ```js
|
||||
* { key: value, key: value, key: value }
|
||||
* ```
|
||||
*/
|
||||
toObject(): { [key: string]: V } {
|
||||
const obj: { [key: string]: V } = {};
|
||||
for (const [key, value] of this.entries()) {
|
||||
obj[key] = value;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an object
|
||||
*
|
||||
* If baseObject, add only if instance of baseObject
|
||||
*
|
||||
* If no baseObject, add
|
||||
* @param key The key of the object
|
||||
* @param value The object data
|
||||
* @param replace Whether to replace an existing object with the same key
|
||||
* @return The existing or newly created object
|
||||
*/
|
||||
add(key: string, value: V, replace: boolean = false): V {
|
||||
if (this.has(key) && !replace) {
|
||||
return this.get(key);
|
||||
}
|
||||
if (this.baseObject && !(value instanceof this.baseObject)) return null;
|
||||
|
||||
this.set(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first object to make the function evaluate true
|
||||
* @param func A function that takes an object and returns something
|
||||
* @return The first matching object, or `null` if no match
|
||||
*/
|
||||
find(func: Function): V {
|
||||
for (const item of this.values()) {
|
||||
if (func(item)) return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array with the results of applying the given function to each element
|
||||
* @param callbackfn A function that takes an object and returns something
|
||||
*/
|
||||
map<U>(callbackfn: (value?: V, index?: number, array?: V[]) => U): U[] {
|
||||
const arr = [];
|
||||
for (const item of this.values()) {
|
||||
arr.push(callbackfn(item));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the objects that make the function evaluate true
|
||||
* @param func A function that takes an object and returns true if it matches
|
||||
*/
|
||||
filter(func: (value: V) => boolean): V[] {
|
||||
const arr = [];
|
||||
for (const item of this.values()) {
|
||||
if (func(item)) {
|
||||
arr.push(item);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if at least one element passes the test implemented by the provided function. Returns true if yes, or false if not.
|
||||
* @param func A function that takes an object and returns true if it matches
|
||||
*/
|
||||
some(func: (value: V) => boolean) {
|
||||
for (const item of this.values()) {
|
||||
if (func(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an object
|
||||
* @param key The key of the object
|
||||
* @param value The updated object data
|
||||
*/
|
||||
update(key: string, value: V) {
|
||||
return this.add(key, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an object
|
||||
* @param key The key of the object
|
||||
* @returns The removed object, or `null` if nothing was removed
|
||||
*/
|
||||
remove(key: string): V {
|
||||
const item = this.get(key);
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
this.delete(key);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random object from the Collection
|
||||
* @returns The random object or `null` if empty
|
||||
*/
|
||||
random(): V {
|
||||
if (!this.size) {
|
||||
return null;
|
||||
}
|
||||
return Array.from(this.values())[Math.floor(Math.random() * this.size)];
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `[Collection<${this.baseObject.name}>]`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,92 +1,92 @@
|
|||
import { Member, Message, TextableChannel } from 'eris';
|
||||
import { Client } from '.';
|
||||
|
||||
export default class Command {
|
||||
public client: Client;
|
||||
|
||||
/**
|
||||
* The name of the command
|
||||
*/
|
||||
public name: string;
|
||||
/**
|
||||
* The description for the command.
|
||||
*/
|
||||
|
||||
public description: string;
|
||||
|
||||
/**
|
||||
* Usage for the command.
|
||||
*/
|
||||
public usage: string;
|
||||
/**
|
||||
* The aliases for the command.
|
||||
*/
|
||||
|
||||
public aliases: string[];
|
||||
|
||||
/**
|
||||
* - **0:** Everyone
|
||||
* - **1:** Associates+
|
||||
* - **2:** Core Team+
|
||||
* - **3:** Moderators, Supervisor, & Board of Directors
|
||||
* - **4:** Technicians, Supervisor, & Board of Directors
|
||||
* - **5:** Moderators, Technicians, Supervisor, & Board of Directors
|
||||
* - **6:** Supervisor+
|
||||
* - **7:** Board of Directors
|
||||
*/
|
||||
public permissions: number;
|
||||
|
||||
/**
|
||||
* Determines if the command is only available in server.
|
||||
*/
|
||||
public guildOnly: boolean;
|
||||
|
||||
/**
|
||||
* Determines if the command is enabled or not.
|
||||
*/
|
||||
public enabled: boolean;
|
||||
|
||||
public run(message: Message, args: string[]): Promise<any> { return Promise.resolve(); }
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
|
||||
this.aliases = [];
|
||||
}
|
||||
|
||||
public checkPermissions(member: Member): boolean {
|
||||
if (member.id === '278620217221971968' || member.id === '253600545972027394') return true;
|
||||
switch (this.permissions) {
|
||||
case 0:
|
||||
return true;
|
||||
case 1:
|
||||
return member.roles.some((r) => ['701481967149121627', '453689940140883988', '455972169449734144', '701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 2:
|
||||
return member.roles.some((r) => ['453689940140883988', '455972169449734144', '701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 3:
|
||||
return member.roles.some((r) => ['455972169449734144', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 4:
|
||||
return member.roles.some((r) => ['701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 5:
|
||||
return member.roles.some((r) => ['455972169449734144', '701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 6:
|
||||
return member.roles.some((r) => ['701454855952138300', '662163685439045632'].includes(r));
|
||||
case 7:
|
||||
return member.roles.includes('662163685439045632');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public error(channel: TextableChannel, text: string): Promise<Message> {
|
||||
return channel.createMessage(`***${this.client.util.emojis.ERROR} ${text}***`);
|
||||
}
|
||||
|
||||
public success(channel: TextableChannel, text: string): Promise<Message> {
|
||||
return channel.createMessage(`***${this.client.util.emojis.SUCCESS} ${text}***`);
|
||||
}
|
||||
|
||||
public loading(channel: TextableChannel, text: string): Promise<Message> {
|
||||
return channel.createMessage(`***${this.client.util.emojis.LOADING} ${text}***`);
|
||||
}
|
||||
}
|
||||
import { Member, Message, TextableChannel } from 'eris';
|
||||
import { Client } from '.';
|
||||
|
||||
export default class Command {
|
||||
public client: Client;
|
||||
|
||||
/**
|
||||
* The name of the command
|
||||
*/
|
||||
public name: string;
|
||||
/**
|
||||
* The description for the command.
|
||||
*/
|
||||
|
||||
public description: string;
|
||||
|
||||
/**
|
||||
* Usage for the command.
|
||||
*/
|
||||
public usage: string;
|
||||
/**
|
||||
* The aliases for the command.
|
||||
*/
|
||||
|
||||
public aliases: string[];
|
||||
|
||||
/**
|
||||
* - **0:** Everyone
|
||||
* - **1:** Associates+
|
||||
* - **2:** Core Team+
|
||||
* - **3:** Moderators, Supervisor, & Board of Directors
|
||||
* - **4:** Technicians, Supervisor, & Board of Directors
|
||||
* - **5:** Moderators, Technicians, Supervisor, & Board of Directors
|
||||
* - **6:** Supervisor+
|
||||
* - **7:** Board of Directors
|
||||
*/
|
||||
public permissions: number;
|
||||
|
||||
/**
|
||||
* Determines if the command is only available in server.
|
||||
*/
|
||||
public guildOnly: boolean;
|
||||
|
||||
/**
|
||||
* Determines if the command is enabled or not.
|
||||
*/
|
||||
public enabled: boolean;
|
||||
|
||||
public run(message: Message, args: string[]): Promise<any> { return Promise.resolve(); }
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
|
||||
this.aliases = [];
|
||||
}
|
||||
|
||||
public checkPermissions(member: Member): boolean {
|
||||
if (member.id === '278620217221971968' || member.id === '253600545972027394') return true;
|
||||
switch (this.permissions) {
|
||||
case 0:
|
||||
return true;
|
||||
case 1:
|
||||
return member.roles.some((r) => ['701481967149121627', '453689940140883988', '455972169449734144', '701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 2:
|
||||
return member.roles.some((r) => ['453689940140883988', '455972169449734144', '701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 3:
|
||||
return member.roles.some((r) => ['455972169449734144', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 4:
|
||||
return member.roles.some((r) => ['701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 5:
|
||||
return member.roles.some((r) => ['455972169449734144', '701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||
case 6:
|
||||
return member.roles.some((r) => ['701454855952138300', '662163685439045632'].includes(r));
|
||||
case 7:
|
||||
return member.roles.includes('662163685439045632');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public error(channel: TextableChannel, text: string): Promise<Message> {
|
||||
return channel.createMessage(`***${this.client.util.emojis.ERROR} ${text}***`);
|
||||
}
|
||||
|
||||
public success(channel: TextableChannel, text: string): Promise<Message> {
|
||||
return channel.createMessage(`***${this.client.util.emojis.SUCCESS} ${text}***`);
|
||||
}
|
||||
|
||||
public loading(channel: TextableChannel, text: string): Promise<Message> {
|
||||
return channel.createMessage(`***${this.client.util.emojis.LOADING} ${text}***`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import { Client } from '.';
|
||||
|
||||
export default class Event {
|
||||
public client: Client
|
||||
|
||||
public event: string;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
this.event = '';
|
||||
this.run = this.run.bind(this);
|
||||
}
|
||||
|
||||
public async run(...args: any[]): Promise<void> { return Promise.resolve(); }
|
||||
}
|
||||
import { Client } from '.';
|
||||
|
||||
export default class Event {
|
||||
public client: Client
|
||||
|
||||
public event: string;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
this.event = '';
|
||||
this.run = this.run.bind(this);
|
||||
}
|
||||
|
||||
public async run(...args: any[]): Promise<void> { return Promise.resolve(); }
|
||||
}
|
||||
|
|
|
@ -1,142 +1,142 @@
|
|||
/* eslint-disable no-bitwise */
|
||||
import { Member, User } from 'eris';
|
||||
import { randomBytes } from 'crypto';
|
||||
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(user: User, moderator: Member, duration: number, reason?: string): Promise<ModerationInterface> {
|
||||
if (reason && reason.length > 512) throw new Error('Ban reason cannot be longer than 512 characters');
|
||||
await this.client.guilds.get(this.client.config.guildID).banMember(user.id, 7, reason);
|
||||
const logID = randomBytes(2).toString('hex');
|
||||
const mod = new ModerationModel({
|
||||
userID: user.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.setColor('#e74c3c');
|
||||
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 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 = randomBytes(2).toString('hex');
|
||||
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.setColor('#1abc9c');
|
||||
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();
|
||||
}
|
||||
|
||||
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');
|
||||
await this.client.guilds.get(this.client.config.guildID).kickMember(user.id, reason);
|
||||
const logID = randomBytes(2).toString('hex');
|
||||
const mod = new ModerationModel({
|
||||
userID: user.id,
|
||||
logID,
|
||||
moderatorID: moderator.id,
|
||||
reason: reason || null,
|
||||
type: 5,
|
||||
date: new Date(),
|
||||
});
|
||||
|
||||
const embed = new RichEmbed();
|
||||
embed.setTitle(`Case ${logID} | Kick`);
|
||||
embed.setColor('#e74c3c');
|
||||
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();
|
||||
}
|
||||
}
|
||||
/* eslint-disable no-bitwise */
|
||||
import { Member, User } from 'eris';
|
||||
import { randomBytes } from 'crypto';
|
||||
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(user: User, moderator: Member, duration: number, reason?: string): Promise<ModerationInterface> {
|
||||
if (reason && reason.length > 512) throw new Error('Ban reason cannot be longer than 512 characters');
|
||||
await this.client.guilds.get(this.client.config.guildID).banMember(user.id, 7, reason);
|
||||
const logID = randomBytes(2).toString('hex');
|
||||
const mod = new ModerationModel({
|
||||
userID: user.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.setColor('#e74c3c');
|
||||
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 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 = randomBytes(2).toString('hex');
|
||||
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.setColor('#1abc9c');
|
||||
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();
|
||||
}
|
||||
|
||||
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');
|
||||
await this.client.guilds.get(this.client.config.guildID).kickMember(user.id, reason);
|
||||
const logID = randomBytes(2).toString('hex');
|
||||
const mod = new ModerationModel({
|
||||
userID: user.id,
|
||||
logID,
|
||||
moderatorID: moderator.id,
|
||||
reason: reason || null,
|
||||
type: 5,
|
||||
date: new Date(),
|
||||
});
|
||||
|
||||
const embed = new RichEmbed();
|
||||
embed.setTitle(`Case ${logID} | Kick`);
|
||||
embed.setColor('#e74c3c');
|
||||
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,164 +1,164 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
|
||||
import { EmbedOptions } from 'eris';
|
||||
|
||||
export default class RichEmbed implements EmbedOptions {
|
||||
title?: string
|
||||
|
||||
type?: string
|
||||
|
||||
description?: string
|
||||
|
||||
url?: string
|
||||
|
||||
timestamp?: string | Date
|
||||
|
||||
color?: number
|
||||
|
||||
footer?: { text: string, icon_url?: string, proxy_icon_url?: string}
|
||||
|
||||
image?: { url?: string, proxy_url?: string, height?: number, width?: number }
|
||||
|
||||
thumbnail?: { url?: string, proxy_url?: string, height?: number, width?: number }
|
||||
|
||||
video?: { url: string, height?: number, width?: number }
|
||||
|
||||
provider?: { name: string, url?: string}
|
||||
|
||||
author?: { name: string, url?: string, proxy_icon_url?: string, icon_url?: string}
|
||||
|
||||
fields?: {name: string, value: string, inline?: boolean}[]
|
||||
|
||||
constructor(data: EmbedOptions = {}) {
|
||||
this.title = data.title;
|
||||
this.description = data.description;
|
||||
this.url = data.url;
|
||||
this.color = data.color;
|
||||
this.author = data.author;
|
||||
this.timestamp = data.timestamp;
|
||||
this.fields = data.fields || [];
|
||||
this.thumbnail = data.thumbnail;
|
||||
this.image = data.image;
|
||||
this.footer = data.footer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title of this embed.
|
||||
*/
|
||||
setTitle(title: string) {
|
||||
if (typeof title !== 'string') throw new TypeError('RichEmbed titles must be a string.');
|
||||
if (title.length > 256) throw new RangeError('RichEmbed titles may not exceed 256 characters.');
|
||||
this.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description of this embed.
|
||||
*/
|
||||
setDescription(description: string) {
|
||||
if (typeof description !== 'string') throw new TypeError('RichEmbed descriptions must be a string.');
|
||||
if (description.length > 2048) throw new RangeError('RichEmbed descriptions may not exceed 2048 characters.');
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URL of this embed.
|
||||
*/
|
||||
setURL(url: string) {
|
||||
if (typeof url !== 'string') throw new TypeError('RichEmbed URLs must be a string.');
|
||||
if (!url.startsWith('http://') && !url.startsWith('https://')) url = `https://${url}`;
|
||||
this.url = encodeURI(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of this embed.
|
||||
*/
|
||||
setColor(color: string | number) {
|
||||
if (typeof color === 'string' || typeof color === 'number') {
|
||||
if (typeof color === 'string') {
|
||||
const regex = /[^a-f0-9]/gi;
|
||||
color = color.replace(/#/g, '');
|
||||
if (regex.test(color)) throw new RangeError('Hexadecimal colours must not contain characters other than 0-9 and a-f.');
|
||||
color = parseInt(color, 16);
|
||||
} else if (color < 0 || color > 16777215) throw new RangeError('Base 10 colours must not be less than 0 or greater than 16777215.');
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
throw new TypeError('RichEmbed colours must be hexadecimal as string or number.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the author of this embed.
|
||||
*/
|
||||
setAuthor(name: string, icon_url?: string, url?: string) {
|
||||
if (typeof name !== 'string') throw new TypeError('RichEmbed Author names must be a string.');
|
||||
if (url && typeof url !== 'string') throw new TypeError('RichEmbed Author URLs must be a string.');
|
||||
if (icon_url && typeof icon_url !== 'string') throw new TypeError('RichEmbed Author icons must be a string.');
|
||||
this.author = { name, icon_url, url };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timestamp of this embed.
|
||||
*/
|
||||
setTimestamp(timestamp = new Date()) {
|
||||
if (Number.isNaN(timestamp.getTime())) throw new TypeError('Expecting ISO8601 (Date constructor)');
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a field to the embed (max 25).
|
||||
*/
|
||||
addField(name: string, value: string, inline = false) {
|
||||
if (typeof name !== 'string') throw new TypeError('RichEmbed Field names must be a string.');
|
||||
if (typeof value !== 'string') throw new TypeError('RichEmbed Field values must be a string.');
|
||||
if (typeof inline !== 'boolean') throw new TypeError('RichEmbed Field inlines must be a boolean.');
|
||||
if (this.fields.length >= 25) throw new RangeError('RichEmbeds may not exceed 25 fields.');
|
||||
if (name.length > 256) throw new RangeError('RichEmbed field names may not exceed 256 characters.');
|
||||
if (!/\S/.test(name)) throw new RangeError('RichEmbed field names may not be empty.');
|
||||
if (value.length > 1024) throw new RangeError('RichEmbed field values may not exceed 1024 characters.');
|
||||
if (!/\S/.test(value)) throw new RangeError('RichEmbed field values may not be empty.');
|
||||
this.fields.push({ name, value, inline });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for `<RichEmbed>.addField('\u200B', '\u200B', inline)`.
|
||||
*/
|
||||
addBlankField(inline = false) {
|
||||
return this.addField('\u200B', '\u200B', inline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the thumbnail of this embed.
|
||||
*/
|
||||
setThumbnail(url: string) {
|
||||
if (typeof url !== 'string') throw new TypeError('RichEmbed Thumbnail URLs must be a string.');
|
||||
this.thumbnail = { url };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image of this embed.
|
||||
*/
|
||||
setImage(url: string) {
|
||||
if (typeof url !== 'string') throw new TypeError('RichEmbed Image URLs must be a string.');
|
||||
if (!url.startsWith('http://') || !url.startsWith('https://')) url = `https://${url}`;
|
||||
this.image = { url };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the footer of this embed.
|
||||
*/
|
||||
setFooter(text: string, icon_url?: string) {
|
||||
if (typeof text !== 'string') throw new TypeError('RichEmbed Footers must be a string.');
|
||||
if (icon_url && typeof icon_url !== 'string') throw new TypeError('RichEmbed Footer icon URLs must be a string.');
|
||||
if (text.length > 2048) throw new RangeError('RichEmbed footer text may not exceed 2048 characters.');
|
||||
this.footer = { text, icon_url };
|
||||
return this;
|
||||
}
|
||||
}
|
||||
/* eslint-disable no-param-reassign */
|
||||
|
||||
import { EmbedOptions } from 'eris';
|
||||
|
||||
export default class RichEmbed implements EmbedOptions {
|
||||
title?: string
|
||||
|
||||
type?: string
|
||||
|
||||
description?: string
|
||||
|
||||
url?: string
|
||||
|
||||
timestamp?: string | Date
|
||||
|
||||
color?: number
|
||||
|
||||
footer?: { text: string, icon_url?: string, proxy_icon_url?: string}
|
||||
|
||||
image?: { url?: string, proxy_url?: string, height?: number, width?: number }
|
||||
|
||||
thumbnail?: { url?: string, proxy_url?: string, height?: number, width?: number }
|
||||
|
||||
video?: { url: string, height?: number, width?: number }
|
||||
|
||||
provider?: { name: string, url?: string}
|
||||
|
||||
author?: { name: string, url?: string, proxy_icon_url?: string, icon_url?: string}
|
||||
|
||||
fields?: {name: string, value: string, inline?: boolean}[]
|
||||
|
||||
constructor(data: EmbedOptions = {}) {
|
||||
this.title = data.title;
|
||||
this.description = data.description;
|
||||
this.url = data.url;
|
||||
this.color = data.color;
|
||||
this.author = data.author;
|
||||
this.timestamp = data.timestamp;
|
||||
this.fields = data.fields || [];
|
||||
this.thumbnail = data.thumbnail;
|
||||
this.image = data.image;
|
||||
this.footer = data.footer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title of this embed.
|
||||
*/
|
||||
setTitle(title: string) {
|
||||
if (typeof title !== 'string') throw new TypeError('RichEmbed titles must be a string.');
|
||||
if (title.length > 256) throw new RangeError('RichEmbed titles may not exceed 256 characters.');
|
||||
this.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description of this embed.
|
||||
*/
|
||||
setDescription(description: string) {
|
||||
if (typeof description !== 'string') throw new TypeError('RichEmbed descriptions must be a string.');
|
||||
if (description.length > 2048) throw new RangeError('RichEmbed descriptions may not exceed 2048 characters.');
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URL of this embed.
|
||||
*/
|
||||
setURL(url: string) {
|
||||
if (typeof url !== 'string') throw new TypeError('RichEmbed URLs must be a string.');
|
||||
if (!url.startsWith('http://') && !url.startsWith('https://')) url = `https://${url}`;
|
||||
this.url = encodeURI(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of this embed.
|
||||
*/
|
||||
setColor(color: string | number) {
|
||||
if (typeof color === 'string' || typeof color === 'number') {
|
||||
if (typeof color === 'string') {
|
||||
const regex = /[^a-f0-9]/gi;
|
||||
color = color.replace(/#/g, '');
|
||||
if (regex.test(color)) throw new RangeError('Hexadecimal colours must not contain characters other than 0-9 and a-f.');
|
||||
color = parseInt(color, 16);
|
||||
} else if (color < 0 || color > 16777215) throw new RangeError('Base 10 colours must not be less than 0 or greater than 16777215.');
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
throw new TypeError('RichEmbed colours must be hexadecimal as string or number.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the author of this embed.
|
||||
*/
|
||||
setAuthor(name: string, icon_url?: string, url?: string) {
|
||||
if (typeof name !== 'string') throw new TypeError('RichEmbed Author names must be a string.');
|
||||
if (url && typeof url !== 'string') throw new TypeError('RichEmbed Author URLs must be a string.');
|
||||
if (icon_url && typeof icon_url !== 'string') throw new TypeError('RichEmbed Author icons must be a string.');
|
||||
this.author = { name, icon_url, url };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timestamp of this embed.
|
||||
*/
|
||||
setTimestamp(timestamp = new Date()) {
|
||||
if (Number.isNaN(timestamp.getTime())) throw new TypeError('Expecting ISO8601 (Date constructor)');
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a field to the embed (max 25).
|
||||
*/
|
||||
addField(name: string, value: string, inline = false) {
|
||||
if (typeof name !== 'string') throw new TypeError('RichEmbed Field names must be a string.');
|
||||
if (typeof value !== 'string') throw new TypeError('RichEmbed Field values must be a string.');
|
||||
if (typeof inline !== 'boolean') throw new TypeError('RichEmbed Field inlines must be a boolean.');
|
||||
if (this.fields.length >= 25) throw new RangeError('RichEmbeds may not exceed 25 fields.');
|
||||
if (name.length > 256) throw new RangeError('RichEmbed field names may not exceed 256 characters.');
|
||||
if (!/\S/.test(name)) throw new RangeError('RichEmbed field names may not be empty.');
|
||||
if (value.length > 1024) throw new RangeError('RichEmbed field values may not exceed 1024 characters.');
|
||||
if (!/\S/.test(value)) throw new RangeError('RichEmbed field values may not be empty.');
|
||||
this.fields.push({ name, value, inline });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for `<RichEmbed>.addField('\u200B', '\u200B', inline)`.
|
||||
*/
|
||||
addBlankField(inline = false) {
|
||||
return this.addField('\u200B', '\u200B', inline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the thumbnail of this embed.
|
||||
*/
|
||||
setThumbnail(url: string) {
|
||||
if (typeof url !== 'string') throw new TypeError('RichEmbed Thumbnail URLs must be a string.');
|
||||
this.thumbnail = { url };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image of this embed.
|
||||
*/
|
||||
setImage(url: string) {
|
||||
if (typeof url !== 'string') throw new TypeError('RichEmbed Image URLs must be a string.');
|
||||
if (!url.startsWith('http://') || !url.startsWith('https://')) url = `https://${url}`;
|
||||
this.image = { url };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the footer of this embed.
|
||||
*/
|
||||
setFooter(text: string, icon_url?: string) {
|
||||
if (typeof text !== 'string') throw new TypeError('RichEmbed Footers must be a string.');
|
||||
if (icon_url && typeof icon_url !== 'string') throw new TypeError('RichEmbed Footer icon URLs must be a string.');
|
||||
if (text.length > 2048) throw new RangeError('RichEmbed footer text may not exceed 2048 characters.');
|
||||
this.footer = { text, icon_url };
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,75 +1,75 @@
|
|||
/* eslint-disable consistent-return */
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { Server } from '.';
|
||||
|
||||
export default class Route {
|
||||
public server: Server;
|
||||
|
||||
public conf: { path: string; deprecated?: boolean; maintenance?: boolean; };
|
||||
|
||||
public router: Router;
|
||||
|
||||
constructor(server: Server) {
|
||||
this.server = server;
|
||||
this.conf = { path: '' };
|
||||
this.router = Router();
|
||||
}
|
||||
|
||||
public bind() {}
|
||||
|
||||
public init() {
|
||||
this.router.all('*', (req, res, next) => {
|
||||
this.server.client.util.signale.log(`'${req.method}' request from '${req.ip}' to '${req.hostname}${req.path}'.`);
|
||||
if (this.conf.maintenance === true) res.status(503).json({ code: this.constants.codes.MAINTENANCE_OR_UNAVAILABLE, message: this.constants.messages.MAINTENANCE_OR_UNAVAILABLE });
|
||||
else if (this.conf.deprecated === true) res.status(501).json({ code: this.constants.codes.DEPRECATED, message: this.constants.messages.DEPRECATED });
|
||||
else next();
|
||||
});
|
||||
}
|
||||
|
||||
public deprecated(): void {
|
||||
this.router.all('*', (_req, res) => {
|
||||
res.status(501).json({ code: this.constants.codes.DEPRECATED, message: this.constants.messages.DEPRECATED });
|
||||
});
|
||||
}
|
||||
|
||||
public maintenance(): void {
|
||||
this.router.all('*', (_req, res) => {
|
||||
res.status(503).json({ code: this.constants.codes.MAINTENANCE_OR_UNAVAILABLE, message: this.constants.messages.MAINTENANCE_OR_UNAVAILABLE });
|
||||
});
|
||||
}
|
||||
|
||||
public handleError(error: Error, res: Response) {
|
||||
res.status(500).json({ code: this.constants.codes.SERVER_ERROR, message: this.constants.messages.SERVER_ERROR });
|
||||
this.server.parent.client.util.handleError(error);
|
||||
}
|
||||
|
||||
get constants() {
|
||||
return {
|
||||
codes: {
|
||||
SUCCESS: 100,
|
||||
UNAUTHORIZED: 101,
|
||||
PERMISSION_DENIED: 104,
|
||||
ENDPOINT_NOT_FOUND: 104,
|
||||
NOT_FOUND: 1041,
|
||||
ACCOUNT_NOT_FOUND: 1041,
|
||||
CLIENT_ERROR: 1044,
|
||||
SERVER_ERROR: 105,
|
||||
DEPRECATED: 1051,
|
||||
MAINTENANCE_OR_UNAVAILABLE: 1053,
|
||||
},
|
||||
messages: {
|
||||
UNAUTHORIZED: ['CREDENTIALS_INVALID', 'The credentials you supplied are invalid.'],
|
||||
BEARER_TOKEN_INVALID: ['BEARER_TOKEN_INVALID', 'The Bearer token you supplied is invalid.'],
|
||||
PERMISSION_DENIED: ['PERMISSION_DENIED', 'You do not have valid credentials to access this resource.'],
|
||||
NOT_FOUND: ['NOT_FOUND', 'The resource you requested cannot be located.'],
|
||||
ENDPOINT_NOT_FOUND: ['ENDPOINT_NOT_FOUND', 'The endpoint you requested does not exist or cannot be located.'],
|
||||
SERVER_ERROR: ['INTERNAL_ERROR', 'An internal error has occurred, Engineers have been notified.'],
|
||||
DEPRECATED: ['ENDPOINT_OR_RESOURCE_DEPRECATED', 'The endpoint or resource you\'re trying to access has been deprecated.'],
|
||||
MAINTENANCE_OR_UNAVAILABLE: ['SERVICE_UNAVAILABLE', 'The endpoint or resource you\'re trying to access is either in maintenance or is not available.'],
|
||||
},
|
||||
discord: {
|
||||
SERVER_ID: '446067825673633794',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
/* eslint-disable consistent-return */
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { Server } from '.';
|
||||
|
||||
export default class Route {
|
||||
public server: Server;
|
||||
|
||||
public conf: { path: string; deprecated?: boolean; maintenance?: boolean; };
|
||||
|
||||
public router: Router;
|
||||
|
||||
constructor(server: Server) {
|
||||
this.server = server;
|
||||
this.conf = { path: '' };
|
||||
this.router = Router();
|
||||
}
|
||||
|
||||
public bind() {}
|
||||
|
||||
public init() {
|
||||
this.router.all('*', (req, res, next) => {
|
||||
this.server.client.util.signale.log(`'${req.method}' request from '${req.ip}' to '${req.hostname}${req.path}'.`);
|
||||
if (this.conf.maintenance === true) res.status(503).json({ code: this.constants.codes.MAINTENANCE_OR_UNAVAILABLE, message: this.constants.messages.MAINTENANCE_OR_UNAVAILABLE });
|
||||
else if (this.conf.deprecated === true) res.status(501).json({ code: this.constants.codes.DEPRECATED, message: this.constants.messages.DEPRECATED });
|
||||
else next();
|
||||
});
|
||||
}
|
||||
|
||||
public deprecated(): void {
|
||||
this.router.all('*', (_req, res) => {
|
||||
res.status(501).json({ code: this.constants.codes.DEPRECATED, message: this.constants.messages.DEPRECATED });
|
||||
});
|
||||
}
|
||||
|
||||
public maintenance(): void {
|
||||
this.router.all('*', (_req, res) => {
|
||||
res.status(503).json({ code: this.constants.codes.MAINTENANCE_OR_UNAVAILABLE, message: this.constants.messages.MAINTENANCE_OR_UNAVAILABLE });
|
||||
});
|
||||
}
|
||||
|
||||
public handleError(error: Error, res: Response) {
|
||||
res.status(500).json({ code: this.constants.codes.SERVER_ERROR, message: this.constants.messages.SERVER_ERROR });
|
||||
this.server.parent.client.util.handleError(error);
|
||||
}
|
||||
|
||||
get constants() {
|
||||
return {
|
||||
codes: {
|
||||
SUCCESS: 100,
|
||||
UNAUTHORIZED: 101,
|
||||
PERMISSION_DENIED: 104,
|
||||
ENDPOINT_NOT_FOUND: 104,
|
||||
NOT_FOUND: 1041,
|
||||
ACCOUNT_NOT_FOUND: 1041,
|
||||
CLIENT_ERROR: 1044,
|
||||
SERVER_ERROR: 105,
|
||||
DEPRECATED: 1051,
|
||||
MAINTENANCE_OR_UNAVAILABLE: 1053,
|
||||
},
|
||||
messages: {
|
||||
UNAUTHORIZED: ['CREDENTIALS_INVALID', 'The credentials you supplied are invalid.'],
|
||||
BEARER_TOKEN_INVALID: ['BEARER_TOKEN_INVALID', 'The Bearer token you supplied is invalid.'],
|
||||
PERMISSION_DENIED: ['PERMISSION_DENIED', 'You do not have valid credentials to access this resource.'],
|
||||
NOT_FOUND: ['NOT_FOUND', 'The resource you requested cannot be located.'],
|
||||
ENDPOINT_NOT_FOUND: ['ENDPOINT_NOT_FOUND', 'The endpoint you requested does not exist or cannot be located.'],
|
||||
SERVER_ERROR: ['INTERNAL_ERROR', 'An internal error has occurred, Engineers have been notified.'],
|
||||
DEPRECATED: ['ENDPOINT_OR_RESOURCE_DEPRECATED', 'The endpoint or resource you\'re trying to access has been deprecated.'],
|
||||
MAINTENANCE_OR_UNAVAILABLE: ['SERVICE_UNAVAILABLE', 'The endpoint or resource you\'re trying to access is either in maintenance or is not available.'],
|
||||
},
|
||||
discord: {
|
||||
SERVER_ID: '446067825673633794',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,68 +1,68 @@
|
|||
import express from 'express';
|
||||
import helmet from 'helmet';
|
||||
import { promises as fs } from 'fs';
|
||||
import { Server as HTTPServer } from 'http';
|
||||
import { Collection, ServerManagement, Route } from '.';
|
||||
|
||||
export default class Server {
|
||||
public app: express.Application;
|
||||
|
||||
public routes: Collection<Route>;
|
||||
|
||||
public parent: ServerManagement;
|
||||
|
||||
public port: number;
|
||||
|
||||
private root: string;
|
||||
|
||||
constructor(parent: ServerManagement, port: number, routeRoot: string) {
|
||||
this.parent = parent;
|
||||
this.app = express();
|
||||
this.routes = new Collection<Route>();
|
||||
this.port = port;
|
||||
this.root = routeRoot;
|
||||
|
||||
this.loadRoutes();
|
||||
this.init();
|
||||
}
|
||||
|
||||
get client() {
|
||||
return this.parent.client;
|
||||
}
|
||||
|
||||
public async loadRoutes() {
|
||||
const routes = Object.values<typeof Route>(require(this.root));
|
||||
for (const RouteFile of routes) {
|
||||
const route = new RouteFile(this);
|
||||
if (route.conf.deprecated) {
|
||||
route.deprecated();
|
||||
} else if (route.conf.maintenance) {
|
||||
route.maintenance();
|
||||
} else {
|
||||
route.init();
|
||||
route.bind();
|
||||
}
|
||||
this.parent.client.util.signale.success(`Successfully loaded route 'http://localhost:${this.port}/${route.conf.path}'.`);
|
||||
this.routes.add(route.conf.path, route);
|
||||
this.app.use(route.conf.path, route.router);
|
||||
}
|
||||
this.app.listen(this.port);
|
||||
}
|
||||
|
||||
public init() {
|
||||
this.app.set('trust proxy', 'loopback');
|
||||
this.app.use(helmet({
|
||||
hsts: false,
|
||||
hidePoweredBy: false,
|
||||
contentSecurityPolicy: {
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
},
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
public listen(port: number): HTTPServer {
|
||||
return this.app.listen(port);
|
||||
}
|
||||
}
|
||||
import express from 'express';
|
||||
import helmet from 'helmet';
|
||||
import { promises as fs } from 'fs';
|
||||
import { Server as HTTPServer } from 'http';
|
||||
import { Collection, ServerManagement, Route } from '.';
|
||||
|
||||
export default class Server {
|
||||
public app: express.Application;
|
||||
|
||||
public routes: Collection<Route>;
|
||||
|
||||
public parent: ServerManagement;
|
||||
|
||||
public port: number;
|
||||
|
||||
private root: string;
|
||||
|
||||
constructor(parent: ServerManagement, port: number, routeRoot: string) {
|
||||
this.parent = parent;
|
||||
this.app = express();
|
||||
this.routes = new Collection<Route>();
|
||||
this.port = port;
|
||||
this.root = routeRoot;
|
||||
|
||||
this.loadRoutes();
|
||||
this.init();
|
||||
}
|
||||
|
||||
get client() {
|
||||
return this.parent.client;
|
||||
}
|
||||
|
||||
public async loadRoutes() {
|
||||
const routes = Object.values<typeof Route>(require(this.root));
|
||||
for (const RouteFile of routes) {
|
||||
const route = new RouteFile(this);
|
||||
if (route.conf.deprecated) {
|
||||
route.deprecated();
|
||||
} else if (route.conf.maintenance) {
|
||||
route.maintenance();
|
||||
} else {
|
||||
route.init();
|
||||
route.bind();
|
||||
}
|
||||
this.parent.client.util.signale.success(`Successfully loaded route 'http://localhost:${this.port}/${route.conf.path}'.`);
|
||||
this.routes.add(route.conf.path, route);
|
||||
this.app.use(route.conf.path, route.router);
|
||||
}
|
||||
this.app.listen(this.port);
|
||||
}
|
||||
|
||||
public init() {
|
||||
this.app.set('trust proxy', 'loopback');
|
||||
this.app.use(helmet({
|
||||
hsts: false,
|
||||
hidePoweredBy: false,
|
||||
contentSecurityPolicy: {
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
},
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
public listen(port: number): HTTPServer {
|
||||
return this.app.listen(port);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
import { Client, Collection, Server } from '.';
|
||||
import serverSetup from '../api';
|
||||
|
||||
export default class ServerManagement {
|
||||
public client: Client;
|
||||
|
||||
public servers: Collection<Server>;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
this.servers = new Collection<Server>();
|
||||
this.loadServers();
|
||||
}
|
||||
|
||||
public async loadServers() {
|
||||
const apiRoot = Object.entries<(management: ServerManagement) => Server>(serverSetup);
|
||||
for (const [api, server] of apiRoot) {
|
||||
this.servers.add(api, server(this));
|
||||
this.client.util.signale.success(`Successfully loaded server '${api}'.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
import { Client, Collection, Server } from '.';
|
||||
import serverSetup from '../api';
|
||||
|
||||
export default class ServerManagement {
|
||||
public client: Client;
|
||||
|
||||
public servers: Collection<Server>;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
this.servers = new Collection<Server>();
|
||||
this.loadServers();
|
||||
}
|
||||
|
||||
public async loadServers() {
|
||||
const apiRoot = Object.entries<(management: ServerManagement) => Server>(serverSetup);
|
||||
for (const [api, server] of apiRoot) {
|
||||
this.servers.add(api, server(this));
|
||||
this.client.util.signale.success(`Successfully loaded server '${api}'.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,138 +1,138 @@
|
|||
/* eslint-disable no-bitwise */
|
||||
import nodemailer from 'nodemailer';
|
||||
import signale from 'signale';
|
||||
import { Member, Message, Guild, PrivateChannel, GroupChannel, Role, AnyGuildChannel } from 'eris';
|
||||
import { Client, Command, Moderation, RichEmbed } from '.';
|
||||
import { statusMessages as emotes } from '../configs/emotes.json';
|
||||
|
||||
export default class Util {
|
||||
public client: Client;
|
||||
|
||||
public moderation: Moderation;
|
||||
|
||||
public signale: signale.Signale;
|
||||
|
||||
public transporter: nodemailer.Transporter;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
this.moderation = new Moderation(this.client);
|
||||
this.signale = signale;
|
||||
this.signale.config({
|
||||
displayDate: true,
|
||||
displayTimestamp: true,
|
||||
displayFilename: true,
|
||||
});
|
||||
this.transporter = nodemailer.createTransport({
|
||||
host: 'staff.libraryofcode.org',
|
||||
port: 587,
|
||||
auth: { user: 'internal', pass: this.client.config.emailPass },
|
||||
});
|
||||
}
|
||||
|
||||
get emojis() {
|
||||
return {
|
||||
SUCCESS: emotes.success,
|
||||
LOADING: emotes.loading,
|
||||
ERROR: emotes.error,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a command
|
||||
* @param query Command input
|
||||
* @param message Only used to check for errors
|
||||
*/
|
||||
public resolveCommand(query: string | string[]): Promise<{cmd: Command, args: string[] }> {
|
||||
try {
|
||||
if (typeof query === 'string') query = query.split(' ');
|
||||
const commands = this.client.commands.toArray();
|
||||
const resolvedCommand = commands.find((c) => c.name === query[0].toLowerCase() || c.aliases.includes(query[0].toLowerCase()));
|
||||
|
||||
if (!resolvedCommand) return Promise.resolve(null);
|
||||
query.shift();
|
||||
return Promise.resolve({ cmd: resolvedCommand, args: query });
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
public resolveGuildChannel(query: string, { channels }: Guild, categories = false): AnyGuildChannel | undefined {
|
||||
const ch: AnyGuildChannel[] = channels.filter((c) => (!categories ? c.type !== 4 : true));
|
||||
return ch.find((c) => c.id === query.replace(/[<#>]/g, '') || c.name === query)
|
||||
|| ch.find((c) => c.name.toLowerCase() === query.toLowerCase())
|
||||
|| ch.find((c) => c.name.toLowerCase().startsWith(query.toLowerCase()));
|
||||
}
|
||||
|
||||
public resolveRole(query: string, { roles }: Guild): Role | undefined {
|
||||
return roles.find((r) => r.id === query.replace(/[<@&>]/g, '') || r.name === query)
|
||||
|| roles.find((r) => r.name.toLowerCase() === query.toLowerCase())
|
||||
|| roles.find((r) => r.name.toLowerCase().startsWith(query.toLowerCase()));
|
||||
}
|
||||
|
||||
public resolveMember(query: string, { members }: Guild): Member | undefined {
|
||||
return members.find((m) => `${m.username}#${m.discriminator}` === query || m.username === query || m.id === query.replace(/[<@!>]/g, '') || m.nick === query) // Exact match for mention, username+discrim, username and user ID
|
||||
|| members.find((m) => `${m.username.toLowerCase()}#${m.discriminator}` === query.toLowerCase() || m.username.toLowerCase() === query.toLowerCase() || (m.nick && m.nick.toLowerCase() === query.toLowerCase())) // Case insensitive match for username+discrim, username
|
||||
|| members.find((m) => m.username.toLowerCase().startsWith(query.toLowerCase()) || (m.nick && m.nick.toLowerCase().startsWith(query.toLowerCase())));
|
||||
}
|
||||
|
||||
public async handleError(error: Error, message?: Message, command?: Command, disable = true): Promise<void> {
|
||||
try {
|
||||
this.signale.error(error);
|
||||
const info = { content: `\`\`\`js\n${error.stack || error}\n\`\`\``, embed: null };
|
||||
if (message) {
|
||||
const embed = new RichEmbed();
|
||||
embed.setColor('FF0000');
|
||||
embed.setAuthor(`Error caused by ${message.author.username}#${message.author.discriminator}`, message.author.avatarURL);
|
||||
embed.setTitle('Message content');
|
||||
embed.setDescription(message.content);
|
||||
embed.addField('User', `${message.author.mention} (\`${message.author.id}\`)`, true);
|
||||
embed.addField('Channel', message.channel.mention, true);
|
||||
let guild: string;
|
||||
if (message.channel instanceof PrivateChannel || message.channel instanceof GroupChannel) guild = '@me';
|
||||
else guild = message.channel.guild.id;
|
||||
embed.addField('Message link', `[Click here](https://discordapp.com/channels/${guild}/${message.channel.id}/${message.id})`, true);
|
||||
embed.setTimestamp(new Date(message.timestamp));
|
||||
info.embed = embed;
|
||||
}
|
||||
await this.client.createMessage('595788220764127272', info);
|
||||
const msg = message ? message.content.slice(this.client.config.prefix.length).trim().split(/ +/g) : [];
|
||||
if (command && disable) this.resolveCommand(msg).then((c) => { c.cmd.enabled = false; });
|
||||
if (message) message.channel.createMessage(`***${this.emojis.ERROR} An unexpected error has occured - please contact a Staff member.${command && disable ? ' This command has been disabled.' : ''}***`);
|
||||
} catch (err) {
|
||||
this.signale.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
public splitString(string: string, length: number): string[] {
|
||||
if (!string) return [];
|
||||
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);
|
||||
string = string.substr(pos);
|
||||
arrayString.push(str);
|
||||
}
|
||||
return arrayString;
|
||||
}
|
||||
|
||||
public splitFields(fields: { name: string, value: string, inline?: boolean }[]): { name: string, value: string, inline?: boolean }[][] {
|
||||
let index = 0;
|
||||
const array: {name: string, value: string, inline?: boolean}[][] = [[]];
|
||||
while (fields.length) {
|
||||
if (array[index].length >= 25) { index += 1; array[index] = []; }
|
||||
array[index].push(fields[0]); fields.shift();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public decimalToHex(int: number): string {
|
||||
const hex = int.toString(16);
|
||||
return '#000000'.substring(0, 7 - hex.length) + hex;
|
||||
}
|
||||
}
|
||||
/* eslint-disable no-bitwise */
|
||||
import nodemailer from 'nodemailer';
|
||||
import signale from 'signale';
|
||||
import { Member, Message, Guild, PrivateChannel, GroupChannel, Role, AnyGuildChannel } from 'eris';
|
||||
import { Client, Command, Moderation, RichEmbed } from '.';
|
||||
import { statusMessages as emotes } from '../configs/emotes.json';
|
||||
|
||||
export default class Util {
|
||||
public client: Client;
|
||||
|
||||
public moderation: Moderation;
|
||||
|
||||
public signale: signale.Signale;
|
||||
|
||||
public transporter: nodemailer.Transporter;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
this.moderation = new Moderation(this.client);
|
||||
this.signale = signale;
|
||||
this.signale.config({
|
||||
displayDate: true,
|
||||
displayTimestamp: true,
|
||||
displayFilename: true,
|
||||
});
|
||||
this.transporter = nodemailer.createTransport({
|
||||
host: 'staff.libraryofcode.org',
|
||||
port: 587,
|
||||
auth: { user: 'internal', pass: this.client.config.emailPass },
|
||||
});
|
||||
}
|
||||
|
||||
get emojis() {
|
||||
return {
|
||||
SUCCESS: emotes.success,
|
||||
LOADING: emotes.loading,
|
||||
ERROR: emotes.error,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a command
|
||||
* @param query Command input
|
||||
* @param message Only used to check for errors
|
||||
*/
|
||||
public resolveCommand(query: string | string[]): Promise<{cmd: Command, args: string[] }> {
|
||||
try {
|
||||
if (typeof query === 'string') query = query.split(' ');
|
||||
const commands = this.client.commands.toArray();
|
||||
const resolvedCommand = commands.find((c) => c.name === query[0].toLowerCase() || c.aliases.includes(query[0].toLowerCase()));
|
||||
|
||||
if (!resolvedCommand) return Promise.resolve(null);
|
||||
query.shift();
|
||||
return Promise.resolve({ cmd: resolvedCommand, args: query });
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
public resolveGuildChannel(query: string, { channels }: Guild, categories = false): AnyGuildChannel | undefined {
|
||||
const ch: AnyGuildChannel[] = channels.filter((c) => (!categories ? c.type !== 4 : true));
|
||||
return ch.find((c) => c.id === query.replace(/[<#>]/g, '') || c.name === query)
|
||||
|| ch.find((c) => c.name.toLowerCase() === query.toLowerCase())
|
||||
|| ch.find((c) => c.name.toLowerCase().startsWith(query.toLowerCase()));
|
||||
}
|
||||
|
||||
public resolveRole(query: string, { roles }: Guild): Role | undefined {
|
||||
return roles.find((r) => r.id === query.replace(/[<@&>]/g, '') || r.name === query)
|
||||
|| roles.find((r) => r.name.toLowerCase() === query.toLowerCase())
|
||||
|| roles.find((r) => r.name.toLowerCase().startsWith(query.toLowerCase()));
|
||||
}
|
||||
|
||||
public resolveMember(query: string, { members }: Guild): Member | undefined {
|
||||
return members.find((m) => `${m.username}#${m.discriminator}` === query || m.username === query || m.id === query.replace(/[<@!>]/g, '') || m.nick === query) // Exact match for mention, username+discrim, username and user ID
|
||||
|| members.find((m) => `${m.username.toLowerCase()}#${m.discriminator}` === query.toLowerCase() || m.username.toLowerCase() === query.toLowerCase() || (m.nick && m.nick.toLowerCase() === query.toLowerCase())) // Case insensitive match for username+discrim, username
|
||||
|| members.find((m) => m.username.toLowerCase().startsWith(query.toLowerCase()) || (m.nick && m.nick.toLowerCase().startsWith(query.toLowerCase())));
|
||||
}
|
||||
|
||||
public async handleError(error: Error, message?: Message, command?: Command, disable = true): Promise<void> {
|
||||
try {
|
||||
this.signale.error(error);
|
||||
const info = { content: `\`\`\`js\n${error.stack || error}\n\`\`\``, embed: null };
|
||||
if (message) {
|
||||
const embed = new RichEmbed();
|
||||
embed.setColor('FF0000');
|
||||
embed.setAuthor(`Error caused by ${message.author.username}#${message.author.discriminator}`, message.author.avatarURL);
|
||||
embed.setTitle('Message content');
|
||||
embed.setDescription(message.content);
|
||||
embed.addField('User', `${message.author.mention} (\`${message.author.id}\`)`, true);
|
||||
embed.addField('Channel', message.channel.mention, true);
|
||||
let guild: string;
|
||||
if (message.channel instanceof PrivateChannel || message.channel instanceof GroupChannel) guild = '@me';
|
||||
else guild = message.channel.guild.id;
|
||||
embed.addField('Message link', `[Click here](https://discordapp.com/channels/${guild}/${message.channel.id}/${message.id})`, true);
|
||||
embed.setTimestamp(new Date(message.timestamp));
|
||||
info.embed = embed;
|
||||
}
|
||||
await this.client.createMessage('595788220764127272', info);
|
||||
const msg = message ? message.content.slice(this.client.config.prefix.length).trim().split(/ +/g) : [];
|
||||
if (command && disable) this.resolveCommand(msg).then((c) => { c.cmd.enabled = false; });
|
||||
if (message) message.channel.createMessage(`***${this.emojis.ERROR} An unexpected error has occured - please contact a Staff member.${command && disable ? ' This command has been disabled.' : ''}***`);
|
||||
} catch (err) {
|
||||
this.signale.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
public splitString(string: string, length: number): string[] {
|
||||
if (!string) return [];
|
||||
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);
|
||||
string = string.substr(pos);
|
||||
arrayString.push(str);
|
||||
}
|
||||
return arrayString;
|
||||
}
|
||||
|
||||
public splitFields(fields: { name: string, value: string, inline?: boolean }[]): { name: string, value: string, inline?: boolean }[][] {
|
||||
let index = 0;
|
||||
const array: {name: string, value: string, inline?: boolean}[][] = [[]];
|
||||
while (fields.length) {
|
||||
if (array[index].length >= 25) { index += 1; array[index] = []; }
|
||||
array[index].push(fields[0]); fields.shift();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public decimalToHex(int: number): string {
|
||||
const hex = int.toString(16);
|
||||
return '#000000'.substring(0, 7 - hex.length) + hex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
export { default as Client } from './Client';
|
||||
export { default as Collection } from './Collection';
|
||||
export { default as Command } from './Command';
|
||||
export { default as Event } from './Event';
|
||||
export { default as Moderation } from './Moderation';
|
||||
export { default as RichEmbed } from './RichEmbed';
|
||||
export { default as Route } from './Route';
|
||||
export { default as Server } from './Server';
|
||||
export { default as ServerManagement } from './ServerManagement';
|
||||
export { default as Util } from './Util';
|
||||
export { default as Client } from './Client';
|
||||
export { default as Collection } from './Collection';
|
||||
export { default as Command } from './Command';
|
||||
export { default as Event } from './Event';
|
||||
export { default as Moderation } from './Moderation';
|
||||
export { default as RichEmbed } from './RichEmbed';
|
||||
export { default as Route } from './Route';
|
||||
export { default as Server } from './Server';
|
||||
export { default as ServerManagement } from './ServerManagement';
|
||||
export { default as Util } from './Util';
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
import { Message } from 'eris';
|
||||
import { Client, Command } from '../class';
|
||||
|
||||
export default class AddRank extends Command {
|
||||
constructor(client: Client) {
|
||||
super(client);
|
||||
this.name = 'addrank';
|
||||
this.description = 'Makes a role self-assignable.';
|
||||
this.usage = `${this.client.config.prefix}addrank <role> <permissions, pass 0 for everyone. separate role IDs with ':'> <description>`;
|
||||
this.permissions = 6;
|
||||
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]);
|
||||
if (!args[1]) return this.error(message.channel, 'Permissions are 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));
|
||||
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 });
|
||||
if (check) return this.error(message.channel, 'This role is already self-assignable.');
|
||||
|
||||
let permissions: string[];
|
||||
if (args[1] === '0') {
|
||||
permissions = ['0'];
|
||||
} else {
|
||||
permissions = args[1].split(':');
|
||||
}
|
||||
|
||||
const entry = new this.client.db.Rank({
|
||||
name: role.name,
|
||||
roleID: role.id,
|
||||
permissions,
|
||||
description: args.slice(2).join(' '),
|
||||
});
|
||||
await entry.save();
|
||||
return this.success(message.channel, `Role ${role.name} is now self-assignable.`);
|
||||
} catch (err) {
|
||||
return this.client.util.handleError(err, message, this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import { Message } from 'eris';
|
||||
import { Client, Command } from '../class';
|
||||
|
||||
export default class DelRank extends Command {
|
||||
constructor(client: Client) {
|
||||
super(client);
|
||||
this.name = 'delrank';
|
||||
this.description = 'Deletes an existing self-assignable role. This doesn\'t delete the role itself.';
|
||||
this.usage = `${this.client.config.prefix}delrank <role>`;
|
||||
this.permissions = 6;
|
||||
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 role = this.client.util.resolveRole(args[0], this.client.guilds.get(this.client.config.guildID));
|
||||
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 });
|
||||
if (!check) return this.error(message.channel, 'The entry doesn\'t appear to exist.');
|
||||
|
||||
await this.client.db.Rank.deleteOne({ roleID: role.id });
|
||||
return this.success(message.channel, `Role ${role.name} is no longer self-assignable.`);
|
||||
} catch (err) {
|
||||
return this.client.util.handleError(err, message, this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
export { default as additem } from './additem';
|
||||
export { default as addrank } from './addrank';
|
||||
export { default as addredirect } from './addredirect';
|
||||
export { default as ban } from './ban';
|
||||
export { default as delitem } from './delitem';
|
||||
export { default as delrank } from './delrank';
|
||||
export { default as delredirect } from './delredirect';
|
||||
export { default as djs } from './djs';
|
||||
export { default as eval } from './eval';
|
||||
|
@ -13,6 +15,7 @@ export { default as listredirects } from './listredirects';
|
|||
export { default as npm } from './npm';
|
||||
export { default as page } from './page';
|
||||
export { default as ping } from './ping';
|
||||
export { default as rank } from './rank';
|
||||
export { default as roleinfo } from './roleinfo';
|
||||
export { default as unban } from './unban';
|
||||
export { default as whois } from './whois';
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
import { Message, Role } from 'eris';
|
||||
import { Client, Command, RichEmbed } from '../class';
|
||||
|
||||
export default class Rank extends Command {
|
||||
constructor(client: Client) {
|
||||
super(client);
|
||||
this.name = 'rank';
|
||||
this.description = 'Joins/leaves a self-assignable rank. Run this command without arguments to get a list of self-assignable roles.';
|
||||
this.usage = `${this.client.config.prefix}rank <rank>`;
|
||||
this.permissions = 0;
|
||||
this.guildOnly = true;
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
public async run(message: Message, args: string[]) {
|
||||
try {
|
||||
if (!args[0]) {
|
||||
const roles = await this.client.db.Rank.find();
|
||||
const embed = new RichEmbed();
|
||||
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))) {
|
||||
let perms: string;
|
||||
if (rank.permissions.includes('0')) {
|
||||
perms = 'Everyone';
|
||||
} else {
|
||||
const rolesArray: Role[] = [];
|
||||
rank.permissions.forEach((r) => {
|
||||
rolesArray.push(this.client.guilds.get(this.client.config.guildID).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(', ');
|
||||
}
|
||||
embed.addField(rank.name, `__Description:__ ${rank.description}\n__Permissions:__ ${perms}`);
|
||||
}
|
||||
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||
embed.setTimestamp();
|
||||
return message.channel.createMessage({ embed });
|
||||
}
|
||||
const role = this.client.util.resolveRole(args[0], this.client.guilds.get(this.client.config.guildID));
|
||||
if (!role) return this.error(message.channel, 'The role you specified doesn\'t exist.');
|
||||
const entry = await this.client.db.Rank.findOne({ roleID: role.id }).lean().exec();
|
||||
if (!entry) return this.error(message.channel, 'The rank you specified doesn\'t exist.');
|
||||
if (!message.member.roles.includes(entry.roleID)) {
|
||||
let permCheck: boolean;
|
||||
if (entry.permissions.includes('0')) {
|
||||
permCheck = true;
|
||||
} else {
|
||||
permCheck = entry.permissions.some((item) => message.member.roles.includes(item));
|
||||
}
|
||||
if (!permCheck) return this.error(message.channel, 'Permission denied.');
|
||||
await message.member.addRole(entry.roleID, `User ${message.author.username}#${message.author.discriminator} self-assigned this role.`);
|
||||
this.success(message.channel, `You have self-assigned ${entry.name}.`);
|
||||
} else if (message.member.roles.includes(entry.roleID)) {
|
||||
await message.member.removeRole(entry.roleID, `User ${message.author.username}#${message.author.discriminator} has removed a self-assignable role.`);
|
||||
this.success(message.channel, `You have removed ${entry.name}.`);
|
||||
}
|
||||
return null;
|
||||
} catch (err) {
|
||||
return this.client.util.handleError(err, message, this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,142 +1,142 @@
|
|||
[
|
||||
{
|
||||
"name": "Matthew",
|
||||
"id": "278620217221971968",
|
||||
"title": "Chief Director of Engineering",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "matthew@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/matthew",
|
||||
"github": "https://github.com/matthew119427",
|
||||
"bio": "so baby come light me up, and maybe ill let you on it. a little bit dangerous, but baby thats how i want it. a little less conversation and a little more touch my body. cuz im so into you... ~ Ariana Grande, Into You - Dangerous Woman",
|
||||
"acknowledgements": ["Maintainer & Lead Developer"]
|
||||
},
|
||||
{
|
||||
"name": "Joe",
|
||||
"id": "556969659531001858",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "joe@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/Joe",
|
||||
"github": "https://github.com/sirdroolio",
|
||||
"bio": "new Error(\"Proper Bio not found\");",
|
||||
"acknowledgements": ["Developer"]
|
||||
},
|
||||
{
|
||||
"name": "Bsian",
|
||||
"id": "253600545972027394",
|
||||
"title": "Director of Engineering",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "bsian@staff.libraryofcode.org",
|
||||
"bio": "I also like trains",
|
||||
"acknowledgements": ["Maintainer & Assistant Lead Developer"]
|
||||
},
|
||||
{
|
||||
"name": "NightRaven",
|
||||
"id": "239261547959025665",
|
||||
"title": "Director of Information Security",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "nightraven@staff.libraryofcode.org",
|
||||
"bio": "I like trains"
|
||||
},
|
||||
{
|
||||
"name": "Unknown",
|
||||
"id": "143414786913206272",
|
||||
"title": "Director of Operations",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "unknown@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/unknown",
|
||||
"bio": "im not a proffesional developer or anything, i just enjoy it as a hobby."
|
||||
},
|
||||
{
|
||||
"name": "TheSkele27",
|
||||
"id": "213632190557192192",
|
||||
"title": "Director of Community Engagement",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "theskele27@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/TheSkele27",
|
||||
"github": "https://github.com/TheSkele27",
|
||||
"bio": "Is water wet?"
|
||||
},
|
||||
{
|
||||
"name": "Catbirby",
|
||||
"id": "131953641371205632",
|
||||
"dept": "Supervisor",
|
||||
"emailAddress": "catbirby@staff.libraryofcode.org",
|
||||
"github": "https://github.com/catbirby",
|
||||
"bio": "Computer Tech/Networking Nerd/Sysadmin/Graphic Designer/Audiophile. I don't do much coding but know my way around most languages."
|
||||
},
|
||||
{
|
||||
"name": "D3XTER",
|
||||
"id": "468009964263178262",
|
||||
"dept": "Core Team",
|
||||
"emailAddress": "dexter@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/D3XTER",
|
||||
"bio": "Hi I'm D3XTER how are ya?"
|
||||
},
|
||||
{
|
||||
"name": "DedShotTM",
|
||||
"id": "402154763363418142",
|
||||
"dept": "Technician & Moderator",
|
||||
"emailAddress": "dedshot@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/DedShotTM",
|
||||
"github": "https://github.com/DedShotTM",
|
||||
"bio": "Imagine having a bio",
|
||||
"acknowledgements": ["Contributor"]
|
||||
},
|
||||
{
|
||||
"name": "EdgyBoi2414",
|
||||
"id": "397432516010835970",
|
||||
"dept": "Core Team",
|
||||
"emailAddress": "edgyboi2414@gmail.com",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/EdgyBoi2414",
|
||||
"github": "https://github.com/EdgyBoi2414",
|
||||
"bio": "\"If teardrops could be bottled, there'd be swimming pools, built by models...\" - Some Philosopher"
|
||||
},
|
||||
{
|
||||
"name": "Hector",
|
||||
"id": "377781496292835339",
|
||||
"dept": "Core Team",
|
||||
"emailAddress": "hector@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/Hector",
|
||||
"github": "https://github.com/Hector6704",
|
||||
"bio": "Hi there, I'm the developer of Delta, the Discord bot. I'm a free-time French JavaScript developer. I hope you'll enjoy LOC!"
|
||||
},
|
||||
{
|
||||
"name": "KhaaZ",
|
||||
"id": "179908288337412096",
|
||||
"dept": "Core Team",
|
||||
"emailAddress": "khaaz@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/KhaaZ",
|
||||
"github": "https://github.com/Khaazz",
|
||||
"bio": "I baguette for a living and eat code for breakfast."
|
||||
},
|
||||
{
|
||||
"name": "Ryan",
|
||||
"id": "186679073764802560",
|
||||
"dept": "Associate",
|
||||
"emailAddress": "wbdvryan@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/plainRyan",
|
||||
"bio": "Experiment, learn, share, repeat.",
|
||||
"acknowledgements": ["Contributor"]
|
||||
},
|
||||
{
|
||||
"name": "Zloth",
|
||||
"id": "382368885267234816",
|
||||
"dept": "Associate",
|
||||
"emailAddress": "zloth@staff.libraryofcode.org",
|
||||
"github": "https://github.com/gavintjhxx",
|
||||
"bio": "Wake up. Eat. Code. Sleep. Loop()"
|
||||
},
|
||||
{
|
||||
"name": "PlayerVMachine",
|
||||
"id": "273999507174195203",
|
||||
"dept": "Instructor & Associate",
|
||||
"emailAddress": "nicolas@staff.libraryofcode.org",
|
||||
"bio": "I write C++ to pay off my student loans"
|
||||
},
|
||||
{
|
||||
"name": "Null",
|
||||
"id": "323673862971588609",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/null",
|
||||
"acknowledgements": ["Contributor"]
|
||||
}
|
||||
]
|
||||
[
|
||||
{
|
||||
"name": "Matthew",
|
||||
"id": "278620217221971968",
|
||||
"title": "Chief Director of Engineering",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "matthew@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/matthew",
|
||||
"github": "https://github.com/matthew119427",
|
||||
"bio": "so baby come light me up, and maybe ill let you on it. a little bit dangerous, but baby thats how i want it. a little less conversation and a little more touch my body. cuz im so into you... ~ Ariana Grande, Into You - Dangerous Woman",
|
||||
"acknowledgements": ["Maintainer & Lead Developer"]
|
||||
},
|
||||
{
|
||||
"name": "Joe",
|
||||
"id": "556969659531001858",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "joe@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/Joe",
|
||||
"github": "https://github.com/sirdroolio",
|
||||
"bio": "new Error(\"Proper Bio not found\");",
|
||||
"acknowledgements": ["Developer"]
|
||||
},
|
||||
{
|
||||
"name": "Bsian",
|
||||
"id": "253600545972027394",
|
||||
"title": "Director of Engineering",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "bsian@staff.libraryofcode.org",
|
||||
"bio": "I also like trains",
|
||||
"acknowledgements": ["Maintainer & Assistant Lead Developer"]
|
||||
},
|
||||
{
|
||||
"name": "NightRaven",
|
||||
"id": "239261547959025665",
|
||||
"title": "Director of Information Security",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "nightraven@staff.libraryofcode.org",
|
||||
"bio": "I like trains"
|
||||
},
|
||||
{
|
||||
"name": "Unknown",
|
||||
"id": "143414786913206272",
|
||||
"title": "Director of Operations",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "unknown@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/unknown",
|
||||
"bio": "im not a proffesional developer or anything, i just enjoy it as a hobby."
|
||||
},
|
||||
{
|
||||
"name": "TheSkele27",
|
||||
"id": "213632190557192192",
|
||||
"title": "Director of Community Engagement",
|
||||
"dept": "Board of Directors",
|
||||
"emailAddress": "theskele27@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/TheSkele27",
|
||||
"github": "https://github.com/TheSkele27",
|
||||
"bio": "Is water wet?"
|
||||
},
|
||||
{
|
||||
"name": "Catbirby",
|
||||
"id": "131953641371205632",
|
||||
"dept": "Supervisor",
|
||||
"emailAddress": "catbirby@staff.libraryofcode.org",
|
||||
"github": "https://github.com/catbirby",
|
||||
"bio": "Computer Tech/Networking Nerd/Sysadmin/Graphic Designer/Audiophile. I don't do much coding but know my way around most languages."
|
||||
},
|
||||
{
|
||||
"name": "D3XTER",
|
||||
"id": "468009964263178262",
|
||||
"dept": "Core Team",
|
||||
"emailAddress": "dexter@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/D3XTER",
|
||||
"bio": "Hi I'm D3XTER how are ya?"
|
||||
},
|
||||
{
|
||||
"name": "DedShotTM",
|
||||
"id": "402154763363418142",
|
||||
"dept": "Technician & Moderator",
|
||||
"emailAddress": "dedshot@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/DedShotTM",
|
||||
"github": "https://github.com/DedShotTM",
|
||||
"bio": "Imagine having a bio",
|
||||
"acknowledgements": ["Contributor"]
|
||||
},
|
||||
{
|
||||
"name": "EdgyBoi2414",
|
||||
"id": "397432516010835970",
|
||||
"dept": "Core Team",
|
||||
"emailAddress": "edgyboi2414@gmail.com",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/EdgyBoi2414",
|
||||
"github": "https://github.com/EdgyBoi2414",
|
||||
"bio": "\"If teardrops could be bottled, there'd be swimming pools, built by models...\" - Some Philosopher"
|
||||
},
|
||||
{
|
||||
"name": "Hector",
|
||||
"id": "377781496292835339",
|
||||
"dept": "Core Team",
|
||||
"emailAddress": "hector@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/Hector",
|
||||
"github": "https://github.com/Hector6704",
|
||||
"bio": "Hi there, I'm the developer of Delta, the Discord bot. I'm a free-time French JavaScript developer. I hope you'll enjoy LOC!"
|
||||
},
|
||||
{
|
||||
"name": "KhaaZ",
|
||||
"id": "179908288337412096",
|
||||
"dept": "Core Team",
|
||||
"emailAddress": "khaaz@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/KhaaZ",
|
||||
"github": "https://github.com/Khaazz",
|
||||
"bio": "I baguette for a living and eat code for breakfast."
|
||||
},
|
||||
{
|
||||
"name": "Ryan",
|
||||
"id": "186679073764802560",
|
||||
"dept": "Associate",
|
||||
"emailAddress": "wbdvryan@staff.libraryofcode.org",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/plainRyan",
|
||||
"bio": "Experiment, learn, share, repeat.",
|
||||
"acknowledgements": ["Contributor"]
|
||||
},
|
||||
{
|
||||
"name": "Zloth",
|
||||
"id": "382368885267234816",
|
||||
"dept": "Associate",
|
||||
"emailAddress": "zloth@staff.libraryofcode.org",
|
||||
"github": "https://github.com/gavintjhxx",
|
||||
"bio": "Wake up. Eat. Code. Sleep. Loop()"
|
||||
},
|
||||
{
|
||||
"name": "PlayerVMachine",
|
||||
"id": "273999507174195203",
|
||||
"dept": "Instructor & Associate",
|
||||
"emailAddress": "nicolas@staff.libraryofcode.org",
|
||||
"bio": "I write C++ to pay off my student loans"
|
||||
},
|
||||
{
|
||||
"name": "Null",
|
||||
"id": "323673862971588609",
|
||||
"gitlab": "https://gitlab.libraryofcode.org/null",
|
||||
"acknowledgements": ["Contributor"]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"moderation": {
|
||||
"modlogs": "446080867065135115",
|
||||
"automod": ""
|
||||
}
|
||||
}
|
||||
{
|
||||
"moderation": {
|
||||
"modlogs": "446080867065135115",
|
||||
"automod": ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
{
|
||||
"whois": {
|
||||
"titleAndDepartment": "<:loc:607695848612167700>",
|
||||
"email": "<:email:699786452267040878>",
|
||||
"gitlab": "<:gitlab:699788655748841492>",
|
||||
"github": "<:github:699786469404835939>",
|
||||
"bio": "<:bio:699786408193294416>"
|
||||
},
|
||||
"statusMessages": {
|
||||
"success": "<:modSuccess:578750988907970567>",
|
||||
"loading": "<a:modloading:588607353935364106>",
|
||||
"error": "<:modError:578750737920688128>"
|
||||
}
|
||||
}
|
||||
{
|
||||
"whois": {
|
||||
"titleAndDepartment": "<:loc:607695848612167700>",
|
||||
"email": "<:email:699786452267040878>",
|
||||
"gitlab": "<:gitlab:699788655748841492>",
|
||||
"github": "<:github:699786469404835939>",
|
||||
"bio": "<:bio:699786408193294416>"
|
||||
},
|
||||
"statusMessages": {
|
||||
"success": "<:modSuccess:578750988907970567>",
|
||||
"loading": "<a:modloading:588607353935364106>",
|
||||
"error": "<:modError:578750737920688128>"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
/* eslint-disable no-useless-return */
|
||||
import { Message, TextChannel, NewsChannel } from 'eris';
|
||||
import { Client, Event } from '../class';
|
||||
|
||||
export default class CommandHandler extends Event {
|
||||
public client: Client;
|
||||
|
||||
constructor(client: Client) {
|
||||
super(client);
|
||||
this.event = 'messageCreate';
|
||||
}
|
||||
|
||||
public async run(message: Message) {
|
||||
try {
|
||||
if (message.author.bot) return;
|
||||
if (message.content.indexOf(this.client.config.prefix) !== 0) return;
|
||||
const noPrefix: string[] = message.content.slice(this.client.config.prefix.length).trim().split(/ +/g);
|
||||
const resolved = await this.client.util.resolveCommand(noPrefix);
|
||||
if (!resolved) return;
|
||||
if (resolved.cmd.guildOnly && !(message.channel instanceof TextChannel || message.channel instanceof NewsChannel)) return;
|
||||
if (!resolved.cmd.enabled) { message.channel.createMessage(`***${this.client.util.emojis.ERROR} This command has been disabled***`); return; }
|
||||
if (!resolved.cmd.checkPermissions(message.member)) return;
|
||||
if ((message.channel.type === 0) && !message.channel.guild.members.get(message.author.id)) {
|
||||
message.channel.guild.members.add(await message.channel.guild.getRESTMember(message.author.id));
|
||||
}
|
||||
this.client.util.signale.log(`User '${message.author.username}#${message.author.discriminator}' ran command '${resolved.cmd.name}' in '${message.channel.id}'.`);
|
||||
await resolved.cmd.run(message, resolved.args);
|
||||
} catch (err) {
|
||||
this.client.util.handleError(err, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* eslint-disable no-useless-return */
|
||||
import { Message, TextChannel, NewsChannel } from 'eris';
|
||||
import { Client, Event } from '../class';
|
||||
|
||||
export default class CommandHandler extends Event {
|
||||
public client: Client;
|
||||
|
||||
constructor(client: Client) {
|
||||
super(client);
|
||||
this.event = 'messageCreate';
|
||||
}
|
||||
|
||||
public async run(message: Message) {
|
||||
try {
|
||||
if (message.author.bot) return;
|
||||
if (message.content.indexOf(this.client.config.prefix) !== 0) return;
|
||||
const noPrefix: string[] = message.content.slice(this.client.config.prefix.length).trim().split(/ +/g);
|
||||
const resolved = await this.client.util.resolveCommand(noPrefix);
|
||||
if (!resolved) return;
|
||||
if (resolved.cmd.guildOnly && !(message.channel instanceof TextChannel || message.channel instanceof NewsChannel)) return;
|
||||
if (!resolved.cmd.enabled) { message.channel.createMessage(`***${this.client.util.emojis.ERROR} This command has been disabled***`); return; }
|
||||
if (!resolved.cmd.checkPermissions(message.member)) return;
|
||||
if ((message.channel.type === 0) && !message.channel.guild.members.get(message.author.id)) {
|
||||
message.channel.guild.members.add(await message.channel.guild.getRESTMember(message.author.id));
|
||||
}
|
||||
this.client.util.signale.log(`User '${message.author.username}#${message.author.discriminator}' ran command '${resolved.cmd.name}' in '${message.channel.id}'.`);
|
||||
await resolved.cmd.run(message, resolved.args);
|
||||
} catch (err) {
|
||||
this.client.util.handleError(err, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
export { default as CommandHandler } from './CommandHandler';
|
||||
export { default as ready } from './ready';
|
||||
export { default as CommandHandler } from './CommandHandler';
|
||||
export { default as ready } from './ready';
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import { Client, Event } from '../class';
|
||||
|
||||
export default class Ready extends Event {
|
||||
public client: Client;
|
||||
|
||||
constructor(client: Client) {
|
||||
super(client);
|
||||
this.event = 'ready';
|
||||
}
|
||||
|
||||
public async run() {
|
||||
this.client.util.signale.start(`${this.client.user.username} is now ready!\nServers: ${this.client.guilds.size}\nUsers: ${this.client.users.size}\n\nhttps://gitlab.libraryofcode.org/engineering/communityrelations`);
|
||||
this.client.on('error', (err) => {
|
||||
this.client.util.handleError(err);
|
||||
});
|
||||
process.on('uncaughtException', (err) => {
|
||||
this.client.util.handleError(err);
|
||||
process.exit(1);
|
||||
});
|
||||
process.on('unhandledRejection', (err: Error) => {
|
||||
this.client.util.handleError(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
import { Client, Event } from '../class';
|
||||
|
||||
export default class Ready extends Event {
|
||||
public client: Client;
|
||||
|
||||
constructor(client: Client) {
|
||||
super(client);
|
||||
this.event = 'ready';
|
||||
}
|
||||
|
||||
public async run() {
|
||||
this.client.util.signale.start(`${this.client.user.username} is now ready!\nServers: ${this.client.guilds.size}\nUsers: ${this.client.users.size}\n\nhttps://gitlab.libraryofcode.org/engineering/communityrelations`);
|
||||
this.client.on('error', (err) => {
|
||||
this.client.util.handleError(err);
|
||||
});
|
||||
process.on('uncaughtException', (err) => {
|
||||
this.client.util.handleError(err);
|
||||
process.exit(1);
|
||||
});
|
||||
process.on('unhandledRejection', (err: Error) => {
|
||||
this.client.util.handleError(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import { Client } from '../class';
|
||||
|
||||
let interval: NodeJS.Timeout;
|
||||
|
||||
export default function checkLock(client: Client): NodeJS.Timeout {
|
||||
interval = setInterval(async () => {
|
||||
try {
|
||||
const moderations = await client.db.Moderation.find();
|
||||
moderations.forEach(async (moderation) => {
|
||||
if (!moderation.expiration) return;
|
||||
if (moderation.expiration.processed) return;
|
||||
if (new Date() > moderation.expiration.date) {
|
||||
await moderation.updateOne({ 'expiration.processed': true });
|
||||
const moderator = client.guilds.get(client.config.guildID).members.get(moderation.moderatorID);
|
||||
await client.util.moderation.unban(moderation.userID, moderator);
|
||||
client.util.signale.complete(`Released member ${moderation.userID} | Queue date at ${moderation.expiration.date.toLocaleString('en-us')}`);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
await client.util.handleError(error);
|
||||
}
|
||||
}, 10000);
|
||||
return interval;
|
||||
}
|
||||
import { Client } from '../class';
|
||||
|
||||
let interval: NodeJS.Timeout;
|
||||
|
||||
export default function checkLock(client: Client): NodeJS.Timeout {
|
||||
interval = setInterval(async () => {
|
||||
try {
|
||||
const moderations = await client.db.Moderation.find();
|
||||
moderations.forEach(async (moderation) => {
|
||||
if (!moderation.expiration) return;
|
||||
if (moderation.expiration.processed) return;
|
||||
if (new Date() > moderation.expiration.date) {
|
||||
await moderation.updateOne({ 'expiration.processed': true });
|
||||
const moderator = client.guilds.get(client.config.guildID).members.get(moderation.moderatorID);
|
||||
await client.util.moderation.unban(moderation.userID, moderator);
|
||||
client.util.signale.complete(`Released member ${moderation.userID} | Queue date at ${moderation.expiration.date.toLocaleString('en-us')}`);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
await client.util.handleError(error);
|
||||
}
|
||||
}, 10000);
|
||||
return interval;
|
||||
}
|
||||
|
|
|
@ -1,358 +1,358 @@
|
|||
/* eslint-disable no-continue */
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import { Member, TextableChannel } from 'eris';
|
||||
import { Client } from '../class';
|
||||
|
||||
let interval: NodeJS.Timeout;
|
||||
|
||||
async function setupDepartmentCodes(client: Client): Promise<void> {
|
||||
const directorPagers = await client.db.PagerNumber.findOne({ num: '00' }).lean().exec();
|
||||
const supervisorPagers = await client.db.PagerNumber.findOne({ num: '01' }).lean().exec();
|
||||
const technicianPagers = await client.db.PagerNumber.findOne({ num: '10' }).lean().exec();
|
||||
const moderatorPagers = await client.db.PagerNumber.findOne({ num: '20' }).lean().exec();
|
||||
const coreTeamPagers = await client.db.PagerNumber.findOne({ num: '21' }).lean().exec();
|
||||
const associatePagers = await client.db.PagerNumber.findOne({ num: '22' }).lean().exec();
|
||||
|
||||
if (!directorPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '00',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
if (!supervisorPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '01',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
if (!technicianPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '10',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
setup.save();
|
||||
}
|
||||
if (!moderatorPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '20',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
if (!coreTeamPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '21',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
if (!associatePagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '22',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
}
|
||||
|
||||
function logNewPager(client: Client, num: string, member: Member): void {
|
||||
const channel = <TextableChannel> client.guilds.get(client.config.guildID).channels.get('722636436716781619');
|
||||
channel.createMessage(`__**'${member.user.username}#${member.user.discriminator}' assigned to pager number '${num}'.**__`);
|
||||
}
|
||||
|
||||
export default function departmentPager(client: Client): NodeJS.Timeout {
|
||||
setupDepartmentCodes(client);
|
||||
interval = setInterval(async () => {
|
||||
const acknowledgements = require(`${__dirname}/../configs/acknowledgements.json`);
|
||||
function resolveStaffInformation(id: string) {
|
||||
return acknowledgements.find((m) => m.id === id);
|
||||
}
|
||||
// await client.guilds.get(client.config.guildID).fetchAllMembers();
|
||||
const { members } = client.guilds.get(client.config.guildID);
|
||||
|
||||
for (const member of members.values()) {
|
||||
const pager = await client.db.PagerNumber.findOne({ individualAssignID: member.id }).lean().exec();
|
||||
if (!pager) continue;
|
||||
if (pager.num.startsWith('00') && !member.roles.includes('662163685439045632')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('01') && !member.roles.includes('701454855952138300')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('10') && !member.roles.includes('701454780828221450')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('20') && !member.roles.includes('455972169449734144')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('21') && !member.roles.includes('453689940140883988')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('22') && !member.roles.includes('701481967149121627')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
}
|
||||
}
|
||||
|
||||
// const takenPagers = new Set<string>();
|
||||
|
||||
for (const member of members.values()) {
|
||||
let pager = await client.db.PagerNumber.findOne({ individualAssignID: member.id }).lean().exec();
|
||||
// Directors
|
||||
if (!pager && member.roles.includes('662163685439045632')) {
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `00${String(Math.floor(Math.random() * 9) + 1)}`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
pager = await newNumber.save();
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('701454855952138300')) {
|
||||
// Supervisors
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `01${String(Math.floor(Math.random() * 9) + 1)}`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('701454780828221450')) {
|
||||
// Technicians
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `10${String(Math.floor(Math.random() * 99) + 1)}`;
|
||||
if (randomPagerNumber.length === 3) randomPagerNumber = `${randomPagerNumber}0`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('455972169449734144')) {
|
||||
// Moderators
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `20${String(Math.floor(Math.random() * 99) + 1)}`;
|
||||
if (randomPagerNumber.length === 3) randomPagerNumber = `${randomPagerNumber}0`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('453689940140883988')) {
|
||||
// Core Team
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `21${String(Math.floor(Math.random() * 999) + 1)}`;
|
||||
if (randomPagerNumber.length === 4) randomPagerNumber = `${randomPagerNumber}0`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('701481967149121627')) {
|
||||
// Associates
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `22${String(Math.floor(Math.random() * 999) + 1)}`;
|
||||
if (randomPagerNumber.length === 4) randomPagerNumber = `${randomPagerNumber}0`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Associates
|
||||
const associatePagers = await client.db.PagerNumber.findOne({ num: '22' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('701481967149121627') && !associatePagers.discordIDs.includes(member.id)) {
|
||||
await associatePagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await associatePagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('701481967149121627') && associatePagers.discordIDs.includes(member.id)) {
|
||||
await associatePagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await associatePagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Core Team
|
||||
const coreTeamPagers = await client.db.PagerNumber.findOne({ num: '21' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('453689940140883988') && !coreTeamPagers.discordIDs.includes(member.id)) {
|
||||
await coreTeamPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await coreTeamPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('453689940140883988') && coreTeamPagers.discordIDs.includes(member.id)) {
|
||||
await coreTeamPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await coreTeamPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Moderator
|
||||
const moderatorPagers = await client.db.PagerNumber.findOne({ num: '20' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('455972169449734144') && !moderatorPagers.discordIDs.includes(member.id)) {
|
||||
await moderatorPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await moderatorPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('455972169449734144') && moderatorPagers.discordIDs.includes(member.id)) {
|
||||
await moderatorPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await moderatorPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Technician
|
||||
const technicianPagers = await client.db.PagerNumber.findOne({ num: '10' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('701454780828221450') && !technicianPagers.discordIDs.includes(member.id)) {
|
||||
await technicianPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await technicianPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('701454780828221450') && technicianPagers.discordIDs.includes(member.id)) {
|
||||
await technicianPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await technicianPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Supervisor
|
||||
const supervisorPagers = await client.db.PagerNumber.findOne({ num: '01' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('701454855952138300') && !supervisorPagers.discordIDs.includes(member.id)) {
|
||||
await supervisorPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await supervisorPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('701454855952138300') && supervisorPagers.discordIDs.includes(member.id)) {
|
||||
await supervisorPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await supervisorPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Board of Directors
|
||||
const directorPagers = await client.db.PagerNumber.findOne({ num: '00' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('662163685439045632') && !directorPagers.discordIDs.includes(member.id)) {
|
||||
await directorPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await directorPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('662163685439045632') && directorPagers.discordIDs.includes(member.id)) {
|
||||
await directorPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await directorPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
}, 300000);
|
||||
return interval;
|
||||
}
|
||||
/* eslint-disable no-continue */
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import { Member, TextableChannel } from 'eris';
|
||||
import { Client } from '../class';
|
||||
|
||||
let interval: NodeJS.Timeout;
|
||||
|
||||
async function setupDepartmentCodes(client: Client): Promise<void> {
|
||||
const directorPagers = await client.db.PagerNumber.findOne({ num: '00' }).lean().exec();
|
||||
const supervisorPagers = await client.db.PagerNumber.findOne({ num: '01' }).lean().exec();
|
||||
const technicianPagers = await client.db.PagerNumber.findOne({ num: '10' }).lean().exec();
|
||||
const moderatorPagers = await client.db.PagerNumber.findOne({ num: '20' }).lean().exec();
|
||||
const coreTeamPagers = await client.db.PagerNumber.findOne({ num: '21' }).lean().exec();
|
||||
const associatePagers = await client.db.PagerNumber.findOne({ num: '22' }).lean().exec();
|
||||
|
||||
if (!directorPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '00',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
if (!supervisorPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '01',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
if (!technicianPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '10',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
setup.save();
|
||||
}
|
||||
if (!moderatorPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '20',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
if (!coreTeamPagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '21',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
if (!associatePagers) {
|
||||
const setup = new client.db.PagerNumber({
|
||||
num: '22',
|
||||
individualAssignID: '',
|
||||
emailAddresses: [],
|
||||
discordIDs: [],
|
||||
});
|
||||
await setup.save();
|
||||
}
|
||||
}
|
||||
|
||||
function logNewPager(client: Client, num: string, member: Member): void {
|
||||
const channel = <TextableChannel> client.guilds.get(client.config.guildID).channels.get('722636436716781619');
|
||||
channel.createMessage(`__**'${member.user.username}#${member.user.discriminator}' assigned to pager number '${num}'.**__`);
|
||||
}
|
||||
|
||||
export default function departmentPager(client: Client): NodeJS.Timeout {
|
||||
setupDepartmentCodes(client);
|
||||
interval = setInterval(async () => {
|
||||
const acknowledgements = require(`${__dirname}/../configs/acknowledgements.json`);
|
||||
function resolveStaffInformation(id: string) {
|
||||
return acknowledgements.find((m) => m.id === id);
|
||||
}
|
||||
// await client.guilds.get(client.config.guildID).fetchAllMembers();
|
||||
const { members } = client.guilds.get(client.config.guildID);
|
||||
|
||||
for (const member of members.values()) {
|
||||
const pager = await client.db.PagerNumber.findOne({ individualAssignID: member.id }).lean().exec();
|
||||
if (!pager) continue;
|
||||
if (pager.num.startsWith('00') && !member.roles.includes('662163685439045632')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('01') && !member.roles.includes('701454855952138300')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('10') && !member.roles.includes('701454780828221450')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('20') && !member.roles.includes('455972169449734144')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('21') && !member.roles.includes('453689940140883988')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
} else if (pager.num.startsWith('22') && !member.roles.includes('701481967149121627')) {
|
||||
client.db.PagerNumber.deleteOne({ num: pager.num });
|
||||
client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
|
||||
}
|
||||
}
|
||||
|
||||
// const takenPagers = new Set<string>();
|
||||
|
||||
for (const member of members.values()) {
|
||||
let pager = await client.db.PagerNumber.findOne({ individualAssignID: member.id }).lean().exec();
|
||||
// Directors
|
||||
if (!pager && member.roles.includes('662163685439045632')) {
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `00${String(Math.floor(Math.random() * 9) + 1)}`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
pager = await newNumber.save();
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('701454855952138300')) {
|
||||
// Supervisors
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `01${String(Math.floor(Math.random() * 9) + 1)}`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('701454780828221450')) {
|
||||
// Technicians
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `10${String(Math.floor(Math.random() * 99) + 1)}`;
|
||||
if (randomPagerNumber.length === 3) randomPagerNumber = `${randomPagerNumber}0`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('455972169449734144')) {
|
||||
// Moderators
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `20${String(Math.floor(Math.random() * 99) + 1)}`;
|
||||
if (randomPagerNumber.length === 3) randomPagerNumber = `${randomPagerNumber}0`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('453689940140883988')) {
|
||||
// Core Team
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `21${String(Math.floor(Math.random() * 999) + 1)}`;
|
||||
if (randomPagerNumber.length === 4) randomPagerNumber = `${randomPagerNumber}0`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
} else if (!pager && member.roles.includes('701481967149121627')) {
|
||||
// Associates
|
||||
let randomPagerNumber: string;
|
||||
let status = true;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (status) {
|
||||
randomPagerNumber = `22${String(Math.floor(Math.random() * 999) + 1)}`;
|
||||
if (randomPagerNumber.length === 4) randomPagerNumber = `${randomPagerNumber}0`;
|
||||
const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
|
||||
if (check) status = false;
|
||||
if (check?.num !== randomPagerNumber) status = false;
|
||||
}
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (!acknowledgement || !acknowledgement.emailAddress) return;
|
||||
const newNumber = new client.db.PagerNumber({
|
||||
num: randomPagerNumber,
|
||||
individualAssignID: member.id,
|
||||
emailAddresses: [acknowledgement.emailAddress],
|
||||
discordIDs: [member.id],
|
||||
});
|
||||
if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) return;
|
||||
logNewPager(client, randomPagerNumber, member);
|
||||
pager = await newNumber.save();
|
||||
client.getDMChannel(member.id).then((chan) => {
|
||||
chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Associates
|
||||
const associatePagers = await client.db.PagerNumber.findOne({ num: '22' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('701481967149121627') && !associatePagers.discordIDs.includes(member.id)) {
|
||||
await associatePagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await associatePagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('701481967149121627') && associatePagers.discordIDs.includes(member.id)) {
|
||||
await associatePagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await associatePagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Core Team
|
||||
const coreTeamPagers = await client.db.PagerNumber.findOne({ num: '21' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('453689940140883988') && !coreTeamPagers.discordIDs.includes(member.id)) {
|
||||
await coreTeamPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await coreTeamPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('453689940140883988') && coreTeamPagers.discordIDs.includes(member.id)) {
|
||||
await coreTeamPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await coreTeamPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Moderator
|
||||
const moderatorPagers = await client.db.PagerNumber.findOne({ num: '20' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('455972169449734144') && !moderatorPagers.discordIDs.includes(member.id)) {
|
||||
await moderatorPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await moderatorPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('455972169449734144') && moderatorPagers.discordIDs.includes(member.id)) {
|
||||
await moderatorPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await moderatorPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Technician
|
||||
const technicianPagers = await client.db.PagerNumber.findOne({ num: '10' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('701454780828221450') && !technicianPagers.discordIDs.includes(member.id)) {
|
||||
await technicianPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await technicianPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('701454780828221450') && technicianPagers.discordIDs.includes(member.id)) {
|
||||
await technicianPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await technicianPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Supervisor
|
||||
const supervisorPagers = await client.db.PagerNumber.findOne({ num: '01' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('701454855952138300') && !supervisorPagers.discordIDs.includes(member.id)) {
|
||||
await supervisorPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await supervisorPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('701454855952138300') && supervisorPagers.discordIDs.includes(member.id)) {
|
||||
await supervisorPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await supervisorPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
// Board of Directors
|
||||
const directorPagers = await client.db.PagerNumber.findOne({ num: '00' });
|
||||
for (const member of members.values()) {
|
||||
if (member.roles.includes('662163685439045632') && !directorPagers.discordIDs.includes(member.id)) {
|
||||
await directorPagers.updateOne({ $addToSet: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await directorPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
if (!member.roles.includes('662163685439045632') && directorPagers.discordIDs.includes(member.id)) {
|
||||
await directorPagers.updateOne({ $pull: { discordIDs: member.id } });
|
||||
const acknowledgement = resolveStaffInformation(member.id);
|
||||
if (acknowledgement?.emailAddress) await directorPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
|
||||
}
|
||||
}
|
||||
}, 300000);
|
||||
return interval;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { Client } from '../class';
|
||||
|
||||
let interval: NodeJS.Timeout;
|
||||
|
||||
export default async function fetchMembers(client: Client): Promise<NodeJS.Timeout> {
|
||||
await client.guilds.get(client.config.guildID)?.fetchAllMembers();
|
||||
interval = setInterval(async () => {
|
||||
// await client.guilds.get(client.config.guildID).fetchAllMembers();
|
||||
}, 1800000);
|
||||
return interval;
|
||||
}
|
||||
import { Client } from '../class';
|
||||
|
||||
let interval: NodeJS.Timeout;
|
||||
|
||||
export default async function fetchMembers(client: Client): Promise<NodeJS.Timeout> {
|
||||
await client.guilds.get(client.config.guildID)?.fetchAllMembers();
|
||||
interval = setInterval(async () => {
|
||||
// await client.guilds.get(client.config.guildID).fetchAllMembers();
|
||||
}, 1800000);
|
||||
return interval;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
*/
|
||||
import { parse } from 'yaml';
|
||||
import { promises as fs } from 'fs';
|
||||
import { TextChannel } from 'eris';
|
||||
import { Client } from './class';
|
||||
import * as eventFiles from './events';
|
||||
import * as commandFiles from './commands';
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import { Document, Schema, model } from 'mongoose';
|
||||
|
||||
export interface MemberInterface extends Document {
|
||||
userID: string
|
||||
additional: {
|
||||
langs: ['js', 'py', 'rb', 'ts', 'rs', 'go', 'cfam', 'csharp', 'swift', 'java', 'kt', 'asm'],
|
||||
operatingSystems: ['arch', 'deb', 'cent', 'fedora', 'manjaro', 'mdarwin', 'redhat', 'ubuntu', 'win'],
|
||||
},
|
||||
}
|
||||
|
||||
const Member: Schema = new Schema({
|
||||
userID: String,
|
||||
additional: {
|
||||
langs: Array,
|
||||
operatingSystems: Array,
|
||||
},
|
||||
});
|
||||
|
||||
export default model<MemberInterface>('Member', Member);
|
||||
import { Document, Schema, model } from 'mongoose';
|
||||
|
||||
export interface MemberInterface extends Document {
|
||||
userID: string
|
||||
additional: {
|
||||
langs: ['js', 'py', 'rb', 'ts', 'rs', 'go', 'cfam', 'csharp', 'swift', 'java', 'kt', 'asm'],
|
||||
operatingSystems: ['arch', 'deb', 'cent', 'fedora', 'manjaro', 'mdarwin', 'redhat', 'ubuntu', 'win'],
|
||||
},
|
||||
}
|
||||
|
||||
const Member: Schema = new Schema({
|
||||
userID: String,
|
||||
additional: {
|
||||
langs: Array,
|
||||
operatingSystems: Array,
|
||||
},
|
||||
});
|
||||
|
||||
export default model<MemberInterface>('Member', Member);
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
import { Document, Schema, model } from 'mongoose';
|
||||
|
||||
export interface ModerationInterface extends Document {
|
||||
userID: string,
|
||||
logID: string,
|
||||
moderatorID: string,
|
||||
reason: string,
|
||||
/**
|
||||
* @field 0 - Warn
|
||||
* @field 1 - Unmute
|
||||
* @field 2 - Mute
|
||||
* @field 3 - Kick
|
||||
* @field 4 - Unban
|
||||
* @field 5 - Ban
|
||||
*/
|
||||
type: 0 | 1 | 2 | 3 | 4 | 5
|
||||
date: Date,
|
||||
expiration: {
|
||||
date: Date,
|
||||
processed: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const Moderation: Schema = new Schema({
|
||||
userID: String,
|
||||
logID: String,
|
||||
moderatorID: String,
|
||||
reason: String,
|
||||
type: Number,
|
||||
date: Date,
|
||||
expiration: {
|
||||
date: Date,
|
||||
processed: Boolean,
|
||||
},
|
||||
});
|
||||
|
||||
export default model<ModerationInterface>('Moderation', Moderation);
|
||||
import { Document, Schema, model } from 'mongoose';
|
||||
|
||||
export interface ModerationInterface extends Document {
|
||||
userID: string,
|
||||
logID: string,
|
||||
moderatorID: string,
|
||||
reason: string,
|
||||
/**
|
||||
* @field 0 - Warn
|
||||
* @field 1 - Unmute
|
||||
* @field 2 - Mute
|
||||
* @field 3 - Kick
|
||||
* @field 4 - Unban
|
||||
* @field 5 - Ban
|
||||
*/
|
||||
type: 0 | 1 | 2 | 3 | 4 | 5
|
||||
date: Date,
|
||||
expiration: {
|
||||
date: Date,
|
||||
processed: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const Moderation: Schema = new Schema({
|
||||
userID: String,
|
||||
logID: String,
|
||||
moderatorID: String,
|
||||
reason: String,
|
||||
type: Number,
|
||||
date: Date,
|
||||
expiration: {
|
||||
date: Date,
|
||||
processed: Boolean,
|
||||
},
|
||||
});
|
||||
|
||||
export default model<ModerationInterface>('Moderation', Moderation);
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
import { Document, Schema, model } from 'mongoose';
|
||||
|
||||
export interface PagerNumberRaw {
|
||||
num: string,
|
||||
// This field will be "" if the pager number doesn't belong to an individual user
|
||||
individualAssignID: string,
|
||||
emailAddresses: string[],
|
||||
discordIDs: string[],
|
||||
}
|
||||
|
||||
export interface PagerNumberInterface extends Document {
|
||||
num: string,
|
||||
// This field will be "" if the pager number doesn't belong to an individual user
|
||||
individualAssignID: string,
|
||||
emailAddresses: string[],
|
||||
discordIDs: string[],
|
||||
}
|
||||
|
||||
const PagerNumber: Schema = new Schema({
|
||||
num: String,
|
||||
individualAssignID: String,
|
||||
emailAddresses: Array,
|
||||
discordIDs: Array,
|
||||
});
|
||||
|
||||
export default model<PagerNumberInterface>('PagerNumber', PagerNumber);
|
||||
import { Document, Schema, model } from 'mongoose';
|
||||
|
||||
export interface PagerNumberRaw {
|
||||
num: string,
|
||||
// This field will be "" if the pager number doesn't belong to an individual user
|
||||
individualAssignID: string,
|
||||
emailAddresses: string[],
|
||||
discordIDs: string[],
|
||||
}
|
||||
|
||||
export interface PagerNumberInterface extends Document {
|
||||
num: string,
|
||||
// This field will be "" if the pager number doesn't belong to an individual user
|
||||
individualAssignID: string,
|
||||
emailAddresses: string[],
|
||||
discordIDs: string[],
|
||||
}
|
||||
|
||||
const PagerNumber: Schema = new Schema({
|
||||
num: String,
|
||||
individualAssignID: String,
|
||||
emailAddresses: Array,
|
||||
discordIDs: Array,
|
||||
});
|
||||
|
||||
export default model<PagerNumberInterface>('PagerNumber', PagerNumber);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { Document, Schema, model } from 'mongoose';
|
||||
|
||||
export interface RankInterface extends Document {
|
||||
name: string,
|
||||
roleID: string,
|
||||
permissions: string[],
|
||||
description: string,
|
||||
}
|
||||
|
||||
const Rank: Schema = new Schema({
|
||||
name: String,
|
||||
roleID: String,
|
||||
permissions: Array,
|
||||
description: String,
|
||||
});
|
||||
|
||||
export default model<RankInterface>('Rank', Rank);
|
|
@ -1,21 +1,21 @@
|
|||
import { Document, Schema, model } from 'mongoose';
|
||||
|
||||
export interface RedirectInterface extends Document {
|
||||
key: string,
|
||||
to: string,
|
||||
visitedCount: number,
|
||||
}
|
||||
|
||||
export interface RedirectRaw {
|
||||
key: string,
|
||||
to: string,
|
||||
visitedCount: number,
|
||||
}
|
||||
|
||||
const Redirect: Schema = new Schema({
|
||||
key: String,
|
||||
to: String,
|
||||
visitedCount: Number,
|
||||
});
|
||||
|
||||
export default model<RedirectInterface>('Redirect', Redirect);
|
||||
import { Document, Schema, model } from 'mongoose';
|
||||
|
||||
export interface RedirectInterface extends Document {
|
||||
key: string,
|
||||
to: string,
|
||||
visitedCount: number,
|
||||
}
|
||||
|
||||
export interface RedirectRaw {
|
||||
key: string,
|
||||
to: string,
|
||||
visitedCount: number,
|
||||
}
|
||||
|
||||
const Redirect: Schema = new Schema({
|
||||
key: String,
|
||||
to: String,
|
||||
visitedCount: Number,
|
||||
});
|
||||
|
||||
export default model<RedirectInterface>('Redirect', Redirect);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export { default as Member, MemberInterface } from './Member';
|
||||
export { default as Moderation, ModerationInterface } from './Moderation';
|
||||
export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber';
|
||||
export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect';
|
||||
export { default as Member, MemberInterface } from './Member';
|
||||
export { default as Moderation, ModerationInterface } from './Moderation';
|
||||
export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber';
|
||||
export { default as Rank, RankInterface } from './Rank';
|
||||
export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect';
|
||||
|
|
Loading…
Reference in New Issue