fixed conflict
commit
d4ef0db1cf
|
@ -39,6 +39,7 @@
|
||||||
"import/prefer-default-export": "off",
|
"import/prefer-default-export": "off",
|
||||||
"no-useless-constructor": "off",
|
"no-useless-constructor": "off",
|
||||||
"@typescript-eslint/no-useless-constructor": 2,
|
"@typescript-eslint/no-useless-constructor": 2,
|
||||||
"import/extensions": "off"
|
"import/extensions": "off",
|
||||||
|
"no-param-reassign": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
# Package Management & Libraries
|
# Package Management & Libraries
|
||||||
node_modules
|
node_modules
|
||||||
yarn.lock
|
package-lock.json
|
||||||
package-json.lock
|
|
||||||
|
|
||||||
# Configuration Files
|
# Configuration Files
|
||||||
config.yaml
|
config.yaml
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
stages:
|
||||||
|
- lint
|
||||||
|
- build
|
||||||
|
|
||||||
|
lint:
|
||||||
|
stage: lint
|
||||||
|
script: |
|
||||||
|
yarn install
|
||||||
|
yarn lint
|
||||||
|
|
||||||
|
tsc:
|
||||||
|
stage: build
|
||||||
|
script: |
|
||||||
|
yarn install
|
||||||
|
tsc -p tsconfig.json -noEmit
|
|
@ -0,0 +1,13 @@
|
||||||
|
# BUG REPORT
|
||||||
|
|
||||||
|
**Brief Description:**
|
||||||
|
|
||||||
|
**Priority:** (1-5, 5 being the most urgent)
|
||||||
|
|
||||||
|
**Steps to Reproduce:** (separated with numbers)
|
||||||
|
|
||||||
|
**Expected Result:**
|
||||||
|
|
||||||
|
**Actual Result:**
|
||||||
|
|
||||||
|
**Notes:** (delete if none)
|
|
@ -0,0 +1,5 @@
|
||||||
|
## FEATURE REQUEST / SUGGESTION
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
|
||||||
|
**Description:**
|
|
@ -9,3 +9,8 @@ We accept contributions from the community, however there's a few steps you need
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
If you're interested in tackling an issue, please comment on that particular issue that you're handling it so Maintainers can label it appropriately.
|
If you're interested in tackling an issue, please comment on that particular issue that you're handling it so Maintainers can label it appropriately.
|
||||||
|
|
||||||
|
## Other Information
|
||||||
|
* Make sure your contributions match the current style of the code, run `yarn run lint` to find issues with the style. Requests will be denied if they do not comply with styling.
|
||||||
|
* Submit your merge requests to the **dev** branch only.
|
||||||
|
* If you can use TypeScript functionality, do it. For example, don't declare something as `any` if it can be typed.
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -4,7 +4,7 @@ clean:
|
||||||
@-rm -rf build
|
@-rm -rf build
|
||||||
|
|
||||||
build:
|
build:
|
||||||
tsc -p ./tsconfig.json
|
-tsc -p ./tsconfig.json
|
||||||
|
|
||||||
run:
|
run:
|
||||||
cd build && node main
|
cd build && node main
|
||||||
|
|
31
package.json
31
package.json
|
@ -3,30 +3,37 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "The official system for handling Community Relations in the LOC Discord server.",
|
"description": "The official system for handling Community Relations in the LOC Discord server.",
|
||||||
"main": "build/main.js",
|
"main": "build/main.js",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint -c ./.eslintrc.json src --ext ts"
|
||||||
|
},
|
||||||
"repository": "https://gitlab.libraryofcode.org/engineering/communityrelations.git",
|
"repository": "https://gitlab.libraryofcode.org/engineering/communityrelations.git",
|
||||||
"author": "Matthew R <matthew@staff.libraryofcode.org>",
|
"author": "Matthew R <matthew@staff.libraryofcode.org>",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/mongoose": "^5.7.10",
|
"@types/express": "^4.17.6",
|
||||||
"@types/node": "^13.11.0",
|
"@types/helmet": "^0.0.47",
|
||||||
|
"@types/mongoose": "^5.7.19",
|
||||||
|
"@types/node": "^14.0.1",
|
||||||
"@types/signale": "^1.4.1",
|
"@types/signale": "^1.4.1",
|
||||||
"@types/uuid": "^7.0.2",
|
"@types/uuid": "^7.0.3",
|
||||||
"@types/yaml": "^1.2.0",
|
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^2.27.0",
|
"@typescript-eslint/parser": "^2.33.0",
|
||||||
"@typescript-eslint/parser": "^2.27.0",
|
"eslint": "^7.0.0",
|
||||||
"eslint": "^6.8.0",
|
|
||||||
"eslint-config-airbnb-base": "^14.1.0",
|
"eslint-config-airbnb-base": "^14.1.0",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.20.2",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.9.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"eris": "bsian03/eris#bsian",
|
"eris": "bsian03/eris#bsian",
|
||||||
"moment": "^2.24.0",
|
"eris-pagination": "bsian03/eris-pagination",
|
||||||
"mongoose": "^5.9.9",
|
"express": "^4.17.1",
|
||||||
|
"helmet": "^3.22.0",
|
||||||
|
"moment": "^2.25.3",
|
||||||
|
"mongoose": "^5.9.13",
|
||||||
"signale": "^1.4.0",
|
"signale": "^1.4.0",
|
||||||
"uuid": "^7.0.3",
|
"uuid": "^8.0.0",
|
||||||
"yaml": "^1.8.3"
|
"yaml": "^1.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import locsh from './loc.sh/main';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
'loc.sh': locsh,
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { Server, ServerManagement } from '../../class';
|
||||||
|
|
||||||
|
export default (management: ServerManagement) => {
|
||||||
|
const server = new Server(management, 3890, `${__dirname}/routes`);
|
||||||
|
return server;
|
||||||
|
};
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as root } from './root';
|
|
@ -0,0 +1,24 @@
|
||||||
|
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('/: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 });
|
||||||
|
return res.redirect(link.to);
|
||||||
|
} 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,26 +1,32 @@
|
||||||
import eris from 'eris';
|
import eris from 'eris';
|
||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { Collection, Command, Util } from '.';
|
import { Collection, Command, Util, ServerManagement, Event } from '.';
|
||||||
import { Moderation, ModerationInterface } from '../models';
|
import { Member, MemberInterface, Moderation, ModerationInterface, Redirect, RedirectInterface } from '../models';
|
||||||
|
import * as eventFiles from '../events';
|
||||||
|
import * as commandFiles from '../commands';
|
||||||
|
|
||||||
export default class Client extends eris.Client {
|
export default class Client extends eris.Client {
|
||||||
public config: { token: string, prefix: string, guildID: string, mongoDB: string };
|
public config: { token: string, prefix: string, guildID: string, mongoDB: string };
|
||||||
|
|
||||||
public commands: Collection<Command>;
|
public commands: Collection<Command>;
|
||||||
|
|
||||||
|
public events: Collection<Event>;
|
||||||
|
|
||||||
public intervals: Collection<NodeJS.Timeout>;
|
public intervals: Collection<NodeJS.Timeout>;
|
||||||
|
|
||||||
public util: Util;
|
public util: Util;
|
||||||
|
|
||||||
public db: { moderation: mongoose.Model<ModerationInterface> };
|
public serverManagement: ServerManagement;
|
||||||
|
|
||||||
|
public db: { Member: mongoose.Model<MemberInterface>, Moderation: mongoose.Model<ModerationInterface>, Redirect: mongoose.Model<RedirectInterface> };
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
||||||
constructor(token: string, options?: eris.ClientOptions) {
|
constructor(token: string, options?: eris.ClientOptions) {
|
||||||
super(token, options);
|
super(token, options);
|
||||||
this.commands = new Collection<Command>();
|
this.commands = new Collection<Command>();
|
||||||
|
this.events = new Collection<Event>();
|
||||||
this.intervals = new Collection<NodeJS.Timeout>();
|
this.intervals = new Collection<NodeJS.Timeout>();
|
||||||
this.db = { moderation: Moderation };
|
this.db = { Member, Moderation, Redirect };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadDatabase() {
|
public async loadDatabase() {
|
||||||
|
@ -29,6 +35,7 @@ export default class Client extends eris.Client {
|
||||||
|
|
||||||
public loadPlugins() {
|
public loadPlugins() {
|
||||||
this.util = new Util(this);
|
this.util = new Util(this);
|
||||||
|
this.serverManagement = new ServerManagement(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadIntervals() {
|
public async loadIntervals() {
|
||||||
|
@ -43,25 +50,22 @@ export default class Client extends eris.Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadEvents() {
|
public async loadEvents() {
|
||||||
const evtFiles = await fs.readdir(`${__dirname}/../events`);
|
const evtFiles = Object.entries<new(client: Client) => Event>(eventFiles);
|
||||||
evtFiles.forEach((file) => {
|
for (const [name, Ev] of evtFiles) {
|
||||||
const eventName = file.split('.')[0];
|
const event = new Ev(this);
|
||||||
if (file === 'index.js') return;
|
this.events.add(event.event, event);
|
||||||
// eslint-disable-next-line
|
this.on(event.event, event.run);
|
||||||
const event = new (require(`${__dirname}/../events/${file}`).default)(this);
|
this.util.signale.success(`Successfully loaded event: ${name}`);
|
||||||
this.on(eventName, (...args) => event.run(...args));
|
delete require.cache[require.resolve(`${__dirname}/../events/${name}`)];
|
||||||
this.util.signale.success(`Successfully loaded event: ${eventName}`);
|
}
|
||||||
delete require.cache[require.resolve(`${__dirname}/../events/${file}`)];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadCommands() {
|
public async loadCommands() {
|
||||||
const commandFiles = await fs.readdir(`${__dirname}/../commands`);
|
const cmdFiles = Object.values<new(client: Client) => Command>(commandFiles);
|
||||||
commandFiles.forEach((file) => {
|
for (const Cmd of cmdFiles) {
|
||||||
// eslint-disable-next-line new-cap
|
const command = new Cmd(this);
|
||||||
const command: Command = new (require(`${__dirname}/../commands/${file}`).default)(this);
|
|
||||||
this.commands.add(command.name, command);
|
this.commands.add(command.name, command);
|
||||||
this.util.signale.success(`Successfully loaded command: ${command.name}`);
|
this.util.signale.success(`Successfully loaded command: ${command.name}`);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,13 @@ export default class Command {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* - **0:** Everyone
|
* - **0:** Everyone
|
||||||
* - **1:** Associates Team+
|
* - **1:** Associates+
|
||||||
* - **2:** Sheriff+
|
* - **2:** Core Team+
|
||||||
* - **3:** Faculty Marshals+
|
* - **3:** Moderators, Supervisor, & Board of Directors
|
||||||
* - **4:** Marshal Generals of Engineering
|
* - **4:** Technicians, Supervisor, & Board of Directors
|
||||||
|
* - **5:** Moderators, Technicians, Supervisor, & Board of Directors
|
||||||
|
* - **6:** Supervisor+
|
||||||
|
* - **7:** Board of Directors
|
||||||
*/
|
*/
|
||||||
public permissions: number;
|
public permissions: number;
|
||||||
|
|
||||||
|
@ -57,13 +60,19 @@ export default class Command {
|
||||||
case 0:
|
case 0:
|
||||||
return true;
|
return true;
|
||||||
case 1:
|
case 1:
|
||||||
return member.roles.some((r) => ['662163685439045632', '455972169449734144', '453689940140883988'].includes(r));
|
return member.roles.some((r) => ['701481967149121627', '453689940140883988', '455972169449734144', '701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||||
case 2:
|
case 2:
|
||||||
return member.roles.some((r) => ['662163685439045632', '455972169449734144'].includes(r));
|
return member.roles.some((r) => ['453689940140883988', '455972169449734144', '701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
|
||||||
case 3:
|
case 3:
|
||||||
return member.roles.some((r) => ['662163685439045632'].includes(r));
|
return member.roles.some((r) => ['455972169449734144', '701454855952138300', '662163685439045632'].includes(r));
|
||||||
case 4:
|
case 4:
|
||||||
return member.id === '278620217221971968' || member.id === '253600545972027394';
|
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:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { Client } from '.';
|
||||||
|
|
||||||
|
export default class Event {
|
||||||
|
public client: Client
|
||||||
|
|
||||||
|
public event: string;
|
||||||
|
|
||||||
|
constructor(client: Client) {
|
||||||
|
this.client = client;
|
||||||
|
this.event = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(...args: any[]): Promise<void> { return Promise.resolve(); }
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable no-bitwise */
|
/* eslint-disable no-bitwise */
|
||||||
import { Member, User } from 'eris';
|
import { Member, User } from 'eris';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { randomBytes } from 'crypto';
|
||||||
import moment, { unitOfTime } from 'moment';
|
import moment, { unitOfTime } from 'moment';
|
||||||
import { Client, RichEmbed } from '.';
|
import { Client, RichEmbed } from '.';
|
||||||
import { Moderation as ModerationModel, ModerationInterface } from '../models';
|
import { Moderation as ModerationModel, ModerationInterface } from '../models';
|
||||||
|
@ -43,7 +43,7 @@ export default class Moderation {
|
||||||
public async ban(user: User, moderator: Member, duration: number, reason?: string): Promise<ModerationInterface> {
|
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');
|
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);
|
await this.client.guilds.get(this.client.config.guildID).banMember(user.id, 7, reason);
|
||||||
const logID = uuid();
|
const logID = randomBytes(2).toString('hex');
|
||||||
const mod = new ModerationModel({
|
const mod = new ModerationModel({
|
||||||
userID: user.id,
|
userID: user.id,
|
||||||
logID,
|
logID,
|
||||||
|
@ -85,7 +85,7 @@ export default class Moderation {
|
||||||
this.client.unbanGuildMember(this.client.config.guildID, userID, reason);
|
this.client.unbanGuildMember(this.client.config.guildID, userID, reason);
|
||||||
const user = await this.client.getRESTUser(userID);
|
const user = await this.client.getRESTUser(userID);
|
||||||
if (!user) throw new Error('Cannot get user.');
|
if (!user) throw new Error('Cannot get user.');
|
||||||
const logID = uuid();
|
const logID = randomBytes(2).toString('hex');
|
||||||
const mod = new ModerationModel({
|
const mod = new ModerationModel({
|
||||||
userID,
|
userID,
|
||||||
logID,
|
logID,
|
||||||
|
@ -110,4 +110,33 @@ export default class Moderation {
|
||||||
this.client.createMessage(this.logChannels.modlogs, { embed });
|
this.client.createMessage(this.logChannels.modlogs, { embed });
|
||||||
return mod.save();
|
return mod.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async kick(user: 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,20 +1,8 @@
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
|
|
||||||
export interface EmbedData {
|
import { EmbedOptions } from 'eris';
|
||||||
title?: string
|
|
||||||
description?: string
|
|
||||||
url?: string
|
|
||||||
timestamp?: 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 }
|
|
||||||
author?: { name: string, url?: string, proxy_icon_url?: string, icon_url?: string}
|
|
||||||
fields?: {name: string, value: string, inline?: boolean}[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class RichEmbed implements EmbedData {
|
export default class RichEmbed implements EmbedOptions {
|
||||||
title?: string
|
title?: string
|
||||||
|
|
||||||
type?: string
|
type?: string
|
||||||
|
@ -23,15 +11,15 @@ export default class RichEmbed implements EmbedData {
|
||||||
|
|
||||||
url?: string
|
url?: string
|
||||||
|
|
||||||
timestamp?: Date
|
timestamp?: string | Date
|
||||||
|
|
||||||
color?: number
|
color?: number
|
||||||
|
|
||||||
footer?: { text: string, icon_url?: string, proxy_icon_url?: string}
|
footer?: { text: string, icon_url?: string, proxy_icon_url?: string}
|
||||||
|
|
||||||
image?: { url: string, proxy_url?: string, height?: number, width?: number }
|
image?: { url?: string, proxy_url?: string, height?: number, width?: number }
|
||||||
|
|
||||||
thumbnail?: { 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 }
|
video?: { url: string, height?: number, width?: number }
|
||||||
|
|
||||||
|
@ -41,7 +29,7 @@ export default class RichEmbed implements EmbedData {
|
||||||
|
|
||||||
fields?: {name: string, value: string, inline?: boolean}[]
|
fields?: {name: string, value: string, inline?: boolean}[]
|
||||||
|
|
||||||
constructor(data: EmbedData = {}) {
|
constructor(data: EmbedOptions = {}) {
|
||||||
/*
|
/*
|
||||||
let types: {
|
let types: {
|
||||||
title?: string, type?: string, description?: string, url?: string, timestamp?: Date, color?: number, fields?: {name: string, value: string, inline?: boolean}[]
|
title?: string, type?: string, description?: string, url?: string, timestamp?: Date, color?: number, fields?: {name: string, value: string, inline?: boolean}[]
|
||||||
|
@ -87,7 +75,7 @@ export default class RichEmbed implements EmbedData {
|
||||||
*/
|
*/
|
||||||
setURL(url: string) {
|
setURL(url: string) {
|
||||||
if (typeof url !== 'string') throw new TypeError('RichEmbed URLs must be a string.');
|
if (typeof url !== 'string') throw new TypeError('RichEmbed URLs must be a string.');
|
||||||
if (!url.startsWith('http://') || !url.startsWith('https://')) url = `https://${url}`;
|
if (!url.startsWith('http://') && !url.startsWith('https://')) url = `https://${url}`;
|
||||||
this.url = encodeURI(url);
|
this.url = encodeURI(url);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -124,8 +112,7 @@ export default class RichEmbed implements EmbedData {
|
||||||
* Sets the timestamp of this embed.
|
* Sets the timestamp of this embed.
|
||||||
*/
|
*/
|
||||||
setTimestamp(timestamp = new Date()) {
|
setTimestamp(timestamp = new Date()) {
|
||||||
// eslint-disable-next-line no-restricted-globals
|
if (Number.isNaN(timestamp.getTime())) throw new TypeError('Expecting ISO8601 (Date constructor)');
|
||||||
if (isNaN(timestamp.getTime())) throw new TypeError('Expecting ISO8601 (Date constructor)');
|
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +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',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +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}'.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,8 +37,6 @@ export default class Util {
|
||||||
*/
|
*/
|
||||||
public resolveCommand(query: string | string[]): Promise<{cmd: Command, args: string[] }> {
|
public resolveCommand(query: string | string[]): Promise<{cmd: Command, args: string[] }> {
|
||||||
try {
|
try {
|
||||||
// let resolvedCommand: Command;
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
if (typeof query === 'string') query = query.split(' ');
|
if (typeof query === 'string') query = query.split(' ');
|
||||||
const commands = this.client.commands.toArray();
|
const commands = this.client.commands.toArray();
|
||||||
const resolvedCommand = commands.find((c) => c.name === query[0].toLowerCase() || c.aliases.includes(query[0].toLowerCase()));
|
const resolvedCommand = commands.find((c) => c.name === query[0].toLowerCase() || c.aliases.includes(query[0].toLowerCase()));
|
||||||
|
@ -70,10 +68,10 @@ export default class Util {
|
||||||
|| members.find((m) => m.username.toLowerCase().startsWith(query.toLowerCase()) || (m.nick && m.nick.toLowerCase().startsWith(query.toLowerCase())));
|
|| 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?: boolean): Promise<void> {
|
public async handleError(error: Error, message?: Message, command?: Command, disable = true): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this.signale.error(error);
|
this.signale.error(error);
|
||||||
const info = { content: `\`\`\`js\n${error.stack}\n\`\`\``, embed: null };
|
const info = { content: `\`\`\`js\n${error.stack || error}\n\`\`\``, embed: null };
|
||||||
if (message) {
|
if (message) {
|
||||||
const embed = new RichEmbed();
|
const embed = new RichEmbed();
|
||||||
embed.setColor('FF0000');
|
embed.setColor('FF0000');
|
||||||
|
@ -91,9 +89,8 @@ export default class Util {
|
||||||
}
|
}
|
||||||
await this.client.createMessage('595788220764127272', info);
|
await this.client.createMessage('595788220764127272', info);
|
||||||
const msg = message ? message.content.slice(this.client.config.prefix.length).trim().split(/ +/g) : [];
|
const msg = message ? message.content.slice(this.client.config.prefix.length).trim().split(/ +/g) : [];
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
if (command && disable) this.resolveCommand(msg).then((c) => { c.cmd.enabled = false; });
|
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 Faculty Marshal.${command && disable ? ' This command has been disabled.' : ''}***`);
|
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) {
|
} catch (err) {
|
||||||
this.signale.error(err);
|
this.signale.error(err);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +98,6 @@ export default class Util {
|
||||||
|
|
||||||
public splitString(string: string, length: number): string[] {
|
public splitString(string: string, length: number): string[] {
|
||||||
if (!string) return [];
|
if (!string) return [];
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
if (Array.isArray(string)) string = string.join('\n');
|
if (Array.isArray(string)) string = string.join('\n');
|
||||||
if (string.length <= length) return [string];
|
if (string.length <= length) return [string];
|
||||||
const arrayString: string[] = [];
|
const arrayString: string[] = [];
|
||||||
|
@ -111,19 +107,24 @@ export default class Util {
|
||||||
pos = string.length > length ? string.lastIndexOf('\n', length) : string.length;
|
pos = string.length > length ? string.lastIndexOf('\n', length) : string.length;
|
||||||
if (pos > length) pos = length;
|
if (pos > length) pos = length;
|
||||||
str = string.substr(0, pos);
|
str = string.substr(0, pos);
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
string = string.substr(pos);
|
string = string.substr(pos);
|
||||||
arrayString.push(str);
|
arrayString.push(str);
|
||||||
}
|
}
|
||||||
return arrayString;
|
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 {
|
public decimalToHex(int: number): string {
|
||||||
const red = (int && 0x0000ff) << 16;
|
const hex = int.toString(16);
|
||||||
const green = int && 0x00ff00;
|
return '#000000'.substring(0, 7 - hex.length) + hex;
|
||||||
const blue = (int && 0xff0000) >>> 16;
|
|
||||||
const number = red | green | blue;
|
|
||||||
const asHex = number.toString(16);
|
|
||||||
return '#000000'.substring(0, 7 - asHex.length) + asHex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
export { default as Client } from './Client';
|
export { default as Client } from './Client';
|
||||||
export { default as Collection } from './Collection';
|
export { default as Collection } from './Collection';
|
||||||
export { default as Command } from './Command';
|
export { default as Command } from './Command';
|
||||||
|
export { default as Event } from './Event';
|
||||||
export { default as Moderation } from './Moderation';
|
export { default as Moderation } from './Moderation';
|
||||||
export { default as RichEmbed } from './RichEmbed';
|
export { default as RichEmbed } from './RichEmbed';
|
||||||
|
export { default as Route } from './Route';
|
||||||
|
export { default as Server } from './Server';
|
||||||
|
export { default as ServerManagement } from './ServerManagement';
|
||||||
export { default as Util } from './Util';
|
export { default as Util } from './Util';
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import { Client, Command, RichEmbed } from '../class';
|
||||||
|
|
||||||
|
export default class AddItem extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'additem';
|
||||||
|
this.description = 'Adds information to your whois embed.';
|
||||||
|
this.usage = 'additem [code]';
|
||||||
|
this.permissions = 0;
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(message: Message, args: string[]) {
|
||||||
|
try {
|
||||||
|
if (args.length < 1) {
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle('Whois Data Codes');
|
||||||
|
embed.addField('Languages', '**Assembly Language:** lang-asm\n**C/C++:** lang-cfam\n**C#:** lang-csharp\n**Go:** lang-go\n**Java:** lang-java\n**JavaScript:** lang-js\n**Kotlin:** lang-kt\n**Python:** lang-py\n**Ruby:** lang-rb\n**Rust:** lang-rs\n**Swift:** lang-swift\n**TypeScript:** lang-ts');
|
||||||
|
embed.addField('Operating Systems', '**Arch:** os-arch\n**Debian:** os-deb\n**CentOS:** os-cent\n**Fedora:** os-fedora\n**macOS:** os-mdarwin\n**Manjaro:** os-manjaro\n**RedHat:** os-redhat\n**Ubuntu:** os-ubuntu\n**Windows:** os-win');
|
||||||
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
embed.setTimestamp();
|
||||||
|
return message.channel.createMessage({ embed });
|
||||||
|
}
|
||||||
|
if (args[0].split('-')[0] === 'os' && ['arch', 'deb', 'cent', 'fedora', 'manjaro', 'mdarwin', 'redhat', 'ubuntu', 'win'].includes(args[0].split('-')[1])) {
|
||||||
|
const account = await this.client.db.Member.findOne({ userID: message.member.id });
|
||||||
|
if (!account) {
|
||||||
|
const newAccount = new this.client.db.Member({
|
||||||
|
userID: message.member.id,
|
||||||
|
additional: {
|
||||||
|
operatingSystems: [args[0].split('-')[1]],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await newAccount.save();
|
||||||
|
} else {
|
||||||
|
await account.updateOne({ $addToSet: { 'additional.operatingSystems': args[0].split('-')[1] } });
|
||||||
|
}
|
||||||
|
return message.channel.createMessage(`***${this.client.util.emojis.SUCCESS} Added OS code ${args[0]} to profile.***`);
|
||||||
|
}
|
||||||
|
if (args[0].split('-')[0] === 'lang' && ['js', 'py', 'rb', 'ts', 'rs', 'go', 'cfam', 'csharp', 'swift', 'java', 'kt', 'asm'].includes(args[0].split('-')[1])) {
|
||||||
|
const account = await this.client.db.Member.findOne({ userID: message.member.id });
|
||||||
|
if (!account) {
|
||||||
|
const newAccount = new this.client.db.Member({
|
||||||
|
userID: message.member.id,
|
||||||
|
additional: {
|
||||||
|
langs: [args[0].split('-')[1]],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await newAccount.save();
|
||||||
|
} else {
|
||||||
|
await account.updateOne({ $addToSet: { 'additional.langs': args[0].split('-')[1] } });
|
||||||
|
}
|
||||||
|
return message.channel.createMessage(`***${this.client.util.emojis.SUCCESS} Added language code ${args[0]} to profile.***`);
|
||||||
|
}
|
||||||
|
return message.channel.createMessage(`***${this.client.util.emojis.ERROR} Invalid data code.***`);
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import { Client, Command } from '../class';
|
||||||
|
|
||||||
|
export default class AddRedirect extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'addredirect';
|
||||||
|
this.description = 'Adds a redirect link for \'loc.sh\'';
|
||||||
|
this.usage = 'addredirect <redirect to url> <key>';
|
||||||
|
this.aliases = ['ar'];
|
||||||
|
this.permissions = 6;
|
||||||
|
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 check = await this.client.db.Redirect.findOne({ key: args[1].toLowerCase() });
|
||||||
|
if (check) return this.error(message.channel, `Redirect key ${args[1].toLowerCase()} already exists. Linked to: ${check.to}`);
|
||||||
|
try {
|
||||||
|
const test = new URL(args[0]);
|
||||||
|
if (test.protocol !== 'https:') return this.error(message.channel, 'Protocol must be HTTPS.');
|
||||||
|
} catch {
|
||||||
|
return this.error(message.channel, 'This doesn\'t appear to be a valid URL.');
|
||||||
|
}
|
||||||
|
if ((/^[a-zA-Z0-9]+$/gi.test(args[1].toLowerCase().replace('-', '').trim()) === false) || args[1].toLowerCase().length > 15) return this.error(message.channel, 'Invalid key. The key must be alphanumeric and less than 16 characters.');
|
||||||
|
const redirect = new this.client.db.Redirect({
|
||||||
|
key: args[1].toLowerCase(),
|
||||||
|
to: args[0],
|
||||||
|
});
|
||||||
|
await redirect.save();
|
||||||
|
return this.success(message.channel, `Redirect https://loc.sh/${args[1].toLowerCase()} -> ${args[0]} is now active.`);
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,13 +8,14 @@ export default class Ban extends Command {
|
||||||
this.name = 'ban';
|
this.name = 'ban';
|
||||||
this.description = 'Bans a member from the guild.';
|
this.description = 'Bans a member from the guild.';
|
||||||
this.usage = 'ban <member> [time] [reason]';
|
this.usage = 'ban <member> [time] [reason]';
|
||||||
this.permissions = 2;
|
this.permissions = 3;
|
||||||
this.guildOnly = true;
|
this.guildOnly = true;
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run(message: Message, args: string[]) {
|
public async run(message: Message, args: string[]) {
|
||||||
try {
|
try {
|
||||||
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
const member = this.client.util.resolveMember(args[0], this.client.guilds.get(this.client.config.guildID));
|
const member = this.client.util.resolveMember(args[0], this.client.guilds.get(this.client.config.guildID));
|
||||||
let user: User;
|
let user: User;
|
||||||
if (!member) {
|
if (!member) {
|
||||||
|
@ -23,6 +24,8 @@ export default class Ban extends Command {
|
||||||
} catch {
|
} catch {
|
||||||
return this.error(message.channel, 'Cannot find user.');
|
return this.error(message.channel, 'Cannot find user.');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
user = member.user;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await this.client.guilds.get(this.client.config.guildID).getBan(args[0]);
|
await this.client.guilds.get(this.client.config.guildID).getBan(args[0]);
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import { Client, Command, RichEmbed } from '../class';
|
||||||
|
|
||||||
|
export default class DelItem extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'delitem';
|
||||||
|
this.description = 'Removes information to your whois embed.';
|
||||||
|
this.usage = 'delitem [code]';
|
||||||
|
this.permissions = 0;
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(message: Message, args: string[]) {
|
||||||
|
try {
|
||||||
|
if (args.length < 1) {
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle('Whois Data Codes');
|
||||||
|
embed.addField('Languages', '**Assembly Language:** lang-asm\n**C/C++:** lang-cfam\n**C#:** lang-csharp\n**Go:** lang-go\n**Java:** lang-java\n**JavaScript:** lang-js\n**Kotlin:** lang-kt\n**Python:** lang-py\n**Ruby:** lang-rb\n**Rust:** lang-rs\n**Swift:** lang-swift\n**TypeScript:** lang-ts');
|
||||||
|
embed.addField('Operating Systems', '**Arch:** os-arch\n**Debian:** os-deb\n**CentOS:** os-cent\n**Fedora:** os-fedora\n**macOS:** os-mdarwin\n**Manjaro:** os-manjaro\n**RedHat:** os-redhat\n**Ubuntu:** os-ubuntu\n**Windows:** os-win');
|
||||||
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
embed.setTimestamp();
|
||||||
|
return message.channel.createMessage({ embed });
|
||||||
|
}
|
||||||
|
if (args[0].split('-')[0] === 'os' && ['arch', 'deb', 'cent', 'fedora', 'manjaro', 'mdarwin', 'redhat', 'ubuntu', 'win'].includes(args[0].split('-')[1])) {
|
||||||
|
const account = await this.client.db.Member.findOne({ userID: message.member.id });
|
||||||
|
if (!account || !account?.additional.operatingSystems || account?.additional.operatingSystems.length < 1) {
|
||||||
|
return message.channel.createMessage(`***${this.client.util.emojis.ERROR} You don't have any operating systems to remove.***`);
|
||||||
|
}
|
||||||
|
await account.updateOne({ $pull: { 'additional.operatingSystems': args[0].split('-')[1] } });
|
||||||
|
return message.channel.createMessage(`***${this.client.util.emojis.SUCCESS} Removed OS code ${args[0]} from profile.***`);
|
||||||
|
}
|
||||||
|
if (args[0].split('-')[0] === 'lang' && ['js', 'py', 'rb', 'ts', 'rs', 'go', 'cfam', 'csharp', 'swift', 'java', 'kt', 'asm'].includes(args[0].split('-')[1])) {
|
||||||
|
const account = await this.client.db.Member.findOne({ userID: message.member.id });
|
||||||
|
if (!account || !account?.additional.langs || account?.additional.langs.length < 1) {
|
||||||
|
return message.channel.createMessage(`***${this.client.util.emojis.ERROR} You don't have any languages to remove.***`);
|
||||||
|
}
|
||||||
|
await account.updateOne({ $pull: { 'additional.langs': args[0].split('-')[1] } });
|
||||||
|
return message.channel.createMessage(`***${this.client.util.emojis.SUCCESS} Removed language code ${args[0]} from profile.***`);
|
||||||
|
}
|
||||||
|
return message.channel.createMessage(`***${this.client.util.emojis.ERROR} Invalid data code.***`);
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import { Client, Command } from '../class';
|
||||||
|
|
||||||
|
export default class DelRedirect extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'delredirect';
|
||||||
|
this.description = 'Delete a redirect link for \'loc.sh\'';
|
||||||
|
this.usage = 'delredirect <key>';
|
||||||
|
this.aliases = ['dr'];
|
||||||
|
this.permissions = 6;
|
||||||
|
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 check = await this.client.db.Redirect.findOne({ key: args[0].toLowerCase() });
|
||||||
|
if (!check) return this.error(message.channel, `Redirect key ${args[0].toLowerCase()} doesn't exist.`);
|
||||||
|
await this.client.db.Redirect.deleteOne({ key: args[0].toLowerCase() });
|
||||||
|
return this.success(message.channel, `Deleted redirect https://loc.sh/${args[0].toLowerCase()}.`);
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { Message, EmbedOptions } from 'eris';
|
||||||
|
import axios, { AxiosResponse } from 'axios';
|
||||||
|
import { Client, Command, RichEmbed } from '../class';
|
||||||
|
|
||||||
|
export default class DJS extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'djs';
|
||||||
|
this.description = 'Get information about Discord.js.';
|
||||||
|
this.usage = 'djs <query>';
|
||||||
|
this.permissions = 0;
|
||||||
|
this.guildOnly = false;
|
||||||
|
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 { data }: AxiosResponse<EmbedOptions> = await axios.get(`https://djsdocs.sorta.moe/v2/embed?src=master&q=${args[0]}`);
|
||||||
|
if (!data) return this.error(message.channel, 'Could not find information. Try something else.');
|
||||||
|
|
||||||
|
const embed = new RichEmbed(data);
|
||||||
|
return message.channel.createMessage({ embed });
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ export default class Eval extends Command {
|
||||||
this.name = 'eval';
|
this.name = 'eval';
|
||||||
this.description = 'Evaluates native JS code';
|
this.description = 'Evaluates native JS code';
|
||||||
this.aliases = ['e'];
|
this.aliases = ['e'];
|
||||||
this.permissions = 4;
|
this.permissions = 7;
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
this.guildOnly = false;
|
this.guildOnly = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ import { Activity, Member, Message } from 'eris';
|
||||||
import { Client, Command, RichEmbed } from '../class';
|
import { Client, Command, RichEmbed } from '../class';
|
||||||
|
|
||||||
enum ActivityType {
|
enum ActivityType {
|
||||||
PLAYING = 0,
|
PLAYING,
|
||||||
STREAMING = 1,
|
STREAMING,
|
||||||
LISTENING = 2,
|
LISTENING,
|
||||||
WATCHING = 3,
|
WATCHING,
|
||||||
CUSTOM_STATUS = 4
|
CUSTOM_STATUS
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Game extends Command {
|
export default class Game extends Command {
|
||||||
|
@ -47,13 +47,9 @@ export default class Game extends Command {
|
||||||
embed.setColor('#1ed760');
|
embed.setColor('#1ed760');
|
||||||
embed.addField('Song', mainStatus.details, true);
|
embed.addField('Song', mainStatus.details, true);
|
||||||
embed.addField('Artist', mainStatus.state, true);
|
embed.addField('Artist', mainStatus.state, true);
|
||||||
// @ts-ignore
|
|
||||||
embed.addField('Album', mainStatus.assets.large_text);
|
embed.addField('Album', mainStatus.assets.large_text);
|
||||||
// @ts-ignore
|
|
||||||
embed.addField('Start', `${new Date(mainStatus.timestamps.start).toLocaleTimeString('en-us')} ET`, true);
|
embed.addField('Start', `${new Date(mainStatus.timestamps.start).toLocaleTimeString('en-us')} ET`, true);
|
||||||
// @ts-ignore
|
|
||||||
embed.addField('End', `${new Date(mainStatus.timestamps.end).toLocaleTimeString('en-us')} ET`, true);
|
embed.addField('End', `${new Date(mainStatus.timestamps.end).toLocaleTimeString('en-us')} ET`, true);
|
||||||
// @ts-ignore
|
|
||||||
embed.setThumbnail(`https://i.scdn.co/image/${mainStatus.assets.large_image.split(':')[1]}`);
|
embed.setThumbnail(`https://i.scdn.co/image/${mainStatus.assets.large_image.split(':')[1]}`);
|
||||||
embed.setFooter(`Listening to Spotify | ${this.client.user.username}`, 'https://media.discordapp.net/attachments/358674161566220288/496894273304920064/2000px-Spotify_logo_without_text.png');
|
embed.setFooter(`Listening to Spotify | ${this.client.user.username}`, 'https://media.discordapp.net/attachments/358674161566220288/496894273304920064/2000px-Spotify_logo_without_text.png');
|
||||||
embed.setTimestamp();
|
embed.setTimestamp();
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
import { createPaginationEmbed } from 'eris-pagination';
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import { Client, Command, RichEmbed } from '../class';
|
||||||
|
|
||||||
|
export default class Help extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'help';
|
||||||
|
this.description = 'Information about commands.';
|
||||||
|
this.usage = 'help [command]';
|
||||||
|
this.permissions = 0;
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(message: Message, args: string[]) {
|
||||||
|
try {
|
||||||
|
if (args.length > 0) {
|
||||||
|
const command = this.client.commands.get(args[0].toLowerCase());
|
||||||
|
if (!command) return this.error(message.channel, 'The command you provided doesn\'t exist.');
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle(`${this.client.config.prefix}${command.name}`);
|
||||||
|
embed.addField('Description', command.description ?? '-');
|
||||||
|
embed.addField('Usage', command.usage ?? '-');
|
||||||
|
if (command.aliases.length > 0) {
|
||||||
|
embed.addField('Aliases', command.aliases.map((alias) => `${this.client.config.prefix}${alias}`).join(', '));
|
||||||
|
}
|
||||||
|
let description: string = '';
|
||||||
|
if (!command.enabled) {
|
||||||
|
description += 'This command is disabled.';
|
||||||
|
}
|
||||||
|
if (command.guildOnly) {
|
||||||
|
description += 'This command can only be ran in a guild.';
|
||||||
|
}
|
||||||
|
embed.setDescription(description);
|
||||||
|
switch (command.permissions) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
embed.addField('Permissions', 'Associates+');
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
embed.addField('Permissions', 'Core Team+');
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
embed.addField('Permissions', 'Moderators, Supervisor, & Board of Directors');
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
embed.addField('Permissions', 'Technicians, Supervisor, & Board of Directors');
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
embed.addField('Permissions', 'Moderators, Technicians, Supervisor, & Board of Directors');
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
embed.addField('Permissions', 'Supervisor+');
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
embed.addField('Permissions', 'Board of Directors');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
embed.setTimestamp();
|
||||||
|
return message.channel.createMessage({ embed });
|
||||||
|
}
|
||||||
|
const cmdList: Command[] = [];
|
||||||
|
this.client.commands.forEach((c) => cmdList.push(c));
|
||||||
|
const commands = this.client.commands.map((c) => {
|
||||||
|
const aliases = c.aliases.map((alias) => `${this.client.config.prefix}${alias}`).join(', ');
|
||||||
|
let perm: string;
|
||||||
|
switch (c.permissions) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
perm = 'Associates+';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
perm = 'Core Team+';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
perm = 'Moderators, Supervisor, & Board of Directors';
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
perm = 'Technicians, Supervisor, & Board of Directors';
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
perm = 'Moderators, Technicians, Supervisor, & Board of Directors';
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
perm = 'Supervisor+';
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
perm = 'Board of Directors';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return { name: `${this.client.config.prefix}${c.name}`, value: `**Description:** ${c.description}\n**Aliases:** ${aliases}\n**Usage:** ${c.usage}\n**Permissions:** ${perm ?? ''}`, inline: false };
|
||||||
|
});
|
||||||
|
const splitCommands = this.client.util.splitFields(commands);
|
||||||
|
const cmdPages: RichEmbed[] = [];
|
||||||
|
splitCommands.forEach((splitCmd) => {
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTimestamp(); embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
embed.setDescription(`Command list for ${this.client.user.username}`);
|
||||||
|
splitCmd.forEach((c) => embed.addField(c.name, c.value, c.inline));
|
||||||
|
return cmdPages.push(embed);
|
||||||
|
});
|
||||||
|
if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });
|
||||||
|
return createPaginationEmbed(message, cmdPages);
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import { totalmem } from 'os';
|
||||||
|
import { Client, Command, RichEmbed } from '../class';
|
||||||
|
import { version as erisVersion } from '../../node_modules/eris/package.json';
|
||||||
|
import { version as mongooseVersion } from '../../node_modules/mongoose/package.json';
|
||||||
|
|
||||||
|
export default class Info extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'info';
|
||||||
|
this.description = 'System information.';
|
||||||
|
this.usage = 'info';
|
||||||
|
this.permissions = 0;
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(message: Message) {
|
||||||
|
try {
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle('Information');
|
||||||
|
embed.setThumbnail(this.client.user.avatarURL);
|
||||||
|
embed.addField('Language(s)', '<:TypeScript:703451285789343774> TypeScript', true);
|
||||||
|
embed.addField('Discord Library', `Eris (${erisVersion})`, true);
|
||||||
|
embed.addField('Database Library', `MongoDB w/ Mongoose ODM (${mongooseVersion})`, true);
|
||||||
|
embed.addField('Repository', 'https://gitlab.libraryofcode.org/engineering/communityrelations | Licensed under GNU Affero General Public License V3', true);
|
||||||
|
embed.addField('Memory Usage', `${Math.round(process.memoryUsage().rss / 1024 / 1024)} MB / ${Math.round(totalmem() / 1024 / 1024 / 1024)} GB`, true);
|
||||||
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
embed.setTimestamp();
|
||||||
|
message.channel.createMessage({ embed });
|
||||||
|
} catch (err) {
|
||||||
|
this.client.util.handleError(err, message, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { Message, User } from 'eris';
|
||||||
|
import { Client, Command } from '../class';
|
||||||
|
|
||||||
|
export default class Kick extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'kick';
|
||||||
|
this.description = 'Kicks a member from the guild.';
|
||||||
|
this.usage = 'kick <member> [reason]';
|
||||||
|
this.permissions = 3;
|
||||||
|
this.guildOnly = true;
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(message: Message, args: string[]) {
|
||||||
|
try {
|
||||||
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
|
const member = this.client.util.resolveMember(args[0], this.client.guilds.get(this.client.config.guildID));
|
||||||
|
let user: User;
|
||||||
|
if (!member) {
|
||||||
|
try {
|
||||||
|
user = await this.client.getRESTUser(args[0]);
|
||||||
|
} catch {
|
||||||
|
return this.error(message.channel, 'Cannot find user.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (member && !this.client.util.moderation.checkPermissions(member, message.member)) return this.error(message.channel, 'Permission Denied.');
|
||||||
|
message.delete();
|
||||||
|
|
||||||
|
const reason: string = args[1];
|
||||||
|
if (reason.length > 512) return this.error(message.channel, 'Kick reasons cannot be longer than 512 characters.');
|
||||||
|
await this.client.util.moderation.kick(user, message.member, reason);
|
||||||
|
return this.success(message.channel, `${user.username}#${user.id} has been kicked.`);
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import { createPaginationEmbed } from 'eris-pagination';
|
||||||
|
import { Client, Command, RichEmbed } from '../class';
|
||||||
|
|
||||||
|
export default class DelRedirect extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'listredirects';
|
||||||
|
this.description = 'Delete a redirect link for \'loc.sh\'';
|
||||||
|
this.usage = 'listredirects [key || redirect to]';
|
||||||
|
this.aliases = ['getredirect', 'lsredirects', 'listlinks', 'lsr', 'gr'];
|
||||||
|
this.permissions = 6;
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(message: Message, args: string[]) {
|
||||||
|
try {
|
||||||
|
if (args[0]) {
|
||||||
|
const redirects = await this.client.db.Redirect.find({ $or: [{ key: args[0].toLowerCase() }, { to: args[0].toLowerCase() }] });
|
||||||
|
if (redirects.length <= 0) return this.error(message.channel, 'Could not find an entry matching that query.');
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle('Redirect Information');
|
||||||
|
for (const redirect of redirects) {
|
||||||
|
embed.addField(redirect.key, redirect.to);
|
||||||
|
}
|
||||||
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
embed.setTimestamp();
|
||||||
|
return message.channel.createMessage({ embed });
|
||||||
|
}
|
||||||
|
const redirects = await this.client.db.Redirect.find();
|
||||||
|
if (!redirects) return this.error(message.channel, 'No redirect links found.');
|
||||||
|
const redirectArray: [{ name: string, value: string }?] = [];
|
||||||
|
for (const redirect of redirects) {
|
||||||
|
redirectArray.push({ name: redirect.key, value: redirect.to });
|
||||||
|
}
|
||||||
|
const splitRedirects = this.client.util.splitFields(redirectArray);
|
||||||
|
const cmdPages: RichEmbed[] = [];
|
||||||
|
splitRedirects.forEach((split) => {
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setTitle('Redirect Information');
|
||||||
|
embed.setTimestamp();
|
||||||
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
split.forEach((c) => embed.addField(c.name, c.value));
|
||||||
|
return cmdPages.push(embed);
|
||||||
|
});
|
||||||
|
if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });
|
||||||
|
return createPaginationEmbed(message, cmdPages);
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { Message } from 'eris';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { Client, Command, RichEmbed } from '../class';
|
||||||
|
|
||||||
|
export default class NPM extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'npm';
|
||||||
|
this.description = 'Get information about npm modules.';
|
||||||
|
this.usage = 'npm <module name>';
|
||||||
|
this.permissions = 0;
|
||||||
|
this.guildOnly = false;
|
||||||
|
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 res = await axios.get(`https://registry.npmjs.com/${args[0]}`, { validateStatus: (_) => true });
|
||||||
|
|
||||||
|
if (res.status === 404) return this.error(message.channel, 'Could not find the library, try something else.');
|
||||||
|
|
||||||
|
const { data } = res;
|
||||||
|
|
||||||
|
const bugs: string = data.bugs?.url || '';
|
||||||
|
const description: string = data.description || 'None';
|
||||||
|
const version: string = data['dist-tags']?.latest || 'Unknown';
|
||||||
|
const homepage: string = data.homepage || '';
|
||||||
|
let license: string = 'None';
|
||||||
|
if (typeof data.license === 'object') {
|
||||||
|
license = data.license.type;
|
||||||
|
} else if (typeof data.license === 'string') {
|
||||||
|
license = data.license;
|
||||||
|
}
|
||||||
|
let dependencies: string = 'None';
|
||||||
|
if (version !== 'Unknown' && data.versions[version].dependencies !== undefined && Object.keys(data.versions[version].dependencies).length > 0) {
|
||||||
|
dependencies = Object.keys(data.versions[version].dependencies).join(', ');
|
||||||
|
}
|
||||||
|
const name: string = data.name || 'None';
|
||||||
|
const repository: string = bugs.replace('/issues', '') || '';
|
||||||
|
const creation: string = data.time.created ? new Date(data.time.created).toLocaleString('en') : 'None';
|
||||||
|
const modification: string = data.time.modified ? new Date(data.time.modified).toLocaleString('en') : 'None';
|
||||||
|
|
||||||
|
const embed = new RichEmbed();
|
||||||
|
embed.setColor(0xCC3534);
|
||||||
|
embed.setTimestamp();
|
||||||
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
|
||||||
|
embed.setAuthor('NPM', 'https://i.imgur.com/ErKf5Y0.png', 'https://www.npmjs.com/');
|
||||||
|
embed.setDescription(`[NPM](https://www.npmjs.com/package/${args[0]}) | [Homepage](${homepage}) | [Repository](${repository}) | [Bugs](${bugs})`);
|
||||||
|
embed.addField('Name', name, true);
|
||||||
|
embed.addField('Latest version', version, true);
|
||||||
|
embed.addField('License', license, true);
|
||||||
|
embed.addField('Description', description, false);
|
||||||
|
embed.addField('Dependencies', dependencies, false);
|
||||||
|
embed.addField('Creation Date', creation, true);
|
||||||
|
embed.addField('Modification Date', modification, true);
|
||||||
|
|
||||||
|
return message.channel.createMessage({ embed });
|
||||||
|
} catch (err) {
|
||||||
|
return this.client.util.handleError(err, message, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ export default class Roleinfo extends Command {
|
||||||
|
|
||||||
public async run(message: Message, args: string[]) {
|
public async run(message: Message, args: string[]) {
|
||||||
try {
|
try {
|
||||||
if (!args[0]) return this.error(message.channel, 'You need to specifiy a role ID or a role name.');
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
|
|
||||||
let role: Role = this.client.guilds.get(this.client.config.guildID).roles.find((r: Role) => r.id === args[0]);
|
let role: Role = this.client.guilds.get(this.client.config.guildID).roles.find((r: Role) => r.id === args[0]);
|
||||||
if (!role) { // if it's a role name
|
if (!role) { // if it's a role name
|
||||||
|
|
|
@ -7,13 +7,14 @@ export default class Unban extends Command {
|
||||||
this.name = 'unban';
|
this.name = 'unban';
|
||||||
this.description = 'Unbans a member from the guild.';
|
this.description = 'Unbans a member from the guild.';
|
||||||
this.usage = 'unban <user id> [reason]';
|
this.usage = 'unban <user id> [reason]';
|
||||||
this.permissions = 2;
|
this.permissions = 3;
|
||||||
this.guildOnly = true;
|
this.guildOnly = true;
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run(message: Message, args: string[]) {
|
public async run(message: Message, args: string[]) {
|
||||||
try {
|
try {
|
||||||
|
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
let user: User;
|
let user: User;
|
||||||
try {
|
try {
|
||||||
user = await this.client.getRESTUser(args[0]);
|
user = await this.client.getRESTUser(args[0]);
|
||||||
|
|
|
@ -42,8 +42,8 @@ export default class Whois extends Command {
|
||||||
const ackResolve = this.resolveStaffInformation(member.id);
|
const ackResolve = this.resolveStaffInformation(member.id);
|
||||||
let description = '';
|
let description = '';
|
||||||
if (ackResolve) {
|
if (ackResolve) {
|
||||||
if (ackResolve?.title && ackResolve?.dept) {
|
if (ackResolve?.title) {
|
||||||
description += `${emotes.titleAndDepartment} __**${ackResolve.title}**__, ${ackResolve.dept}\n\n`;
|
description += `${emotes.titleAndDepartment} __**${ackResolve.title}**__\n\n`;
|
||||||
}
|
}
|
||||||
if (ackResolve?.emailAddress) {
|
if (ackResolve?.emailAddress) {
|
||||||
description += `${emotes.email} ${ackResolve.emailAddress}\n`;
|
description += `${emotes.email} ${ackResolve.emailAddress}\n`;
|
||||||
|
@ -68,6 +68,15 @@ export default class Whois extends Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
embed.addField('Status', `${member.status[0].toUpperCase()}${member.status.slice(1)}`, true);
|
embed.addField('Status', `${member.status[0].toUpperCase()}${member.status.slice(1)}`, true);
|
||||||
|
if (member.bot) {
|
||||||
|
embed.addField('Platform', 'API/WebSocket', true);
|
||||||
|
} else if (member.clientStatus?.web === 'online' || member.clientStatus?.web === 'idle' || member.clientStatus?.web === 'dnd') {
|
||||||
|
embed.addField('Platform', 'Web', true);
|
||||||
|
} else if (member.clientStatus?.desktop === 'online' || member.clientStatus?.desktop === 'idle' || member.clientStatus?.desktop === 'dnd') {
|
||||||
|
embed.addField('Platform', 'Desktop', true);
|
||||||
|
} else if (member.clientStatus?.mobile === 'online' || member.clientStatus?.mobile === 'idle' || member.clientStatus?.mobile === 'dnd') {
|
||||||
|
embed.addField('Platform', 'Mobile', true);
|
||||||
|
}
|
||||||
embed.addField('Joined At', `${moment(new Date(member.joinedAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true);
|
embed.addField('Joined At', `${moment(new Date(member.joinedAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true);
|
||||||
embed.addField('Created At', `${moment(new Date(member.user.createdAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true);
|
embed.addField('Created At', `${moment(new Date(member.user.createdAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true);
|
||||||
if (member.roles.length > 0) {
|
if (member.roles.length > 0) {
|
||||||
|
@ -78,14 +87,98 @@ export default class Whois extends Command {
|
||||||
const bit = member.permission.allow;
|
const bit = member.permission.allow;
|
||||||
if (this.client.guilds.get(this.client.config.guildID).ownerID === member.id) serverAcknowledgements.push('Server Owner');
|
if (this.client.guilds.get(this.client.config.guildID).ownerID === member.id) serverAcknowledgements.push('Server Owner');
|
||||||
if ((bit | 8) === bit) { permissions.push('Administrator'); serverAcknowledgements.push('Server Admin'); }
|
if ((bit | 8) === bit) { permissions.push('Administrator'); serverAcknowledgements.push('Server Admin'); }
|
||||||
if ((bit | 20) === bit) { permissions.push('Manage Server'); serverAcknowledgements.push('Server Manager'); }
|
if ((bit | 32) === bit) { permissions.push('Manage Server'); serverAcknowledgements.push('Server Manager'); }
|
||||||
if ((bit | 10) === bit) permissions.push('Manage Channels');
|
if ((bit | 16) === bit) permissions.push('Manage Channels');
|
||||||
if ((bit | 268435456) === bit) permissions.push('Manage Roles');
|
if ((bit | 268435456) === bit) permissions.push('Manage Roles');
|
||||||
if ((bit | 8192) === bit) { permissions.push('Manage Messages'); serverAcknowledgements.push('Server Moderator'); }
|
if ((bit | 8192) === bit) { permissions.push('Manage Messages'); serverAcknowledgements.push('Server Moderator'); }
|
||||||
if ((bit | 134217728) === bit) permissions.push('Manage Nicknames');
|
if ((bit | 134217728) === bit) permissions.push('Manage Nicknames');
|
||||||
if ((bit | 1073741824) === bit) permissions.push('Manage Emojis');
|
if ((bit | 1073741824) === bit) permissions.push('Manage Emojis');
|
||||||
if ((bit | 4) === bit) permissions.push('Ban Members');
|
if ((bit | 4) === bit) permissions.push('Ban Members');
|
||||||
if ((bit | 2) === bit) permissions.push('Kick Members');
|
if ((bit | 2) === bit) permissions.push('Kick Members');
|
||||||
|
const account = await this.client.db.Member.findOne({ userID: member.id });
|
||||||
|
if (account?.additional?.langs.length > 0) {
|
||||||
|
const langs: string[] = [];
|
||||||
|
for (const lang of account.additional.langs.sort((a, b) => a.localeCompare(b))) {
|
||||||
|
switch (lang) {
|
||||||
|
case 'asm':
|
||||||
|
langs.push('<:AssemblyLanguage:703448714248716442> Assembly Language');
|
||||||
|
break;
|
||||||
|
case 'cfam':
|
||||||
|
langs.push('<:clang:553684262193332278> C/C++');
|
||||||
|
break;
|
||||||
|
case 'csharp':
|
||||||
|
langs.push('<:csharp:553684277280112660> C#');
|
||||||
|
break;
|
||||||
|
case 'go':
|
||||||
|
langs.push('<:Go:703449475405971466> Go');
|
||||||
|
break;
|
||||||
|
case 'java':
|
||||||
|
langs.push('<:Java:703449725181100135> Java');
|
||||||
|
break;
|
||||||
|
case 'js':
|
||||||
|
langs.push('<:JavaScriptECMA:703449987916496946> JavaScript');
|
||||||
|
break;
|
||||||
|
case 'kt':
|
||||||
|
langs.push('<:Kotlin:703450201838321684> Kotlin');
|
||||||
|
break;
|
||||||
|
case 'py':
|
||||||
|
langs.push('<:python:553682965482176513> Python');
|
||||||
|
break;
|
||||||
|
case 'rb':
|
||||||
|
langs.push('<:ruby:604812470451699712> Ruby');
|
||||||
|
break;
|
||||||
|
case 'rs':
|
||||||
|
langs.push('<:Rust:703450901960196206> Rust');
|
||||||
|
break;
|
||||||
|
case 'swift':
|
||||||
|
langs.push('<:Swift:703451096093294672> Swift');
|
||||||
|
break;
|
||||||
|
case 'ts':
|
||||||
|
langs.push('<:TypeScript:703451285789343774> TypeScript');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
embed.addField('Known Languages', langs.join(', '));
|
||||||
|
}
|
||||||
|
if (account?.additional?.operatingSystems.length > 0) {
|
||||||
|
const operatingSystems: string[] = [];
|
||||||
|
for (const os of account.additional.operatingSystems.sort((a, b) => a.localeCompare(b))) {
|
||||||
|
switch (os) {
|
||||||
|
case 'arch':
|
||||||
|
operatingSystems.push('<:arch:707694976523304960> Arch');
|
||||||
|
break;
|
||||||
|
case 'deb':
|
||||||
|
operatingSystems.push('<:debian:707695042617147589> Debian');
|
||||||
|
break;
|
||||||
|
case 'cent':
|
||||||
|
operatingSystems.push('<:centos:707702165816213525> CentOS');
|
||||||
|
break;
|
||||||
|
case 'fedora':
|
||||||
|
operatingSystems.push('<:fedora:707695073151680543> Fedora');
|
||||||
|
break;
|
||||||
|
case 'manjaro':
|
||||||
|
operatingSystems.push('<:manjaro:707701473680556062> Manjaro');
|
||||||
|
break;
|
||||||
|
case 'mdarwin':
|
||||||
|
operatingSystems.push('<:mac:707695427754917919> macOS');
|
||||||
|
break;
|
||||||
|
case 'redhat':
|
||||||
|
operatingSystems.push('<:redhat:707695102159749271> RedHat Enterprise Linux');
|
||||||
|
break;
|
||||||
|
case 'ubuntu':
|
||||||
|
operatingSystems.push('<:ubuntu:707695136888586300> Ubuntu');
|
||||||
|
break;
|
||||||
|
case 'win':
|
||||||
|
operatingSystems.push('<:windows10:707695160259248208> Windows');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
embed.addField('Used Operating Systems', operatingSystems.join(', '));
|
||||||
|
}
|
||||||
if (permissions.length > 0) {
|
if (permissions.length > 0) {
|
||||||
embed.addField('Permissions', permissions.join(', '));
|
embed.addField('Permissions', permissions.join(', '));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,17 @@
|
||||||
{
|
{
|
||||||
"name": "Matthew",
|
"name": "Matthew",
|
||||||
"id": "278620217221971968",
|
"id": "278620217221971968",
|
||||||
"title": "Marshal General of Engineering",
|
"title": "Board of Directors",
|
||||||
"dept": "Faculty Marshals",
|
|
||||||
"emailAddress": "matthew@staff.libraryofcode.org",
|
"emailAddress": "matthew@staff.libraryofcode.org",
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/matthew",
|
"gitlab": "https://gitlab.libraryofcode.org/matthew",
|
||||||
"github": "https://github.com/matthew119427",
|
"github": "https://github.com/matthew119427",
|
||||||
"bio": "If you removed all the arteries, veins, & capillaries from a person’s body, and tied them end-to-end…the person will die. - Dr. Niel deGrasse Tyson",
|
"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"]
|
"acknowledgements": ["Maintainer & Lead Developer"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Joe",
|
"name": "Joe",
|
||||||
"id": "556969659531001858",
|
"id": "556969659531001858",
|
||||||
"title": "Marshal General of Community Relations",
|
"title": "Board of Directors",
|
||||||
"dept": "Faculty Marshals",
|
|
||||||
"emailAddress": "joe@staff.libraryofcode.org",
|
"emailAddress": "joe@staff.libraryofcode.org",
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/Joe",
|
"gitlab": "https://gitlab.libraryofcode.org/Joe",
|
||||||
"github": "https://github.com/sirdroolio",
|
"github": "https://github.com/sirdroolio",
|
||||||
|
@ -24,8 +22,7 @@
|
||||||
{
|
{
|
||||||
"name": "Bsian",
|
"name": "Bsian",
|
||||||
"id": "253600545972027394",
|
"id": "253600545972027394",
|
||||||
"title": "Assistant Marshal General of Engineering",
|
"title": "Board of Directors",
|
||||||
"dept": "Faculty Marshals",
|
|
||||||
"emailAddress": "bsian@staff.libraryofcode.org",
|
"emailAddress": "bsian@staff.libraryofcode.org",
|
||||||
"bio": "I also like trains",
|
"bio": "I also like trains",
|
||||||
"acknowledgements": ["Maintainer & Assistant Lead Developer"]
|
"acknowledgements": ["Maintainer & Assistant Lead Developer"]
|
||||||
|
@ -33,23 +30,20 @@
|
||||||
{
|
{
|
||||||
"name": "NightRaven",
|
"name": "NightRaven",
|
||||||
"id": "239261547959025665",
|
"id": "239261547959025665",
|
||||||
"title": "Assistant Marshal General of Community Relations",
|
"title": "Board of Directors",
|
||||||
"dept": "Faculty Marshals",
|
|
||||||
"emailAddress": "nightraven@staff.libraryofcode.org",
|
"emailAddress": "nightraven@staff.libraryofcode.org",
|
||||||
"bio": "I like trains"
|
"bio": "I like trains"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Midori",
|
"name": "Midori",
|
||||||
"id": "109122112643440640",
|
"id": "109122112643440640",
|
||||||
"title": "Assistant Marshal General of Community Relations",
|
"title": "Board of Directors",
|
||||||
"dept": "Faculty Marshals",
|
|
||||||
"emailAddress": "midori@staff.libraryofcode.org"
|
"emailAddress": "midori@staff.libraryofcode.org"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Unknown",
|
"name": "Unknown",
|
||||||
"id": "143414786913206272",
|
"id": "143414786913206272",
|
||||||
"title": "Staff Sergeant",
|
"title": "Board of Directors",
|
||||||
"dept": "Faculty Marshals",
|
|
||||||
"emailAddress": "unknown@staff.libraryofcode.org",
|
"emailAddress": "unknown@staff.libraryofcode.org",
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/unknown",
|
"gitlab": "https://gitlab.libraryofcode.org/unknown",
|
||||||
"bio": "im not a proffesional developer or anything, i just enjoy it as a hobby."
|
"bio": "im not a proffesional developer or anything, i just enjoy it as a hobby."
|
||||||
|
@ -57,53 +51,24 @@
|
||||||
{
|
{
|
||||||
"name": "TheSkele27",
|
"name": "TheSkele27",
|
||||||
"id": "213632190557192192",
|
"id": "213632190557192192",
|
||||||
"title": "Community Advisor",
|
"title": "Board of Directors",
|
||||||
"dept": "Faculty Marshals",
|
|
||||||
"emailAddress": "theskele27@staff.libraryofcode.org",
|
"emailAddress": "theskele27@staff.libraryofcode.org",
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/TheSkele27",
|
"gitlab": "https://gitlab.libraryofcode.org/TheSkele27",
|
||||||
"github": "https://github.com/TheSkele27",
|
"github": "https://github.com/TheSkele27",
|
||||||
"bio": "Is water wet?"
|
"bio": "Is water wet?"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Aikaterna",
|
"name": "Catbirby",
|
||||||
"id": "154497072148643840",
|
"id": "131953641371205632",
|
||||||
"title": "Sheriff",
|
"title": "Supervisor",
|
||||||
"dept": "Staff Team"
|
"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": "Boss",
|
|
||||||
"id": "344954369285947392",
|
|
||||||
"title": "Sheriff",
|
|
||||||
"dept": "Staff Team",
|
|
||||||
"emailAddress": "boss@staff.libraryofcode.org",
|
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/Boss",
|
|
||||||
"bio": "I can’t find a bio for user \"boss\""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Besero",
|
|
||||||
"id": "283318906024886272",
|
|
||||||
"title": "Associate",
|
|
||||||
"dept": "Staff Team",
|
|
||||||
"emailAddress": "besero@staff.libraryofcode.org",
|
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/besero_gg",
|
|
||||||
"github": "https://github.com/kledi-harding",
|
|
||||||
"bio": "Just looking for some fun. I like going on long walks in the park. No guys",
|
|
||||||
"acknowledgements": ["Graphic Designer"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CoalSephos",
|
|
||||||
"id": "155698776512790528",
|
|
||||||
"title": "Associate",
|
|
||||||
"dept": "Staff Team",
|
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/CoalSephos",
|
|
||||||
"github": "https://github.com/CoalSephos",
|
|
||||||
"bio": "[Tastes like chicken?]"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "D3XTER",
|
"name": "D3XTER",
|
||||||
"id": "468009964263178262",
|
"id": "468009964263178262",
|
||||||
"title": "Associate",
|
"title": "Core Team",
|
||||||
"dept": "Staff Team",
|
|
||||||
"emailAddress": "dexter@staff.libraryofcode.org",
|
"emailAddress": "dexter@staff.libraryofcode.org",
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/D3XTER",
|
"gitlab": "https://gitlab.libraryofcode.org/D3XTER",
|
||||||
"bio": "Hi I'm D3XTER how are ya?"
|
"bio": "Hi I'm D3XTER how are ya?"
|
||||||
|
@ -111,8 +76,7 @@
|
||||||
{
|
{
|
||||||
"name": "DedShotTM",
|
"name": "DedShotTM",
|
||||||
"id": "402154763363418142",
|
"id": "402154763363418142",
|
||||||
"title": "Associate",
|
"title": "Technician & Moderator",
|
||||||
"dept": "Staff Team",
|
|
||||||
"emailAddress": "dedshot@staff.libraryofcode.org",
|
"emailAddress": "dedshot@staff.libraryofcode.org",
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/DedShotTM",
|
"gitlab": "https://gitlab.libraryofcode.org/DedShotTM",
|
||||||
"github": "https://github.com/DedShotTM",
|
"github": "https://github.com/DedShotTM",
|
||||||
|
@ -122,8 +86,7 @@
|
||||||
{
|
{
|
||||||
"name": "EdgyBoi2414",
|
"name": "EdgyBoi2414",
|
||||||
"id": "397432516010835970",
|
"id": "397432516010835970",
|
||||||
"title": "Webmaster",
|
"title": "Core Team",
|
||||||
"dept": "Staff Team",
|
|
||||||
"emailAddress": "edgyboi2414@gmail.com",
|
"emailAddress": "edgyboi2414@gmail.com",
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/EdgyBoi2414",
|
"gitlab": "https://gitlab.libraryofcode.org/EdgyBoi2414",
|
||||||
"github": "https://github.com/EdgyBoi2414",
|
"github": "https://github.com/EdgyBoi2414",
|
||||||
|
@ -132,18 +95,23 @@
|
||||||
{
|
{
|
||||||
"name": "Hector",
|
"name": "Hector",
|
||||||
"id": "377781496292835339",
|
"id": "377781496292835339",
|
||||||
"title": "Associate",
|
"title": "Core Team",
|
||||||
"dept": "Staff Team",
|
|
||||||
"emailAddress": "hector@staff.libraryofcode.org",
|
"emailAddress": "hector@staff.libraryofcode.org",
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/Hector",
|
"gitlab": "https://gitlab.libraryofcode.org/Hector",
|
||||||
"github": "https://github.com/Hector6704",
|
"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!"
|
"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": "Realitus",
|
||||||
|
"id": "156450671338586112",
|
||||||
|
"title": "Associate",
|
||||||
|
"github": "https://github.com/Realitus",
|
||||||
|
"bio": "A hobbyist software developer with some rather strange ideas, and even stranger implementations."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "KhaaZ",
|
"name": "KhaaZ",
|
||||||
"id": "179908288337412096",
|
"id": "179908288337412096",
|
||||||
"title": "Associate",
|
"title": "Core Team",
|
||||||
"dept": "Staff Team",
|
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/KhaaZ",
|
"gitlab": "https://gitlab.libraryofcode.org/KhaaZ",
|
||||||
"github": "https://github.com/Khaazz",
|
"github": "https://github.com/Khaazz",
|
||||||
"bio": "I baguette for a living and eat code for breakfast."
|
"bio": "I baguette for a living and eat code for breakfast."
|
||||||
|
@ -151,9 +119,20 @@
|
||||||
{
|
{
|
||||||
"name": "Ryan",
|
"name": "Ryan",
|
||||||
"id": "186679073764802560",
|
"id": "186679073764802560",
|
||||||
|
"title": "Associate",
|
||||||
|
"emailAddress": "wbdvryan@staff.libraryofcode.org",
|
||||||
"gitlab": "https://gitlab.libraryofcode.org/plainRyan",
|
"gitlab": "https://gitlab.libraryofcode.org/plainRyan",
|
||||||
|
"bio": "Experiment, learn, share, repeat.",
|
||||||
"acknowledgements": ["Contributor"]
|
"acknowledgements": ["Contributor"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Zloth",
|
||||||
|
"id": "382368885267234816",
|
||||||
|
"title": "Associate",
|
||||||
|
"emailAddress": "zloth@staff.libraryofcode.org",
|
||||||
|
"github": "https://github.com/gavintjhxx",
|
||||||
|
"bio": "Wake up. Eat. Code. Sleep. Loop()"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Null",
|
"name": "Null",
|
||||||
"id": "323673862971588609",
|
"id": "323673862971588609",
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
/* eslint-disable no-useless-return */
|
/* eslint-disable no-useless-return */
|
||||||
import { Message, TextChannel, NewsChannel } from 'eris';
|
import { Message, TextChannel, NewsChannel } from 'eris';
|
||||||
import { Client } from '../class';
|
import { Client, Event } from '../class';
|
||||||
|
|
||||||
export default class {
|
export default class CommandHandler extends Event {
|
||||||
public client: Client;
|
public client: Client;
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.client = client;
|
super(client);
|
||||||
|
this.event = 'messageCreate';
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run(message: Message) {
|
public async run(message: Message) {
|
||||||
|
@ -19,7 +20,10 @@ export default class {
|
||||||
if (resolved.cmd.guildOnly && !(message.channel instanceof TextChannel || message.channel instanceof NewsChannel)) 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.enabled) { message.channel.createMessage(`***${this.client.util.emojis.ERROR} This command has been disabled***`); return; }
|
||||||
if (!resolved.cmd.checkPermissions(message.member)) return;
|
if (!resolved.cmd.checkPermissions(message.member)) return;
|
||||||
this.client.util.signale.info(`User '${message.author.username}#${message.author.discriminator}' ran command '${resolved.cmd.name}' in '${message.channel.id}'.`);
|
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);
|
await resolved.cmd.run(message, resolved.args);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.client.util.handleError(err, message);
|
this.client.util.handleError(err, message);
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as CommandHandler } from './CommandHandler';
|
||||||
|
export { default as ready } from './ready';
|
|
@ -1,10 +1,11 @@
|
||||||
import { Client } from '../class';
|
import { Client, Event } from '../class';
|
||||||
|
|
||||||
export default class {
|
export default class Ready extends Event {
|
||||||
public client: Client;
|
public client: Client;
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.client = client;
|
super(client);
|
||||||
|
this.event = 'ready';
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run() {
|
public async run() {
|
||||||
|
|
|
@ -2,10 +2,10 @@ import { Client } from '../class';
|
||||||
|
|
||||||
let interval: NodeJS.Timeout;
|
let interval: NodeJS.Timeout;
|
||||||
|
|
||||||
export default function checkLock(client: Client) {
|
export default function checkLock(client: Client): NodeJS.Timeout {
|
||||||
interval = setInterval(async () => {
|
interval = setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
const moderations = await client.db.moderation.find();
|
const moderations = await client.db.Moderation.find();
|
||||||
moderations.forEach(async (moderation) => {
|
moderations.forEach(async (moderation) => {
|
||||||
if (!moderation.expiration) return;
|
if (!moderation.expiration) return;
|
||||||
if (moderation.expiration.processed) return;
|
if (moderation.expiration.processed) return;
|
||||||
|
|
|
@ -0,0 +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;
|
||||||
|
}
|
|
@ -1,3 +1,6 @@
|
||||||
|
/* DM Ramirez with the code below to claim 500 free Rubies!
|
||||||
|
d2c3d8e14b
|
||||||
|
*/
|
||||||
import { parse } from 'yaml';
|
import { parse } from 'yaml';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { Client } from './class';
|
import { Client } from './class';
|
||||||
|
|
|
@ -0,0 +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);
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { Document, Schema, model } from 'mongoose';
|
||||||
|
|
||||||
|
export interface RedirectInterface extends Document {
|
||||||
|
key: string,
|
||||||
|
to: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RedirectRaw {
|
||||||
|
key: string,
|
||||||
|
to: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const Redirect: Schema = new Schema({
|
||||||
|
key: String,
|
||||||
|
to: String,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default model<RedirectInterface>('Redirect', Redirect);
|
|
@ -1 +1,3 @@
|
||||||
|
export { default as Member, MemberInterface } from './Member';
|
||||||
export { default as Moderation, ModerationInterface } from './Moderation';
|
export { default as Moderation, ModerationInterface } from './Moderation';
|
||||||
|
export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect';
|
||||||
|
|
Loading…
Reference in New Issue