Added discord.js docs command #24

Merged
DedShotTM merged 58 commits from djs into dev 2020-05-12 15:48:56 -04:00
22 changed files with 547 additions and 14 deletions

2
.gitignore vendored
View File

@ -1,7 +1,7 @@
# Package Management & Libraries # Package Management & Libraries
node_modules node_modules
yarn.lock yarn.lock
package-json.lock package-lock.json
# Configuration Files # Configuration Files
config.yaml config.yaml

View File

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

View File

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

View File

@ -3,6 +3,9 @@
"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",
@ -23,6 +26,7 @@
"dependencies": { "dependencies": {
"axios": "^0.19.2", "axios": "^0.19.2",
"eris": "bsian03/eris#bsian", "eris": "bsian03/eris#bsian",
"eris-pagination": "bsian03/eris-pagination#dev",
"moment": "^2.24.0", "moment": "^2.24.0",
"mongoose": "^5.9.9", "mongoose": "^5.9.9",
"signale": "^1.4.0", "signale": "^1.4.0",

View File

@ -2,7 +2,7 @@ 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 } from '.';
import { Moderation, ModerationInterface } from '../models'; import { Member, MemberInterface, Moderation, ModerationInterface } from '../models';
export default class Client extends eris.Client { export default class Client extends eris.Client {
public config: { token: string, prefix: string, guildID: string, mongoDB: string }; public config: { token: string, prefix: string, guildID: string, mongoDB: string };
@ -13,14 +13,14 @@ export default class Client extends eris.Client {
public util: Util; public util: Util;
public db: { moderation: mongoose.Model<ModerationInterface> }; public db: { member: mongoose.Model<MemberInterface>, moderation: mongoose.Model<ModerationInterface> };
// eslint-disable-next-line @typescript-eslint/no-useless-constructor // eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor(token: string, options?: eris.ClientOptions) { constructor(token: string, options?: eris.ClientOptions) {
super(token, options); super(token, options);
this.commands = new Collection<Command>(); this.commands = new Collection<Command>();
this.intervals = new Collection<NodeJS.Timeout>(); this.intervals = new Collection<NodeJS.Timeout>();
this.db = { moderation: Moderation }; this.db = { member: Member, moderation: Moderation };
} }
public async loadDatabase() { public async loadDatabase() {

View File

@ -28,9 +28,9 @@ export default class Command {
* - **0:** Everyone * - **0:** Everyone
* - **1:** Associates+ * - **1:** Associates+
* - **2:** Core Team+ * - **2:** Core Team+
* - **3:** Moderators, Supervisor, Board of Directors * - **3:** Moderators, Supervisor, & Board of Directors
* - **4:** Technicians, Supervisor, Board of Directors * - **4:** Technicians, Supervisor, & Board of Directors
* - **5:** Moderators, Technicians, Supervisor, Board of Directors * - **5:** Moderators, Technicians, Supervisor, & Board of Directors
* - **6:** Supervisor+ * - **6:** Supervisor+
* - **7:** Board of Directors * - **7:** Board of Directors
*/ */
@ -68,8 +68,10 @@ export default class Command {
case 4: case 4:
return member.roles.some((r) => ['701454780828221450', '701454855952138300', '662163685439045632'].includes(r)); return member.roles.some((r) => ['701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
case 5: case 5:
return member.roles.some((r) => ['701454855952138300', '662163685439045632'].includes(r)); return member.roles.some((r) => ['455972169449734144', '701454780828221450', '701454855952138300', '662163685439045632'].includes(r));
case 6: case 6:
return member.roles.some((r) => ['701454855952138300', '662163685439045632'].includes(r));
case 7:
return member.roles.includes('662163685439045632'); return member.roles.includes('662163685439045632');
default: default:
return false; return false;

View File

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

View File

@ -118,6 +118,16 @@ export default class Util {
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 hex = int.toString(16); const hex = int.toString(16);
return '#000000'.substring(0, 7 - hex.length) + hex; return '#000000'.substring(0, 7 - hex.length) + hex;

45
src/commands/additem.ts Normal file
View File

@ -0,0 +1,45 @@
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.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
return message.channel.createMessage({ embed });
}
if (['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) {
// eslint-disable-next-line new-cap
const newAccount = new this.client.db.member({
userID: message.member.id,
additional: {
langs: [args[0].split('-')[1]],
},
});
await newAccount.save();
return message.channel.createMessage(`***${this.client.util.emojis.SUCCESS} Added language code ${args[0]} to profile.***`);
}
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 language code.***`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -15,6 +15,7 @@ export default class Ban extends Command {
public async run(message: Message, args: string[]) { public async run(message: Message, args: string[]) {
try { try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
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) {

37
src/commands/delitem.ts Normal file
View File

@ -0,0 +1,37 @@
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.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
return message.channel.createMessage({ embed });
}
if (['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]} to profile.***`);
}
return message.channel.createMessage(`***${this.client.util.emojis.ERROR} Invalid language code.***`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

53
src/commands/djs.ts Normal file
View File

@ -0,0 +1,53 @@
import { Message } from 'eris';
import axios 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]);
let res;
try {
res = await axios.get(`https://djsdocs.sorta.moe/v2/embed?src=master&q=${args[0]}`);
} catch (err) {
this.error(message.channel, 'Please try again later, something unexpected happened.');
return this.client.util.handleError(err, message, this);
}
const { data } = res;
if (!data) return this.error(message.channel, 'Could not find information. Try something else.');
const name: string = data.author?.name || '';
const icon_url: string = data.author?.icon_url || '';
const author_url: string = data.author?.url || '';
const description: string = data.description || 'None';
const title: string = data.title || '';
const embed = new RichEmbed();
embed.setAuthor(name, icon_url, author_url);
embed.setColor(0x2296f3);
embed.setTitle(title);
embed.setDescription(description);
if (data.fields !== undefined && data.fields.length > 0) {
data.fields.forEach((field) => {
embed.addField(field.name, field.value);
});
}
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

116
src/commands/help.ts Normal file
View File

@ -0,0 +1,116 @@
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;
}
// eslint-disable-next-line consistent-return
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) {
this.client.util.handleError(err, message, this);
}
}
}

34
src/commands/info.ts Normal file
View File

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

38
src/commands/kick.ts Normal file
View File

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

65
src/commands/npm.ts Normal file
View File

@ -0,0 +1,65 @@
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';
// eslint-disable-next-line no-prototype-builtins
if (version !== 'Unknown' && data.versions[version].hasOwnProperty('dependencies') && 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);
}
}
}

View File

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

View File

@ -14,6 +14,7 @@ export default class Unban extends Command {
public async run(message: Message, args: string[]) { public async run(message: Message, args: string[]) {
try { try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
let user: User; let user: User;
try { try {
user = await this.client.getRESTUser(args[0]); user = await this.client.getRESTUser(args[0]);

View File

@ -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,61 @@ 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 (permissions.length > 0) { if (permissions.length > 0) {
embed.addField('Permissions', permissions.join(', ')); embed.addField('Permissions', permissions.join(', '));
} }

View File

@ -6,7 +6,7 @@
"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 persons body, and tied them end-to-end…the person will die. - Dr. Niel deGrasse Tyson", "bio": "so baby come light me up, and baby 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"]
}, },
{ {
@ -57,6 +57,14 @@
"github": "https://github.com/TheSkele27", "github": "https://github.com/TheSkele27",
"bio": "Is water wet?" "bio": "Is water wet?"
}, },
{
"name": "Catbirby",
"id": "131953641371205632",
"title": "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": "Besero", "name": "Besero",
"id": "283318906024886272", "id": "283318906024886272",
@ -97,7 +105,7 @@
{ {
"name": "Hector", "name": "Hector",
"id": "377781496292835339", "id": "377781496292835339",
"title": "Associate", "title": "Core 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",
@ -121,9 +129,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": "Undergoing education, codes as a hobby"
},
{ {
"name": "Null", "name": "Null",
"id": "323673862971588609", "id": "323673862971588609",

17
src/models/Member.ts Normal file
View File

@ -0,0 +1,17 @@
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'],
},
}
const Member: Schema = new Schema({
userID: String,
additional: {
langs: Array,
},
});
export default model<MemberInterface>('Member', Member);

View File

@ -1 +1,2 @@
export { default as Member, MemberInterface } from './Member';
export { default as Moderation, ModerationInterface } from './Moderation'; export { default as Moderation, ModerationInterface } from './Moderation';