diff --git a/src/Constants.ts b/src/Constants.ts index 9454d52..cc22fee 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -1,7 +1,5 @@ export const Constants = { - APPROVED_CHANNEL_ID: "1371073576903376896", - PENDING_CHANNEL_ID: "1370539719842070683", - REJECTION_CHANNEL_ID: "1371073658403164261", + APPLICATIONS_CHANNEL_ID: "1377060608431751188", REVIEWER_ROLE_ID: "1375617676139040909", MOD_ROLE_ID: "1370539692143153152", MANAGER_ROLE_ID: "1370539689659863091", @@ -15,5 +13,13 @@ export const Constants = { BAD: 0xffaaaa, YELLOW: 0xeadb77, GOOD: 0xaaffaa + }, + TAGS: { + PENDING: "1377061012645085194", + INTERVIEWED: "1377061105657970758", + ACCEPTED: "1377061136989425895", + REJECTED: "1377061177099681833", + WITHDRAWN: "1377222222254702642", + BANNED: "1377061220825436170" } }; diff --git a/src/components/PendingApplicationMessage.tsx b/src/components/PendingApplicationMessage.tsx index 80ebe71..4a4c09e 100644 --- a/src/components/PendingApplicationMessage.tsx +++ b/src/components/PendingApplicationMessage.tsx @@ -17,13 +17,11 @@ export function PendingApplicationMessage(props: { user: OUser; response: Response; locked?: boolean; - threadID: string; }) { const { id, user, response } = props; const locked = props.locked || false; return ( - {"<@&1375617676139040909>"} - -# Discuss in {`<#${props.threadID}>`} ); } diff --git a/src/components/User.tsx b/src/components/User.tsx index 2cfeb5c..a45d1b3 100644 --- a/src/components/User.tsx +++ b/src/components/User.tsx @@ -12,7 +12,7 @@ export function User(props: { user: DiscordUser }) { {user.globalName || user.username}
- -# @{user.username} + -# @{user.username} ({user.id})
); diff --git a/src/joinRequestActions/accept.tsx b/src/joinRequestActions/accept.tsx index 4120235..995dd81 100644 --- a/src/joinRequestActions/accept.tsx +++ b/src/joinRequestActions/accept.tsx @@ -16,7 +16,7 @@ client.on("interactionCreate", async (interaction) => { if (interaction.type === InteractionTypes.MESSAGE_COMPONENT) if (interaction.data.componentType === ComponentTypes.BUTTON) { if (interaction.data.customID.split("-")[0] === "accept") { - await interaction.defer(MessageFlags.EPHEMERAL); + await interaction.defer(); if ( !canUser(interaction.member!, "review") || (!canUser(interaction.member!, "owner") && @@ -33,12 +33,10 @@ client.on("interactionCreate", async (interaction) => { ); await db.run( - "DELETE FROM applications WHERE id=?", - application.id - ); - await client.rest.channels.deleteMessage( - application.channel_id, - application.message_id + `UPDATE applications SET status=1 WHERE id=?`, + interaction.data.customID.split("-")[ + interaction.data.customID.split("-").length - 1 + ] ); await selfappReq( @@ -50,14 +48,14 @@ client.on("interactionCreate", async (interaction) => { ); const user = await client.rest.users.get(application.user_id); await interaction.createFollowup({ - flags: MessageFlags.EPHEMERAL, - content: `<:blobcatgreen:1375806000312881233> Approved @${user.tag}'s join request!` + content: `<:blobcatgreen:1375806000312881233> **Approved** \`@${user.tag}\`'s join request!` }); const response: Response = JSON.parse(application.responses); - const msg = await client.rest.channels.createMessage( - Constants.APPROVED_CHANNEL_ID, + const msg = await client.rest.channels.editMessage( + application.channel_id, + application.message_id, ## Join request accepted @@ -91,25 +89,11 @@ client.on("interactionCreate", async (interaction) => { })() }); - await client.rest.request({ - auth: `Bot ${process.env.BOT_TOKEN}`, - method: "POST", - path: `/channels/${application.thread_id}/messages`, - json: { - content: "", - flags: 0, - message_reference: { - channel_id: msg.channelID, - guild_id: msg.guildID!, - message_id: msg.id, - type: 1 - } - } - }); - await client.rest.channels.edit(application.thread_id, { + archived: true, locked: true, - reason: `${user.tag}'s application has been accepted` + reason: `${user.tag}'s application has been accepted`, + appliedTags: [Constants.TAGS.ACCEPTED] }); } } diff --git a/src/joinRequestActions/interview.ts b/src/joinRequestActions/interview.ts index 034f2c0..1748009 100644 --- a/src/joinRequestActions/interview.ts +++ b/src/joinRequestActions/interview.ts @@ -2,6 +2,7 @@ import { ComponentTypes, InteractionTypes, MessageFlags } from "oceanic.js"; import { client } from ".."; import { canUser } from "../utils/utils"; import { selfappReq } from "../utils/selfappReq"; +import { Constants } from "~/Constants"; client.on("interactionCreate", async (interaction) => { if (interaction.type === InteractionTypes.MESSAGE_COMPONENT) @@ -28,6 +29,12 @@ client.on("interactionCreate", async (interaction) => { )) as any ).code; + client.rest.channels.edit(interaction.channelID, { + appliedTags: [ + Constants.TAGS.PENDING, + Constants.TAGS.INTERVIEWED + ] + }); return await interaction.createFollowup({ flags: MessageFlags.EPHEMERAL, content: `https://discord.gg/${gdmInvite}` diff --git a/src/joinRequestActions/lockUnlock.tsx b/src/joinRequestActions/lockUnlock.tsx index 9b87ea1..2b2b2b2 100644 --- a/src/joinRequestActions/lockUnlock.tsx +++ b/src/joinRequestActions/lockUnlock.tsx @@ -19,7 +19,6 @@ client.on("interactionCreate", async (interaction) => { "SELECT * FROM applications WHERE message_id=?", interaction.message.id ); - console.log(application); switch (interaction.data.customID.split("-")[0]) { case "lock": { @@ -31,7 +30,6 @@ client.on("interactionCreate", async (interaction) => { application.user_id )} locked={true} - threadID={application.thread_id} /> ); break; @@ -45,7 +43,6 @@ client.on("interactionCreate", async (interaction) => { application.user_id )} locked={false} - threadID={application.thread_id} /> ); break; diff --git a/src/joinRequestActions/reject.tsx b/src/joinRequestActions/reject.tsx new file mode 100644 index 0000000..d4f44ef --- /dev/null +++ b/src/joinRequestActions/reject.tsx @@ -0,0 +1,152 @@ +import { + AnyComponentSelectMenuInteraction, + ComponentInteraction, + ComponentTypes, + InteractionTypes, + MessageFlags, + ModalSubmitInteraction, + TextInputStyles +} from "oceanic.js"; +import { client } from ".."; +import { canUser } from "../utils/utils"; +import { selfappReq } from "../utils/selfappReq"; +import { Response } from "~/utils/types"; +import { db } from "~/utils/database"; +import { ComponentMessage } from "components-jsx/ComponentMessage"; +import { Container } from "components-jsx/Container"; +import { Divider } from "components-jsx/Divider"; +import { TextDisplay } from "components-jsx/TextDisplay"; +import { ApplicationContent } from "~/components/ApplicationContent"; +import { User } from "~/components/User"; +import { Constants } from "~/Constants"; +import { TextInput } from "components-jsx/TextInput"; +import { ActionRow } from "components-jsx/ActionRow"; +import { rejectReasons } from "~/utils/rejectReasons"; + +export async function rejectUser( + interaction: ComponentInteraction | ModalSubmitInteraction, + reason: string = "" +) { + await interaction.defer(); + const shouldBan = interaction.data.customID.includes("ban"); + const application = await db.get( + "SELECT * FROM applications WHERE id=?", + interaction.data.customID.split("-")[ + interaction.data.customID.split("-").length - 2 + ] + ); + + const user = await client.rest.users.get(application.user_id); + await interaction.createFollowup({ + content: `${ + shouldBan + ? "<:BAN:1375806319621046313>" + : "<:blobcatred:1375806202470203513>" + } **Rejected** \`@${user.tag}\`'s join request${ + shouldBan ? " and banned them" : "" + }!` + }); + + const response: Response = JSON.parse(application.responses); + + const msg = await client.rest.channels.editMessage( + application.channel_id, + application.message_id, + + + ## Join request rejected + + + + + + + ### Reason +
+ {reason} +
+
+
+ ); + + await db.run( + `UPDATE applications SET status=-1, reject_reason=?, actioned_by=?, message_id=? WHERE id=?`, + reason, + interaction.member!.id, + msg.id, + interaction.data.customID.split("-")[ + interaction.data.customID.split("-").length - 1 + ] + ); + + await selfappReq( + `/guilds/${interaction.guildID}/requests/id/${application.id}`, + "PATCH", + { + action: "REJECTED", + rejection_reason: reason + } + ); + shouldBan && + (await interaction.guild?.createBan(user.id, { + reason + })); + + await client.rest.channels.edit(application.thread_id, { + locked: true, + reason: `${user.tag}'s application has been rejected`, + appliedTags: [Constants.TAGS.REJECTED] + }); +} + +client.on("interactionCreate", async (interaction) => { + if (interaction.type === InteractionTypes.MODAL_SUBMIT) { + await rejectUser( + interaction, + `${interaction.member?.tag}: ${ + interaction.data.components.getTextInput("reason") || + "No reason provided" + }` + ); + } + if (interaction.type === InteractionTypes.MESSAGE_COMPONENT) { + if (interaction.data.componentType === ComponentTypes.BUTTON) { + if (interaction.data.customID.split("-")[0] === "reject") { + if (!canUser(interaction.member!, "review")) + return await interaction.createFollowup({ + flags: MessageFlags.EPHEMERAL, + content: "💢 nop" + }); + + await interaction.createModal({ + title: `Reject ${ + interaction.data.customID.includes("ban") + ? "and ban " + : "" + }user`, + components: [ + + + + ], + customID: interaction.data.customID + }); + } + } + if (interaction.data.componentType === ComponentTypes.STRING_SELECT) { + await rejectUser( + interaction, + `${interaction.member!.tag}: ${ + rejectReasons[interaction.data.values.getStrings()[0]] + .reason + }` + ); + } + } +}); diff --git a/src/joinRequestHandler.tsx b/src/joinRequestHandler.tsx index 3247f45..738cd0c 100644 --- a/src/joinRequestHandler.tsx +++ b/src/joinRequestHandler.tsx @@ -28,6 +28,7 @@ import { ApplicationContent } from "./components/ApplicationContent"; import("./joinRequestActions/lockUnlock"); import("./joinRequestActions/interview"); import("./joinRequestActions/accept"); +import("./joinRequestActions/reject"); export async function setupJoinRequestHandler(shard: Shard) { shard.ws?.on("message", async (d) => { @@ -61,19 +62,9 @@ export async function setupJoinRequestHandler(shard: Shard) { const user = await client.rest.users.get( applicationData.request.user.id ); - const thread = - await client.rest.channels.startThreadWithoutMessage( - Constants.PENDING_CHANNEL_ID, - { - name: `${user.tag}'s application`, - type: ChannelTypes.PUBLIC_THREAD, - autoArchiveDuration: 10080 - } - ); - - const pendingMsg = - await client.rest.channels.createMessage( - Constants.PENDING_CHANNEL_ID, + const baller = { + name: `${user.tag}'s application`, + message: ( + ), + appliedTags: [Constants.TAGS.PENDING] + }; + console.log(JSON.stringify(baller)); + const thread = + await client.rest.channels.startThreadInThreadOnlyChannel( + Constants.APPLICATIONS_CHANNEL_ID, + baller ); const fullApplicantProfile: any = await selfappReq( @@ -94,6 +92,7 @@ export async function setupJoinRequestHandler(shard: Shard) { ); thread.createMessage({ + content: `<@&${Constants.REVIEWER_ROLE_ID}> new application from \`@${user.tag}\``, embeds: [ { color: Constants.COLORS.NEW_REQ, @@ -111,8 +110,8 @@ export async function setupJoinRequestHandler(shard: Shard) { "INSERT INTO applications (id, user_id, status, message_id, channel_id, responses, thread_id) VALUES (?, ?, 0, ?, ?, ?, ?)", applicationData.request.id, applicationData.request.user_id, - pendingMsg.id, - pendingMsg.channelID, + thread.id, + thread.id, JSON.stringify(response), thread.id ); @@ -131,69 +130,89 @@ export async function setupJoinRequestHandler(shard: Shard) { applicationData.user_id ); + const response: Response = JSON.parse( + application ? application.responses : "{}" // this will never be used if no applications + ); + if (application) { await db.run( "DELETE FROM applications WHERE id=?", applicationData.id ); - await client.rest.channels.deleteMessage( - application.channel_id, - application.message_id - ); - } - - const response: Response = JSON.parse( - application ? application.responses : {} // this will never be used if no applications - ); - - const msg = await client.rest.channels.createMessage( - Constants.REJECTION_CHANNEL_ID, - - - - ## Join request withdrawn - - - - - - {application ? ( + if (application.status === 1) return; + client.rest.channels.editMessage( + application.thread_id, + application.message_id, + + + + ## Join request withdrawn + + + + - ) : ( - - ### Application -
- User hasn't applied -
- )} -
-
- ); - - await client.rest.request({ - auth: `Bot ${process.env.BOT_TOKEN}`, - method: "POST", - path: `/channels/${application.thread_id}/messages`, - json: { - content: "", - flags: 0, - message_reference: { - channel_id: msg.channelID, - guild_id: msg.guildID!, - message_id: msg.id, - type: 1 - } - } - }); - - if (application) + {application.reject_reason && } + {application.reject_reason && ( + + ### Rejection reason +
+ {application.reject_reason} +
+ )} +
+
+ ); await client.rest.channels.edit(application.thread_id, { + archived: true, locked: true, - reason: `${user.tag}'s application has been withdrawn` + reason: `${user.tag}'s application has been withdrawn`, + appliedTags: [Constants.TAGS.WITHDRAWN] }); + application.reject_reason && + client.rest.channels.edit(application.thread_id, { + appliedTags: [ + Constants.TAGS.REJECTED, + Constants.TAGS.WITHDRAWN + ] + }); + } else { + const th = + await client.rest.channels.startThreadInThreadOnlyChannel( + Constants.APPLICATIONS_CHANNEL_ID, + { + name: `${user.tag}'s application`, + message: ( + + + + ## Join request withdrawn + + + + + + ### Application +
+ User hasn't applied +
+
+
+ ), + appliedTags: [Constants.TAGS.WITHDRAWN] + } + ); + th.edit({ + locked: true + }); + } break; } } diff --git a/src/utils/rejectReasons.ts b/src/utils/rejectReasons.ts index 08b4041..5798c51 100644 --- a/src/utils/rejectReasons.ts +++ b/src/utils/rejectReasons.ts @@ -18,6 +18,6 @@ export const rejectReasons: { }, ai: { shortDesc: "AI", - reason: "You have obviously used AI in your application. Therefore, you will not be allowed to reapply." + reason: "You have obviously used AI in your application." } };