Merge pull request 'master' (#1) from engineering/crra:master into master
Reviewed-on: pax/crra#1
commit
c40f26c640
|
@ -15,6 +15,34 @@ export type MemberAdditionalAcknowledgement =
|
||||||
"Voting Seat Member of the Board of Governors" |
|
"Voting Seat Member of the Board of Governors" |
|
||||||
string;
|
string;
|
||||||
|
|
||||||
|
export const MemberGuildRoleIDMap = {
|
||||||
|
// Chair/Vice Chair of the Board of Governors
|
||||||
|
CHAIR_OR_VICE_OF_BOARD: "608394038466445320",
|
||||||
|
// Management
|
||||||
|
MANAGEMENT: "1077646568091570236",
|
||||||
|
// Director of Operations
|
||||||
|
DIRECTOR_OF_OPERATIONS: "1077647072163020840",
|
||||||
|
// Director of Engineering
|
||||||
|
DIRECTOR_OF_ENGINEERING: "1077646956890951690",
|
||||||
|
// Board of Governors
|
||||||
|
BOARD_OF_GOVERNORS: "662163685439045632",
|
||||||
|
// Project Manager
|
||||||
|
PROJECT_MANAGER: "1077647157928132711",
|
||||||
|
// Services Manager
|
||||||
|
SERVICES_MANAGER: "1077647467056742482",
|
||||||
|
// Staff
|
||||||
|
STAFF: "446104438969466890",
|
||||||
|
// Technician
|
||||||
|
TECHNICIAN: "701454780828221450",
|
||||||
|
// Moderator
|
||||||
|
MODERATOR: "455972169449734144",
|
||||||
|
// Core Team
|
||||||
|
CORE_TEAM: "453689940140883988",
|
||||||
|
// Intern (Training)
|
||||||
|
INTERN: "701481967149121627",
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// enum for the used programming languages in whois information
|
// enum for the used programming languages in whois information
|
||||||
export enum MemberUsedLanguages {
|
export enum MemberUsedLanguages {
|
||||||
ASM = "lang-asm",
|
ASM = "lang-asm",
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
import DiscordInteractionCommand from "../../util/DiscordInteractionCommand";
|
||||||
|
import { ChatInputCommandInteraction } from "discord.js";
|
||||||
|
import { inspect } from "util";
|
||||||
|
import { discordBotToken } from "../../config.json";
|
||||||
|
|
||||||
|
export default class Eval extends DiscordInteractionCommand {
|
||||||
|
// This is a list of IDs that are allowed to use this command.
|
||||||
|
private listOfAllowedIDs: string[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super("eval", "Executes arbitrary JS code and returns the output.");
|
||||||
|
// this option is required and is a string of JavaScript code to execute
|
||||||
|
this.builder.addStringOption(option => option.setName("code").setDescription("The code to execute.").setRequired(true));
|
||||||
|
// this option is optional and is a boolean that determines whether the code should be run as an async function
|
||||||
|
this.builder.addBooleanOption(option => option.setName("async").setDescription("Whether to run the code as an async function.").setRequired(false));
|
||||||
|
// this option is optional and is an integer that determines the depth of the eval inspection
|
||||||
|
this.builder.addIntegerOption(option => option.setName("depth").setDescription("The depth of the inspection.").setRequired(false));
|
||||||
|
|
||||||
|
this.listOfAllowedIDs = [
|
||||||
|
"278620217221971968", // Matthew
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public async execute(interaction: ChatInputCommandInteraction) {
|
||||||
|
// @ts-ignore
|
||||||
|
let evalString = interaction.options.getString("code").trim();
|
||||||
|
if (evalString == null) return interaction.reply({ content: "You must provide code to evaluate.", ephemeral: true });
|
||||||
|
if (!this.listOfAllowedIDs.includes(interaction.user.id)) return interaction.reply({ content: "Permission denied.", ephemeral: true });
|
||||||
|
await interaction.deferReply({ephemeral: true});
|
||||||
|
|
||||||
|
// set scoped variables to be able to access over eval
|
||||||
|
const guild = interaction.guild || interaction.client.guilds.cache.get(this.GUILD_ID);
|
||||||
|
// the output of eval() is stored in evaled
|
||||||
|
let evaled: any;
|
||||||
|
let depth: number | null = 0;
|
||||||
|
// if depth option exists, set the depth variable to the value provided by the user
|
||||||
|
if (interaction.options.getInteger("depth") != null) {
|
||||||
|
depth = interaction.options.getInteger("depth");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if command specified as async, swap the evalString in an async function
|
||||||
|
if (interaction.options.getBoolean("async")) {
|
||||||
|
evalString = `(async () => { ${evalString} })()`;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line no-eval
|
||||||
|
evaled = await eval(evalString);
|
||||||
|
if (typeof evaled !== 'string') {
|
||||||
|
evaled = inspect(evaled, { depth });
|
||||||
|
}
|
||||||
|
if (evaled === undefined) {
|
||||||
|
evaled = 'undefined';
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// @ts-ignore
|
||||||
|
evaled = error.stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaces all instances of the bot token with [REDACTED] in output
|
||||||
|
evaled = evaled.replace(new RegExp(discordBotToken, 'gi'), '[REDACTED]');
|
||||||
|
|
||||||
|
// TODO: Figure this out.
|
||||||
|
/*const display = this.client.util.splitString(evaled, 1975);
|
||||||
|
if (display[5]) {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.post('https://snippets.cloud.libraryofcode.org/documents', display.join(''));
|
||||||
|
return this.success(ctx.message.channel, `Your evaluation evaled can be found on https://snippets.cloud.libraryofcode.org/${data.key}`);
|
||||||
|
} catch (error) {
|
||||||
|
return this.error(ctx.message.channel, `${error}`);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
await interaction.editReply({content: `\`\`\`js\n${evaled}\n\`\`\``})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
import DiscordInteractionCommand from "../../util/DiscordInteractionCommand";
|
import DiscordInteractionCommand from "../../util/DiscordInteractionCommand";
|
||||||
import { MemberModel } from "../../database/Member";
|
import { MemberModel } from "../../database/Member";
|
||||||
import Partner, {PartnerCommissionType, PartnerDepartment, PartnerModel, PartnerRoleType} from "../../database/Partner";
|
import Partner, { PartnerCommissionType, PartnerDepartment, PartnerModel, PartnerRoleType } from "../../database/Partner";
|
||||||
import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, EmbedBuilder, GuildMember } from "discord.js";
|
||||||
import MemberUtil from "../../util/MemberUtil";
|
import MemberUtil from "../../util/MemberUtil";
|
||||||
|
import EmojiConfig from "../../util/EmojiConfig"
|
||||||
|
|
||||||
export default class Whois extends DiscordInteractionCommand {
|
export default class Whois extends DiscordInteractionCommand {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -26,14 +27,14 @@ export default class Whois extends DiscordInteractionCommand {
|
||||||
// if the partner exists, set the iconURL to the organizational logo
|
// if the partner exists, set the iconURL to the organizational logo
|
||||||
const formattedName = MemberUtil.formatName(guildMember, partner);
|
const formattedName = MemberUtil.formatName(guildMember, partner);
|
||||||
embed.setAuthor({ name: formattedName.text, iconURL: formattedName.iconURL });
|
embed.setAuthor({ name: formattedName.text, iconURL: formattedName.iconURL });
|
||||||
// set the title to the partner's title if applicable
|
|
||||||
if (partner?.title) embed.setTitle(partner.title);
|
|
||||||
// set the thumbnail to the user's avatar
|
// set the thumbnail to the user's avatar
|
||||||
embed.setThumbnail(guildMember.user.displayAvatarURL());
|
embed.setThumbnail(guildMember.user.displayAvatarURL());
|
||||||
// initialize the description string
|
// initialize the description string
|
||||||
let embedDescription = '';
|
let embedDescription = '';
|
||||||
if (partner) {
|
if (partner) {
|
||||||
embedDescription += "__**Partner Information**__\n";
|
// set the title to the partner's title if applicable
|
||||||
|
if (partner.title) embedDescription += `## __${EmojiConfig.LOC} ${partner.title}__\n`;
|
||||||
|
embedDescription += "### Partner Information\n";
|
||||||
if (partner.emailAddress) embedDescription += `**Email Address**: ${partner.emailAddress}\n`;
|
if (partner.emailAddress) embedDescription += `**Email Address**: ${partner.emailAddress}\n`;
|
||||||
switch (partner.department) {
|
switch (partner.department) {
|
||||||
case PartnerDepartment.ENGINEERING:
|
case PartnerDepartment.ENGINEERING:
|
||||||
|
@ -74,6 +75,27 @@ export default class Whois extends DiscordInteractionCommand {
|
||||||
}
|
}
|
||||||
embed.setColor(guildMember.displayColor);
|
embed.setColor(guildMember.displayColor);
|
||||||
if (embedDescription?.length > 0) embed.setDescription(embedDescription);
|
if (embedDescription?.length > 0) embed.setDescription(embedDescription);
|
||||||
|
// add status to embed
|
||||||
|
if (guildMember.presence?.status) { // TODO: this currently doesn't work for some reason
|
||||||
|
switch (guildMember.presence.status) {
|
||||||
|
case "online":
|
||||||
|
embed.addFields({ name: "Status", value: "Online", inline: true });
|
||||||
|
break;
|
||||||
|
case "idle":
|
||||||
|
embed.addFields({ name: "Status", value: "Idle", inline: true });
|
||||||
|
break;
|
||||||
|
case "dnd":
|
||||||
|
embed.addFields({ name: "Status", value: "Do Not Disturb", inline: true });
|
||||||
|
break;
|
||||||
|
case "offline" || "invisible":
|
||||||
|
embed.addFields({ name: "Status", value: "Online", inline: true });
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TODO: decide what placeholder we should use for values that fall "out of range"
|
||||||
|
embed.addFields({ name: "Status", value: "", inline: true });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
embed.setFooter({ text: `Discord ID: ${guildMember.id}${databaseMember ? `Internal ID: ${databaseMember?._id}` : ''}` });
|
embed.setFooter({ text: `Discord ID: ${guildMember.id}${databaseMember ? `Internal ID: ${databaseMember?._id}` : ''}` });
|
||||||
|
|
||||||
return await interaction.editReply({ embeds: [embed] });
|
return await interaction.editReply({ embeds: [embed] });
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
export { default as Eval } from "./Eval";
|
||||||
export { default as Partner } from "./Partner";
|
export { default as Partner } from "./Partner";
|
||||||
export { default as Ping } from "./Ping";
|
export { default as Ping } from "./Ping";
|
||||||
export { default as Whois } from "./Whois";
|
export { default as Whois } from "./Whois";
|
||||||
|
|
|
@ -13,8 +13,9 @@ export default class InteractionCreate extends DiscordEvent {
|
||||||
if (!command) return console.error(`No command matching ${interaction.commandName} was found.`);
|
if (!command) return console.error(`No command matching ${interaction.commandName} was found.`);
|
||||||
try {
|
try {
|
||||||
await command.execute(interaction);
|
await command.execute(interaction);
|
||||||
|
console.info(`[Info - Discord] Command '${interaction.commandName}' executed by '${interaction.user.username}'`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(`Error executing command '${interaction.commandName}': by '${interaction.user.username}'\n${error}`);
|
||||||
if (interaction.replied || interaction.deferred) {
|
if (interaction.replied || interaction.deferred) {
|
||||||
await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true });
|
await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true });
|
||||||
} else {
|
} else {
|
||||||
|
|
3
index.ts
3
index.ts
|
@ -13,6 +13,7 @@ export const DiscordEvents: Collection<DiscordEvent> = new Collection();
|
||||||
// Instantiates a new Discord client
|
// Instantiates a new Discord client
|
||||||
const discordClient = new Client({
|
const discordClient = new Client({
|
||||||
intents: [
|
intents: [
|
||||||
|
GatewayIntentBits.DirectMessages,
|
||||||
GatewayIntentBits.GuildIntegrations,
|
GatewayIntentBits.GuildIntegrations,
|
||||||
GatewayIntentBits.GuildPresences,
|
GatewayIntentBits.GuildPresences,
|
||||||
GatewayIntentBits.GuildMessages,
|
GatewayIntentBits.GuildMessages,
|
||||||
|
@ -20,7 +21,7 @@ const discordClient = new Client({
|
||||||
GatewayIntentBits.GuildInvites,
|
GatewayIntentBits.GuildInvites,
|
||||||
GatewayIntentBits.GuildModeration,
|
GatewayIntentBits.GuildModeration,
|
||||||
],
|
],
|
||||||
partials: [ Partials.GuildMember, Partials.Message, Partials.User],
|
partials: [ Partials.GuildMember, Partials.Message, Partials.User, Partials.Channel, ],
|
||||||
});
|
});
|
||||||
const discordREST = new REST().setToken(discordBotToken);
|
const discordREST = new REST().setToken(discordBotToken);
|
||||||
// const stripeClient = new Stripe(stripeToken, { typescript: true });
|
// const stripeClient = new Stripe(stripeToken, { typescript: true });
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
export default class EmojiConfig {
|
||||||
|
public static LOC = "<:loc:607695848612167700>";
|
||||||
|
public static EMAIL = "<:email:699786452267040878>";
|
||||||
|
}
|
|
@ -61,25 +61,23 @@ export default class MemberUtil {
|
||||||
|
|
||||||
// TODO: comments and extended formatting
|
// TODO: comments and extended formatting
|
||||||
public static formatName(target: GuildMember | User, partner?: Partner | null): FormatNameOptions {
|
public static formatName(target: GuildMember | User, partner?: Partner | null): FormatNameOptions {
|
||||||
|
console.log(`[MemberUtil] Formatting name for ${target.displayName} at url ${target instanceof GuildMember ? target.user.displayAvatarURL() : target.displayAvatarURL()}`);
|
||||||
// if the role type is managerial, add a [k] to the end of the name
|
// if the role type is managerial, add a [k] to the end of the name
|
||||||
// if the partner exists, set the iconURL to the organizational logo
|
// if the partner exists, set the iconURL to the organizational logo
|
||||||
if (partner?.roleType == PartnerRoleType.MANAGERIAL) {
|
if (partner?.roleType == PartnerRoleType.MANAGERIAL) {
|
||||||
console.log(`[MemberUtil] Formatting name for ${target.displayName}`)
|
|
||||||
return {
|
return {
|
||||||
text: `${target.displayName} [k]`,
|
text: `${target.displayName} [k]`,
|
||||||
iconURL: "https://static.libraryofcode.org/library_of_code_redeg.png"
|
iconURL: target.displayAvatarURL(),
|
||||||
}
|
}
|
||||||
} else if (partner?.commissionType == PartnerCommissionType.CONTRACTUAL) { // if the commission type is contractual, add a [c] to the end of the name
|
} else if (partner?.commissionType == PartnerCommissionType.CONTRACTUAL) { // if the commission type is contractual, add a [c] to the end of the name
|
||||||
console.log(`[MemberUtil] Formatting name for ${target.displayName}`)
|
|
||||||
return {
|
return {
|
||||||
text: `${target.displayName} [c]`,
|
text: `${target.displayName} [c]`,
|
||||||
iconURL: "https://static.libraryofcode.org/library_of_code_redeg.png"
|
iconURL: target instanceof GuildMember ? target.user.displayAvatarURL() : target.displayAvatarURL(),
|
||||||
}
|
}
|
||||||
} else { // otherwise, just set the author to the member's display name
|
} else { // otherwise, just set the author to the member's display name
|
||||||
console.log(`[MemberUtil] Formatting name for ${target.displayName} at url ${target instanceof GuildMember ? target.user.displayAvatarURL() : target.displayAvatarURL()}`);
|
|
||||||
return {
|
return {
|
||||||
text: target.displayName,
|
text: target.displayName,
|
||||||
iconURL: target instanceof GuildMember ? target.user.displayAvatarURL() : target.displayAvatarURL()
|
iconURL: target instanceof GuildMember ? target.user.displayAvatarURL() : target.displayAvatarURL(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue