diff --git a/database/CommunityReport.ts b/database/CommunityReport.ts index 0b4588f..d5539e5 100644 --- a/database/CommunityReport.ts +++ b/database/CommunityReport.ts @@ -1,42 +1,46 @@ -import { prop, getModelForClass, Ref } from "@typegoose/typegoose" -import Member, { MemberAdditionalAcknowledgement, MemberUsedLanguages, MemberUsedOperatingSystems } from "./Member"; +import { prop, getModelForClass, Ref } from "@typegoose/typegoose"; +import Member, { + MemberAdditionalAcknowledgement, + MemberUsedLanguages, + MemberUsedOperatingSystems, +} from "./Member"; export enum GenerationMethod { - TIMER_INTERNAL, // generated by the internal cron-job timer automatically - INQUIRY_INTERNAL, // internal inquiry generated internally directly through the system. user checks their own inquiry, hard inquiry is performed by a staff member, etc. - INQUIRY_EXTERNAL, // external inquiry generated externally through the system via an external authorized request, such as via EDS + TIMER_INTERNAL, // generated by the internal cron-job timer automatically + INQUIRY_INTERNAL, // internal inquiry generated internally directly through the system. user checks their own inquiry, hard inquiry is performed by a staff member, etc. + INQUIRY_EXTERNAL, // external inquiry generated externally through the system via an external authorized request, such as via EDS } export interface AddtlScoreData { - activity: number; - roles: number; - moderation: number; - cloudServices: number; - misc: number; + activity: number; + roles: number; + moderation: number; + cloudServices: number; + misc: number; } /* TODO -* Comments -* Further attributes for class -* */ + * Comments + * Further attributes for class + * */ export default class CommunityReport { - @prop({ required: true, index: true, ref: () => Member }) - // the member on which this report was generated for - public member: Ref | undefined; + @prop({ required: true, index: true, ref: () => Member }) + // the member on which this report was generated for + public member: Ref | undefined; - @prop({ required: true }) - // the date in which this report was generated on - public date: Date | undefined; + @prop({ required: true }) + // the date in which this report was generated on + public date: Date | undefined; - @prop({ required: true }) - // the CommScore of the member specified - public score: number | undefined; + @prop({ required: true }) + // the CommScore of the member specified + public score: number | undefined; - @prop({ required: true }) - // the method in which this report was generated under - public generationMethod: GenerationMethod | undefined; + @prop({ required: true }) + // the method in which this report was generated under + public generationMethod: GenerationMethod | undefined; - @prop({ required: true }) - public additionalScoreData: AddtlScoreData | undefined; + @prop({ required: true }) + public additionalScoreData: AddtlScoreData | undefined; } diff --git a/database/HardInquiry.ts b/database/HardInquiry.ts index 015cbf6..19eb1d4 100644 --- a/database/HardInquiry.ts +++ b/database/HardInquiry.ts @@ -1,4 +1,4 @@ -import { prop, getModelForClass, Ref } from "@typegoose/typegoose" +import { prop, getModelForClass, Ref } from "@typegoose/typegoose"; import Inquiry from "./Inquiry"; /** @@ -6,6 +6,6 @@ import Inquiry from "./Inquiry"; * Structure is performed this way to have two separate collections for Hard and Soft inquiries. */ export default class HardInquiry extends Inquiry { - @prop({ required: true }) - public reason: string | undefined; + @prop({ required: true }) + public reason: string | undefined; } diff --git a/database/Inquiry.ts b/database/Inquiry.ts index 48054ba..b77b50a 100644 --- a/database/Inquiry.ts +++ b/database/Inquiry.ts @@ -1,6 +1,6 @@ -import { prop, getModelForClass, Ref } from "@typegoose/typegoose" +import { prop, getModelForClass, Ref } from "@typegoose/typegoose"; import Member from "./Member"; -import CommunityReport from "./CommunityReport" +import CommunityReport from "./CommunityReport"; /** * TODO: @@ -9,29 +9,28 @@ import CommunityReport from "./CommunityReport" * - Reason */ - export default abstract class Inquiry { - @prop({ required: true, unique: true }) - // the Inquiry Identifier (previously known as `iid`). this is an UUIDv4 string - public id: string | undefined; + @prop({ required: true, unique: true }) + // the Inquiry Identifier (previously known as `iid`). this is an UUIDv4 string + public id: string | undefined; - @prop({ required: true, index: true, ref: () => Member }) - // the member on which this inquiry was performed on - public member: Ref | undefined; + @prop({ required: true, index: true, ref: () => Member }) + // the member on which this inquiry was performed on + public member: Ref | undefined; - @prop({ required: true }) - // the date in which this inquiry was performed - public date: Date | undefined; + @prop({ required: true }) + // the date in which this inquiry was performed + public date: Date | undefined; - @prop({ required: true, ref: () => Member }) - // the reference to the member who initiated this inquiry or a string value representing the name of a system that initiated the inquiry - public initiatedBy: Ref | string | undefined; + @prop({ required: true, ref: () => Member }) + // the reference to the member who initiated this inquiry or a string value representing the name of a system that initiated the inquiry + public initiatedBy: Ref | string | undefined; - @prop({ required: true, ref: () => CommunityReport }) - // the report that was generated or fetched from this inquiry as of current date - public report: Ref | undefined; + @prop({ required: true, ref: () => CommunityReport }) + // the report that was generated or fetched from this inquiry as of current date + public report: Ref | undefined; - @prop() - // a reason for the inquiry, if applicable. this value is required for HardInquiry - public reason: string | "N/A" | undefined; + @prop() + // a reason for the inquiry, if applicable. this value is required for HardInquiry + public reason: string | "N/A" | undefined; } diff --git a/database/Member.ts b/database/Member.ts index 6ee67c1..fb7c4fd 100644 --- a/database/Member.ts +++ b/database/Member.ts @@ -1,88 +1,87 @@ -import { prop, getModelForClass } from "@typegoose/typegoose" +import { prop, getModelForClass } from "@typegoose/typegoose"; /* TODO -* Comments -* Further attributes for class -* */ + * Comments + * Further attributes for class + * */ export interface SharedMemberAttributes { - discordID: string | undefined; + discordID: string | undefined; } export type MemberAdditionalAcknowledgement = - "Chair of the Board of Governors" | - "Vice Chair of the Board of Governors" | - "Voting Seat Member of the Board of Governors" | - string; + | "Chair of the Board of Governors" + | "Vice Chair of the Board of Governors" + | "Voting Seat Member of the Board of Governors" + | 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", - -} + // 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 export enum MemberUsedLanguages { - ASM = "lang-asm", - CFAM = "lang-cfam", - CSHARP = "lang-csharp", - GO = "lang-go", - JAVA = "lang-java", - JS = "lang-js", - KT = "lang-kt", - PY = "lang-py", - RB = "lang-rb", - RS = "lang-rs", - SWIFT = "lang-swift", - TS = "lang-ts" + ASM = "lang-asm", + CFAM = "lang-cfam", + CSHARP = "lang-csharp", + GO = "lang-go", + JAVA = "lang-java", + JS = "lang-js", + KT = "lang-kt", + PY = "lang-py", + RB = "lang-rb", + RS = "lang-rs", + SWIFT = "lang-swift", + TS = "lang-ts", } // enum for the used operating systems in the whois information export enum MemberUsedOperatingSystems { - ARCH = "os-arch", - DEB = "os-deb", - CENT = "os-cent", - FEDORA = "os-fedora", - MDARWIN = "os-mdarwin", - MANJARO = "os-manjaro", - REDHAT = "os-redhat", - UBUNTU = "os-ubuntu", - WIN = "os-win" + ARCH = "os-arch", + DEB = "os-deb", + CENT = "os-cent", + FEDORA = "os-fedora", + MDARWIN = "os-mdarwin", + MANJARO = "os-manjaro", + REDHAT = "os-redhat", + UBUNTU = "os-ubuntu", + WIN = "os-win", } export default class Member implements SharedMemberAttributes { - @prop({ required: true, unique: true }) - public discordID: string | undefined; + @prop({ required: true, unique: true }) + public discordID: string | undefined; - @prop() - public usedOperatingSystems: MemberUsedOperatingSystems[] | undefined; + @prop() + public usedOperatingSystems: MemberUsedOperatingSystems[] | undefined; - @prop() - public usedLanguages: MemberUsedLanguages[] | undefined; + @prop() + public usedLanguages: MemberUsedLanguages[] | undefined; - @prop() - public additionalAcknowledgement: MemberAdditionalAcknowledgement[] | undefined; + @prop() + public additionalAcknowledgement: MemberAdditionalAcknowledgement[] | undefined; } export const MemberModel = getModelForClass(Member); diff --git a/database/Partner.ts b/database/Partner.ts index b55e16c..f5022f7 100644 --- a/database/Partner.ts +++ b/database/Partner.ts @@ -2,72 +2,71 @@ import { prop, getModelForClass } from "@typegoose/typegoose"; import Member from "./Member"; /* TODO -* Comments -* Further attributes for class -* */ + * Comments + * Further attributes for class + * */ import { SharedMemberAttributes } from "./Member"; export type PartnerTitle = - "Director of Engineering" | - "Director of Operations" | - "Deputy Director of Engineering" | - "Deputy Director of Operations" | - "Services Manager" | - "Project Manager" | - "Engineering Core Partner" | - "Operations Core Partner" | - "Community Moderator" | - "Technician" | - string; - + | "Director of Engineering" + | "Director of Operations" + | "Deputy Director of Engineering" + | "Deputy Director of Operations" + | "Services Manager" + | "Project Manager" + | "Engineering Core Partner" + | "Operations Core Partner" + | "Community Moderator" + | "Technician" + | string; export enum PartnerDepartment { - INDEPENDENT_AGENCY, - ENGINEERING, // Department of Engineering - OPERATIONS // Department of Operations + INDEPENDENT_AGENCY, + ENGINEERING, // Department of Engineering + OPERATIONS, // Department of Operations } export enum PartnerRoleType { - MANAGERIAL, - NONMANAGERIAL, + MANAGERIAL, + NONMANAGERIAL, } export enum PartnerCommissionType { - TENURE, - PROVISIONAL, - CONTRACTUAL, - ACTING, - INTERIM, - TRIAL, + TENURE, + PROVISIONAL, + CONTRACTUAL, + ACTING, + INTERIM, + TRIAL, } export default class Partner implements SharedMemberAttributes { - @prop({ required: true, unique: true }) - public discordID: string | undefined; + @prop({ required: true, unique: true }) + public discordID: string | undefined; - @prop() - public emailAddress: string | undefined; + @prop() + public emailAddress: string | undefined; - @prop({ required: true }) - public roleType: PartnerRoleType | undefined; + @prop({ required: true }) + public roleType: PartnerRoleType | undefined; - @prop({ required: true }) - public commissionType: PartnerCommissionType | undefined; + @prop({ required: true }) + public commissionType: PartnerCommissionType | undefined; - @prop({ required: true }) - public department: PartnerDepartment | undefined; + @prop({ required: true }) + public department: PartnerDepartment | undefined; - @prop({ required: true }) - public title: PartnerTitle | "Partner" | undefined; + @prop({ required: true }) + public title: PartnerTitle | "Partner" | undefined; - @prop() - // - public directReport: Partner | string | undefined; + @prop() + // + public directReport: Partner | string | undefined; - @prop() - // this field dictates if the partner is able to perform developer commands, such as "eval" - public canPerformDevCommands: boolean | undefined; + @prop() + // this field dictates if the partner is able to perform developer commands, such as "eval" + public canPerformDevCommands: boolean | undefined; } export const PartnerModel = getModelForClass(Partner); diff --git a/database/Vendor.ts b/database/Vendor.ts index efa19cd..4dc049d 100644 --- a/database/Vendor.ts +++ b/database/Vendor.ts @@ -1,15 +1,15 @@ -import { prop } from '@typegoose/typegoose'; +import { prop } from "@typegoose/typegoose"; // This class represents a Vendor, which ia an entity that is permitted to access CommunityReport information, and may be permitted to manipulate data, through the HTtP API. export default class Vendor { - @prop({ required: true }) - public name: string | undefined; + @prop({ required: true }) + public name: string | undefined; - @prop({ required: true, unique: true }) - // the uuidv4 string identifier of the vendor; this functions as the identifier and api key for the vendor - public key: string | undefined; + @prop({ required: true, unique: true }) + // the uuidv4 string identifier of the vendor; this functions as the identifier and api key for the vendor + public key: string | undefined; - @prop({ default: false }) - // determines if this vendor can perform a Hard Inquiry and receive additional privileged information - public privileged: boolean | undefined; + @prop({ default: false }) + // determines if this vendor can perform a Hard Inquiry and receive additional privileged information + public privileged: boolean | undefined; } diff --git a/discord/commands/Eval.ts b/discord/commands/Eval.ts index bc2384f..d3ea6fb 100644 --- a/discord/commands/Eval.ts +++ b/discord/commands/Eval.ts @@ -4,64 +4,74 @@ 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[]; + // 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)); + 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 - ]; + 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"); } - 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}); + // if command specified as async, swap the evalString in an async function + if (interaction.options.getBoolean("async")) { + evalString = `(async () => { ${evalString} })()`; + } - // 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"); - } + try { + evaled = await eval(evalString); + if (typeof evaled !== "string") { + evaled = inspect(evaled, { depth }); + } + if (evaled === undefined) { + evaled = "undefined"; + } + } catch (error) { + // @ts-ignore + evaled = error.stack; + } - // if command specified as async, swap the evalString in an async function - if (interaction.options.getBoolean("async")) { - evalString = `(async () => { ${evalString} })()`; - } + // replaces all instances of the bot token with [REDACTED] in output + evaled = evaled.replace(new RegExp(discordBotToken, "gi"), "[REDACTED]"); - 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); + // 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('')); @@ -70,6 +80,6 @@ export default class Eval extends DiscordInteractionCommand { return this.error(ctx.message.channel, `${error}`); } }*/ - await interaction.editReply({content: `\`\`\`js\n${evaled}\n\`\`\``}) - } + await interaction.editReply({ content: `\`\`\`js\n${evaled}\n\`\`\`` }); + } } diff --git a/discord/commands/Partner.ts b/discord/commands/Partner.ts index 368f013..fc4dd36 100644 --- a/discord/commands/Partner.ts +++ b/discord/commands/Partner.ts @@ -2,12 +2,12 @@ import DiscordInteractionCommand from "../../util/DiscordInteractionCommand"; import { ChatInputCommandInteraction } from "discord.js"; export default class Ping extends DiscordInteractionCommand { - constructor() { - super("partner", "Manipulates partner information."); - } + constructor() { + super("partner", "Manipulates partner information."); + } - public async execute(interaction: ChatInputCommandInteraction): Promise { - if (interaction.options?.getSubcommand(true) === "add") { - } + public async execute(interaction: ChatInputCommandInteraction): Promise { + if (interaction.options?.getSubcommand(true) === "add") { } + } } diff --git a/discord/commands/PartnerAdd.ts b/discord/commands/PartnerAdd.ts index d79df4e..8ec9927 100644 --- a/discord/commands/PartnerAdd.ts +++ b/discord/commands/PartnerAdd.ts @@ -1,25 +1,34 @@ -import DiscordInteractionCommand, { DiscordInteractionCommandSkeleton } from "../../util/DiscordInteractionCommand"; +import DiscordInteractionCommand, { + DiscordInteractionCommandSkeleton, +} from "../../util/DiscordInteractionCommand"; import { guildID } from "../../config.json"; import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; import { MemberModel } from "../../database/Member"; import { PartnerModel } from "../../database/Partner"; export default class PartnerAdd implements DiscordInteractionCommandSkeleton { - public GUILD_ID: string; - public name: string; - public description: string - public builder: SlashCommandBuilder; - constructor() { - this.name = "partner"; - this.description = "Creates a new partner entry."; - this.builder = new SlashCommandBuilder(); - this.GUILD_ID = guildID; - } + public GUILD_ID: string; + public name: string; + public description: string; + public builder: SlashCommandBuilder; + constructor() { + this.name = "partner"; + this.description = "Creates a new partner entry."; + this.builder = new SlashCommandBuilder(); + this.GUILD_ID = guildID; + } - public async execute(interaction: ChatInputCommandInteraction) { - const member = MemberModel.findOne({ discordID: interaction.user.id }); - if (!member) return interaction.reply({ content: "The specified partner does not have a base member entry.", ephemeral: true }); - if (!(await PartnerModel.findOne({discordID: interaction.user.id}))) return interaction.reply({ content: "The specified partner already has a partner entry.", ephemeral: true }); - - } + public async execute(interaction: ChatInputCommandInteraction) { + const member = MemberModel.findOne({ discordID: interaction.user.id }); + if (!member) + return interaction.reply({ + content: "The specified partner does not have a base member entry.", + ephemeral: true, + }); + if (!(await PartnerModel.findOne({ discordID: interaction.user.id }))) + return interaction.reply({ + content: "The specified partner already has a partner entry.", + ephemeral: true, + }); + } } diff --git a/discord/commands/Ping.ts b/discord/commands/Ping.ts index 4f6110f..a7170e0 100644 --- a/discord/commands/Ping.ts +++ b/discord/commands/Ping.ts @@ -2,20 +2,20 @@ import DiscordInteractionCommand from "../../util/DiscordInteractionCommand"; import { ChatInputCommandInteraction } from "discord.js"; export default class Ping extends DiscordInteractionCommand { - constructor() { - super("ping", "Pings the bot"); - } + constructor() { + super("ping", "Pings the bot"); + } - public async execute(interaction: ChatInputCommandInteraction): Promise { - const startTimestamp = Date.now(); // Mark the start of processing + public async execute(interaction: ChatInputCommandInteraction): Promise { + const startTimestamp = Date.now(); // Mark the start of processing - await interaction.reply({ content: "Pong!", ephemeral: false }); - const repliedTimestamp = Date.now(); // Mark the timestamp after replying + await interaction.reply({ content: "Pong!", ephemeral: false }); + const repliedTimestamp = Date.now(); // Mark the timestamp after replying - const endTimestamp = Date.now(); // Mark the end of all processing (after editReply) + const endTimestamp = Date.now(); // Mark the end of all processing (after editReply) - await interaction.editReply({ - content: `🏓 Pong!\nClient: \`${repliedTimestamp - interaction.createdTimestamp}ms\`\nResponse: \`${endTimestamp - startTimestamp}ms\`` - }); - } + await interaction.editReply({ + content: `🏓 Pong!\nClient: \`${repliedTimestamp - interaction.createdTimestamp}ms\`\nResponse: \`${endTimestamp - startTimestamp}ms\``, + }); + } } diff --git a/discord/commands/Whois.ts b/discord/commands/Whois.ts index 33d1148..6ff1582 100644 --- a/discord/commands/Whois.ts +++ b/discord/commands/Whois.ts @@ -1,103 +1,117 @@ import DiscordInteractionCommand from "../../util/DiscordInteractionCommand"; 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, GuildMember } from "discord.js"; import MemberUtil from "../../util/MemberUtil"; -import EmojiConfig from "../../util/EmojiConfig" +import EmojiConfig from "../../util/EmojiConfig"; export default class Whois extends DiscordInteractionCommand { - constructor() { - super("whois", "Retrieves information about a user."); - this.builder.addUserOption(option => option.setName("member").setDescription("The member to get information about.").setRequired(true)); - } + constructor() { + super("whois", "Retrieves information about a user."); + this.builder.addUserOption((option) => + option + .setName("member") + .setDescription("The member to get information about.") + .setRequired(true) + ); + } - public async execute(interaction: ChatInputCommandInteraction) { - // defer our reply and perform database/external API operations/lookups - await interaction.deferReply({ ephemeral: false }); - const target = interaction.options.getUser("member", true); - const guild = interaction.guild || interaction.client.guilds.cache.get(this.GUILD_ID); - const guildMember = await guild?.members.fetch(target.id); - const databaseMember = await MemberModel.findOne({ discordID: target.id }); - const partner = await PartnerModel.findOne({ discordID: target.id }); - // return an error if target was not located - if (!guildMember) return interaction.editReply({ content: `Member target ${target.id} was not located.`}); - // build our embed - const embed = new EmbedBuilder(); - // 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 - const formattedName = MemberUtil.formatName(guildMember, partner); - embed.setAuthor({ name: formattedName.text, iconURL: formattedName.iconURL }); - // set the thumbnail to the user's avatar - embed.setThumbnail(guildMember.user.displayAvatarURL()); - // initialize the description string - let embedDescription = ''; - if (partner) { - // 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`; - switch (partner.department) { - case PartnerDepartment.ENGINEERING: - embedDescription += "**Department**: Dept. of Engineering\n"; - break; - case PartnerDepartment.OPERATIONS: - embedDescription += "**Department**: Dept. of Operations\n"; - break; - case PartnerDepartment.INDEPENDENT_AGENCY: - embedDescription += "**Department**: Independent Agency/Contractor\n"; - break; - } - switch (partner.commissionType) { - case PartnerCommissionType.TENURE: - embedDescription += "**Commission Type**: Tenure\n"; - break; - case PartnerCommissionType.PROVISIONAL: - embedDescription += "**Commission Type**: Provisional\n"; - break; - case PartnerCommissionType.CONTRACTUAL: - embedDescription += "**Commission Type**: Contractual/Independent/Collaborator\n"; - break; - case PartnerCommissionType.ACTING: - embedDescription += "**Commission Type**: Acting\n"; - break; - case PartnerCommissionType.INTERIM: - embedDescription += "**Commission Type**: Interim\n"; - break; - case PartnerCommissionType.TRIAL: - embedDescription += "**Commission Type**: Trial/Intern\n"; - break; - } - if (partner.directReport) { - if (partner.directReport instanceof Partner) { - embedDescription += `**Direct Report**: ${partner.directReport.title}\n`; - } - } + public async execute(interaction: ChatInputCommandInteraction) { + // defer our reply and perform database/external API operations/lookups + await interaction.deferReply({ ephemeral: false }); + const target = interaction.options.getUser("member", true); + const guild = interaction.guild || interaction.client.guilds.cache.get(this.GUILD_ID); + const guildMember = await guild?.members.fetch(target.id); + const databaseMember = await MemberModel.findOne({ discordID: target.id }); + const partner = await PartnerModel.findOne({ discordID: target.id }); + // return an error if target was not located + if (!guildMember) + return interaction.editReply({ content: `Member target ${target.id} was not located.` }); + // build our embed + const embed = new EmbedBuilder(); + // 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 + const formattedName = MemberUtil.formatName(guildMember, partner); + embed.setAuthor({ name: formattedName.text, iconURL: formattedName.iconURL }); + // set the thumbnail to the user's avatar + embed.setThumbnail(guildMember.user.displayAvatarURL()); + // initialize the description string + let embedDescription = ""; + if (partner) { + // 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`; + switch (partner.department) { + case PartnerDepartment.ENGINEERING: + embedDescription += "**Department**: Dept. of Engineering\n"; + break; + case PartnerDepartment.OPERATIONS: + embedDescription += "**Department**: Dept. of Operations\n"; + break; + case PartnerDepartment.INDEPENDENT_AGENCY: + embedDescription += "**Department**: Independent Agency/Contractor\n"; + break; + } + switch (partner.commissionType) { + case PartnerCommissionType.TENURE: + embedDescription += "**Commission Type**: Tenure\n"; + break; + case PartnerCommissionType.PROVISIONAL: + embedDescription += "**Commission Type**: Provisional\n"; + break; + case PartnerCommissionType.CONTRACTUAL: + embedDescription += "**Commission Type**: Contractual/Independent/Collaborator\n"; + break; + case PartnerCommissionType.ACTING: + embedDescription += "**Commission Type**: Acting\n"; + break; + case PartnerCommissionType.INTERIM: + embedDescription += "**Commission Type**: Interim\n"; + break; + case PartnerCommissionType.TRIAL: + embedDescription += "**Commission Type**: Trial/Intern\n"; + break; + } + if (partner.directReport) { + if (partner.directReport instanceof Partner) { + embedDescription += `**Direct Report**: ${partner.directReport.title}\n`; } - embed.setColor(guildMember.displayColor); - 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}` : ''}` }); - - return await interaction.editReply({ embeds: [embed] }); + } } + embed.setColor(guildMember.displayColor); + 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}` : ""}`, + }); + + return await interaction.editReply({ embeds: [embed] }); + } } diff --git a/discord/events/InteractionCreate.ts b/discord/events/InteractionCreate.ts index db44f4f..b923652 100644 --- a/discord/events/InteractionCreate.ts +++ b/discord/events/InteractionCreate.ts @@ -3,24 +3,34 @@ import { DiscordInteractionCommands } from "../../index"; import { Client, Interaction } from "discord.js"; export default class InteractionCreate extends DiscordEvent { - constructor(client: Client) { - super("interactionCreate", client); - } + constructor(client: Client) { + super("interactionCreate", client); + } - public async execute(interaction: Interaction): Promise { - if (!interaction.isChatInputCommand()) return; - const command = DiscordInteractionCommands.get(interaction.commandName); - if (!command) return console.error(`No command matching ${interaction.commandName} was found.`); - try { - await command.execute(interaction); - console.info(`[Info - Discord] Command '${interaction.commandName}' executed by '${interaction.user.username}'`); - } catch (error) { - console.error(`Error executing command '${interaction.commandName}': by '${interaction.user.username}'\n${error}`); - if (interaction.replied || interaction.deferred) { - await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true }); - } else { - await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); - } - } + public async execute(interaction: Interaction): Promise { + if (!interaction.isChatInputCommand()) return; + const command = DiscordInteractionCommands.get(interaction.commandName); + if (!command) return console.error(`No command matching ${interaction.commandName} was found.`); + try { + await command.execute(interaction); + console.info( + `[Info - Discord] Command '${interaction.commandName}' executed by '${interaction.user.username}'` + ); + } catch (error) { + console.error( + `Error executing command '${interaction.commandName}': by '${interaction.user.username}'\n${error}` + ); + if (interaction.replied || interaction.deferred) { + await interaction.followUp({ + content: "There was an error while executing this command!", + ephemeral: true, + }); + } else { + await interaction.reply({ + content: "There was an error while executing this command!", + ephemeral: true, + }); + } } + } } diff --git a/util/Collection.ts b/util/Collection.ts index 699af71..7fea15d 100644 --- a/util/Collection.ts +++ b/util/Collection.ts @@ -2,153 +2,153 @@ * Hold a bunch of something */ export default class Collection extends Map { - baseObject: (new (...args: any[]) => V) | undefined; + baseObject: (new (...args: any[]) => V) | undefined; - /** - * Creates an instance of Collection - */ - constructor(iterable: Iterable<[string, V]> | object | null = null) { - if (iterable && iterable instanceof Array) { - super(iterable); - } else if (iterable && iterable instanceof Object) { - super(Object.entries(iterable)); - } else { - super(); - } + /** + * Creates an instance of Collection + */ + constructor(iterable: Iterable<[string, V]> | object | null = null) { + if (iterable && iterable instanceof Array) { + super(iterable); + } else if (iterable && iterable instanceof Object) { + super(Object.entries(iterable)); + } else { + super(); } + } - /** - * Map to array - * ```js - * [value, value, value] - * ``` - */ - toArray(): V[] { - return [...this.values()]; + /** + * Map to array + * ```js + * [value, value, value] + * ``` + */ + toArray(): V[] { + return [...this.values()]; + } + + /** + * Map to object + * ```js + * { key: value, key: value, key: value } + * ``` + */ + toObject(): { [key: string]: V } { + const obj: { [key: string]: V } = {}; + for (const [key, value] of this.entries()) { + obj[key] = value; } + return obj; + } - /** - * Map to object - * ```js - * { key: value, key: value, key: value } - * ``` - */ - toObject(): { [key: string]: V } { - const obj: { [key: string]: V } = {}; - for (const [key, value] of this.entries()) { - obj[key] = value; - } - return obj; + /** + * Add an object + * + * If baseObject, add only if instance of baseObject + * + * If no baseObject, add + * @param key The key of the object + * @param value The object data + * @param replace Whether to replace an existing object with the same key + * @return The existing or newly created object + */ + add(key: string, value: V, replace: boolean = false): V | undefined | null { + if (this.has(key) && !replace) { + return this.get(key); } + if (this.baseObject && !(value instanceof this.baseObject)) return null; - /** - * Add an object - * - * If baseObject, add only if instance of baseObject - * - * If no baseObject, add - * @param key The key of the object - * @param value The object data - * @param replace Whether to replace an existing object with the same key - * @return The existing or newly created object - */ - add(key: string, value: V, replace: boolean = false): V | undefined | null { - if (this.has(key) && !replace) { - return this.get(key); - } - if (this.baseObject && !(value instanceof this.baseObject)) return null; + this.set(key, value); + return value; + } - this.set(key, value); - return value; + /** + * Return the first object to make the function evaluate true + * @param func A function that takes an object and returns something + * @return The first matching object, or `null` if no match + */ + find(func: Function): V | null { + for (const item of this.values()) { + if (func(item)) return item; } + return null; + } - /** - * Return the first object to make the function evaluate true - * @param func A function that takes an object and returns something - * @return The first matching object, or `null` if no match - */ - find(func: Function): V | null { - for (const item of this.values()) { - if (func(item)) return item; - } - return null; + /** + * Return an array with the results of applying the given function to each element + * @param callbackfn A function that takes an object and returns something + */ + map(callbackfn: (value?: V, index?: number, array?: V[]) => U): U[] { + const arr = []; + for (const item of this.values()) { + arr.push(callbackfn(item)); } + return arr; + } - /** - * Return an array with the results of applying the given function to each element - * @param callbackfn A function that takes an object and returns something - */ - map(callbackfn: (value?: V, index?: number, array?: V[]) => U): U[] { - const arr = []; - for (const item of this.values()) { - arr.push(callbackfn(item)); - } - return arr; + /** + * Return all the objects that make the function evaluate true + * @param func A function that takes an object and returns true if it matches + */ + filter(func: (value: V) => boolean): V[] { + const arr = []; + for (const item of this.values()) { + if (func(item)) { + arr.push(item); + } } + return arr; + } - /** - * Return all the objects that make the function evaluate true - * @param func A function that takes an object and returns true if it matches - */ - filter(func: (value: V) => boolean): V[] { - const arr = []; - for (const item of this.values()) { - if (func(item)) { - arr.push(item); - } - } - return arr; + /** + * Test if at least one element passes the test implemented by the provided function. Returns true if yes, or false if not. + * @param func A function that takes an object and returns true if it matches + */ + some(func: (value: V) => boolean) { + for (const item of this.values()) { + if (func(item)) { + return true; + } } + return false; + } - /** - * Test if at least one element passes the test implemented by the provided function. Returns true if yes, or false if not. - * @param func A function that takes an object and returns true if it matches - */ - some(func: (value: V) => boolean) { - for (const item of this.values()) { - if (func(item)) { - return true; - } - } - return false; - } + /** + * Update an object + * @param key The key of the object + * @param value The updated object data + */ + update(key: string, value: V) { + return this.add(key, value, true); + } - /** - * Update an object - * @param key The key of the object - * @param value The updated object data - */ - update(key: string, value: V) { - return this.add(key, value, true); + /** + * Remove an object + * @param key The key of the object + * @returns The removed object, or `null` if nothing was removed + */ + remove(key: string): V | null { + const item = this.get(key); + if (!item) { + return null; } + this.delete(key); + return item; + } - /** - * Remove an object - * @param key The key of the object - * @returns The removed object, or `null` if nothing was removed - */ - remove(key: string): V | null { - const item = this.get(key); - if (!item) { - return null; - } - this.delete(key); - return item; + /** + * Get a random object from the Collection + * @returns The random object or `null` if empty + */ + random(): V | null { + if (!this.size) { + return null; } + return Array.from(this.values())[Math.floor(Math.random() * this.size)]; + } - /** - * Get a random object from the Collection - * @returns The random object or `null` if empty - */ - random(): V | null { - if (!this.size) { - return null; - } - return Array.from(this.values())[Math.floor(Math.random() * this.size)]; - } - - toString() { - // @ts-ignore - return `[Collection<${this.baseObject.name}>]`; - } + toString() { + // @ts-ignore + return `[Collection<${this.baseObject.name}>]`; + } } diff --git a/util/DiscordEvent.ts b/util/DiscordEvent.ts index a0187f4..e75f161 100644 --- a/util/DiscordEvent.ts +++ b/util/DiscordEvent.ts @@ -1,12 +1,12 @@ import { Client } from "discord.js"; export default abstract class DiscordEvent { - public name: string; - protected client: Client; + public name: string; + protected client: Client; - protected constructor(name: string = "", client: Client) { - this.name = name; - this.client = client; - this.execute = this.execute.bind(this); - } - public abstract execute(...args: any[]): Error | Promise; + protected constructor(name: string = "", client: Client) { + this.name = name; + this.client = client; + this.execute = this.execute.bind(this); + } + public abstract execute(...args: any[]): Error | Promise; } diff --git a/util/DiscordInteractionCommand.ts b/util/DiscordInteractionCommand.ts index 9c7f5c2..f5f8d28 100644 --- a/util/DiscordInteractionCommand.ts +++ b/util/DiscordInteractionCommand.ts @@ -2,30 +2,32 @@ import { SlashCommandBuilder, ChatInputCommandInteraction } from "discord.js"; import { guildID } from "../config.json"; export interface DiscordInteractionCommandSkeleton { - GUILD_ID: string; - builder?: SlashCommandBuilder; - description: string; - execute: (interaction: ChatInputCommandInteraction) => Error | Promise; - name: string; + GUILD_ID: string; + builder?: SlashCommandBuilder; + description: string; + execute: (interaction: ChatInputCommandInteraction) => Error | Promise; + name: string; } -export default abstract class DiscordInteractionCommand implements DiscordInteractionCommandSkeleton { - public name: string; - public description: string; - public builder: SlashCommandBuilder; +export default abstract class DiscordInteractionCommand + implements DiscordInteractionCommandSkeleton +{ + public name: string; + public description: string; + public builder: SlashCommandBuilder; - public GUILD_ID: string; + public GUILD_ID: string; - protected constructor(name: string, description: string) { - this.name = name; - this.description = description; - this.builder = new SlashCommandBuilder(); + protected constructor(name: string, description: string) { + this.name = name; + this.description = description; + this.builder = new SlashCommandBuilder(); - this.builder.setName(this.name); - this.builder.setDescription(this.description); + this.builder.setName(this.name); + this.builder.setDescription(this.description); - this.GUILD_ID = guildID; - } + this.GUILD_ID = guildID; + } - public abstract execute(interaction: ChatInputCommandInteraction): Error | Promise; + public abstract execute(interaction: ChatInputCommandInteraction): Error | Promise; } diff --git a/util/EmojiConfig.ts b/util/EmojiConfig.ts index ae400de..58a68a9 100644 --- a/util/EmojiConfig.ts +++ b/util/EmojiConfig.ts @@ -1,4 +1,4 @@ export default class EmojiConfig { - public static LOC = "<:loc:607695848612167700>"; - public static EMAIL = "<:email:699786452267040878>"; + public static LOC = "<:loc:607695848612167700>"; + public static EMAIL = "<:email:699786452267040878>"; } diff --git a/util/MemberUtil.ts b/util/MemberUtil.ts index 71f040d..9b7bf2e 100644 --- a/util/MemberUtil.ts +++ b/util/MemberUtil.ts @@ -1,84 +1,118 @@ import Partner, { - PartnerCommissionType, - PartnerDepartment, - PartnerModel, - PartnerRoleType, - PartnerTitle + PartnerCommissionType, + PartnerDepartment, + PartnerModel, + PartnerRoleType, + PartnerTitle, } from "../database/Partner"; import Member, { MemberAdditionalAcknowledgement, MemberModel } from "../database/Member"; import { Client, GuildMember, User } from "discord.js"; import { guildID } from "../config.json"; export interface PartnerOptions { - roleType: PartnerRoleType; - commissionType: PartnerCommissionType; - department: PartnerDepartment; - title: PartnerTitle; - directReport: Partner | string; + roleType: PartnerRoleType; + commissionType: PartnerCommissionType; + department: PartnerDepartment; + title: PartnerTitle; + directReport: Partner | string; } export interface FormatNameOptions { - text: string; - iconURL: string; + text: string; + iconURL: string; } // TODO: Add the rest of the remaining role configurations export const PartnerDiscordRoleMap = { - // Director of Engineering, Management, Staff, Technician, Core Team, Play Caller - "Director of Engineering": ["1077646568091570236", "1077646956890951690", "446104438969466890", "701454780828221450", "453689940140883988", "1014978134573064293"], - // Director of Operations, Management, Staff, Moderator, Core Team, Play Caller - "Director of Operations": ["1077647072163020840", "1077646956890951690", "446104438969466890", "455972169449734144", "453689940140883988", "1014978134573064293"] -} + // Director of Engineering, Management, Staff, Technician, Core Team, Play Caller + "Director of Engineering": [ + "1077646568091570236", + "1077646956890951690", + "446104438969466890", + "701454780828221450", + "453689940140883988", + "1014978134573064293", + ], + // Director of Operations, Management, Staff, Moderator, Core Team, Play Caller + "Director of Operations": [ + "1077647072163020840", + "1077646956890951690", + "446104438969466890", + "455972169449734144", + "453689940140883988", + "1014978134573064293", + ], +}; export default class MemberUtil { - public static async createNewPartner(member: Member, options: PartnerOptions) { - const partner = new PartnerModel(); - partner.discordID = member.discordID; - partner.roleType = options.roleType; - partner.commissionType = options.commissionType; - partner.department = options.department; - partner.title = options.title; - partner.directReport = options.directReport; - await partner.save(); - return partner; - } + public static async createNewPartner(member: Member, options: PartnerOptions) { + const partner = new PartnerModel(); + partner.discordID = member.discordID; + partner.roleType = options.roleType; + partner.commissionType = options.commissionType; + partner.department = options.department; + partner.title = options.title; + partner.directReport = options.directReport; + await partner.save(); + return partner; + } - public static async getPartner(member: Member) { - return PartnerModel.findOne({ discordID: member.discordID }); - } + public static async getPartner(member: Member) { + return PartnerModel.findOne({ discordID: member.discordID }); + } - public static async deletePartner(member: Member) { - return PartnerModel.deleteOne({ discordID: member.discordID }); - } + public static async deletePartner(member: Member) { + return PartnerModel.deleteOne({ discordID: member.discordID }); + } - public static addAcknowledgementToMember(member: Member, acknowledgement: MemberAdditionalAcknowledgement) { - if (!member.additionalAcknowledgement || member.additionalAcknowledgement?.length === 0) { - MemberModel.updateOne({ discordID: member.discordID }, { additionalAcknowledgement: [] }); - } - if (member.additionalAcknowledgement?.includes(acknowledgement)) throw new Error("This member already has this acknowledgement.") - return MemberModel.updateOne({ discordID: member.discordID }, { $push: { additionalAcknowledgement: acknowledgement } }); + public static addAcknowledgementToMember( + member: Member, + acknowledgement: MemberAdditionalAcknowledgement + ) { + if (!member.additionalAcknowledgement || member.additionalAcknowledgement?.length === 0) { + MemberModel.updateOne({ discordID: member.discordID }, { additionalAcknowledgement: [] }); } + if (member.additionalAcknowledgement?.includes(acknowledgement)) + throw new Error("This member already has this acknowledgement."); + return MemberModel.updateOne( + { discordID: member.discordID }, + { $push: { additionalAcknowledgement: acknowledgement } } + ); + } - // TODO: comments and extended formatting - 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 partner exists, set the iconURL to the organizational logo - if (partner?.roleType == PartnerRoleType.MANAGERIAL) { - return { - text: `${target.displayName} [k]`, - iconURL: target.displayAvatarURL(), - } - } else if (partner?.commissionType == PartnerCommissionType.CONTRACTUAL) { // if the commission type is contractual, add a [c] to the end of the name - return { - text: `${target.displayName} [c]`, - iconURL: target instanceof GuildMember ? target.user.displayAvatarURL() : target.displayAvatarURL(), - } - } else { // otherwise, just set the author to the member's display name - return { - text: target.displayName, - iconURL: target instanceof GuildMember ? target.user.displayAvatarURL() : target.displayAvatarURL(), - } - } + // TODO: comments and extended formatting + 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 partner exists, set the iconURL to the organizational logo + if (partner?.roleType == PartnerRoleType.MANAGERIAL) { + return { + text: `${target.displayName} [k]`, + iconURL: target.displayAvatarURL(), + }; + } else if (partner?.commissionType == PartnerCommissionType.CONTRACTUAL) { + // if the commission type is contractual, add a [c] to the end of the name + return { + text: `${target.displayName} [c]`, + iconURL: + target instanceof GuildMember + ? target.user.displayAvatarURL() + : target.displayAvatarURL(), + }; + } else { + // otherwise, just set the author to the member's display name + return { + text: target.displayName, + iconURL: + target instanceof GuildMember + ? target.user.displayAvatarURL() + : target.displayAvatarURL(), + }; } + } }