diff --git a/src/Constants.ts b/src/Constants.ts
index c8fbc6e..b0d4873 100644
--- a/src/Constants.ts
+++ b/src/Constants.ts
@@ -1,4 +1,10 @@
export const Constants = {
PENDING_CHANNEL_ID: "1370539719842070683",
- REJECTION_CHANNEL_ID: "1371073658403164261"
+ REJECTION_CHANNEL_ID: "1371073658403164261",
+ COLORS: {
+ NEW_REQ: 0xaaaaff,
+ BAD: 0xffaaaa,
+ YELLOW: 0xeadb77,
+ GOOD: 0xaaffaa
+ }
};
diff --git a/src/components/ApplicationContent.tsx b/src/components/ApplicationContent.tsx
new file mode 100644
index 0000000..97a14c8
--- /dev/null
+++ b/src/components/ApplicationContent.tsx
@@ -0,0 +1,47 @@
+import { TextDisplay } from "components-jsx/TextDisplay";
+import { Response } from "~/types";
+
+export function ApplicationContent(props: {
+ response: Response;
+ includeDetails?: boolean;
+}) {
+ const { response } = props;
+ return (
+
+ ### Application
+
+ Here for
+
+ -# {response.hereFor.join(", ")}
+
+ Found through
+
+ -#{" "}
+ {(() => {
+ switch (response.foundThrough) {
+ case "archive":
+ return "Guild Archive/nelly.tools";
+ case "tag":
+ return 'Hit "Ask to Join" on a clan tag';
+ case "user":
+ return "User invited them\n-# **Only accept if someone is mentioned in details**";
+ case "other":
+ return "Something else";
+ case "sold":
+ return "Was sold an invite\n-# **Only the owner can interact with this application**";
+ }
+ })()}
+
+ Languages
+
+ -# {response.languages}
+
+ Can boost
+
+ -# {response.canBoost ? "Yes" : "No"}
+ {props.includeDetails
+ ? `\nDetails\n-# ${response.details.replaceAll("\n", "\n-# ")}`
+ : ""}
+
+ );
+}
diff --git a/src/components/PendingApplicationMessage.tsx b/src/components/PendingApplicationMessage.tsx
new file mode 100644
index 0000000..e5f6565
--- /dev/null
+++ b/src/components/PendingApplicationMessage.tsx
@@ -0,0 +1,112 @@
+import { ActionRow } from "components-jsx/ActionRow";
+import { Button } from "components-jsx/Button";
+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 { ButtonStyles, User as OUser } from "oceanic.js";
+import { Response } from "~/types";
+import { User } from "./User";
+import { Constants } from "~/Constants";
+import { ApplicationContent } from "./ApplicationContent";
+
+export function PendingApplicationMessage(props: {
+ id: string;
+ user: OUser;
+ response: Response;
+ locked?: boolean;
+}) {
+ const { id, user, response } = props;
+ const locked = props.locked || false;
+ return (
+
+ {"<@&1375617676139040909>"}
+
+ ## New join request
+
+
+
+
+
+
+ ### Details
+
+ {response.details}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/joinRequestHandler.tsx b/src/joinRequestHandler.tsx
index 8e9a1b6..597d88d 100644
--- a/src/joinRequestHandler.tsx
+++ b/src/joinRequestHandler.tsx
@@ -16,6 +16,8 @@ import { selfappReq } from "./selfappReq";
import { User } from "./components/User";
import { Response } from "./types";
import { match } from "./utils";
+import { PendingApplicationMessage } from "./components/PendingApplicationMessage";
+import { ApplicationContent } from "./components/ApplicationContent";
export async function setupJoinRequestHandler(shard: Shard) {
shard.ws?.on("message", async (d) => {
@@ -52,140 +54,51 @@ export async function setupJoinRequestHandler(shard: Shard) {
const pendingMsg =
await client.rest.channels.createMessage(
Constants.PENDING_CHANNEL_ID,
-
-
- {"<@&1375617676139040909>"}
-
-
-
- ## New join request
-
-
-
-
-
- ### Application
-
- Here for
-
- -# {response.hereFor.join(", ")}
-
- Found through
-
- -#{" "}
- {(() => {
- switch (
- response.foundThrough
- ) {
- case "archive":
- return "Guild Archive/nelly.tools";
- case "tag":
- return 'Hit "Ask to Join" on a clan tag';
- case "user":
- return "User invited them\n-# **Only accept if someone is mentioned in details**";
- case "other":
- return "Something else";
- case "sold":
- return "Was sold an invite\n-# **Only the owner can interact with this application**";
- }
- })()}
-
- Languages
-
- -# {response.languages}
-
- Can boost
-
- -#{" "}
- {response.canBoost
- ? "Yes"
- : "No"}
-
-
-
- ### Details
-
- {response.details}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
);
+
+ const thread = await pendingMsg.startThread({
+ name: `${user.tag}'s application`,
+ autoArchiveDuration: 10080
+ });
+
+ const fullApplicantProfile: any = await selfappReq(
+ `/users/${user.id}/profile`,
+ "GET",
+ {
+ join_request_id: applicationData.request.id
+ }
+ );
+
+ thread.createMessage({
+ embeds: [
+ {
+ color: Constants.COLORS.NEW_REQ,
+ title: "User bio",
+ description:
+ "```\n" +
+ fullApplicantProfile.user_profile
+ .bio +
+ "\n```"
+ }
+ ]
+ });
+
await db.run(
- "INSERT INTO applications (id, user_id, status, message_id, channel_id, responses) VALUES (?, ?, 0, ?, ?, ?)",
+ "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,
- JSON.stringify(response)
+ JSON.stringify(response),
+ thread.id
);
break;
@@ -198,6 +111,10 @@ export async function setupJoinRequestHandler(shard: Shard) {
"SELECT * FROM applications WHERE id=?",
applicationData.id
);
+ const user = await client.rest.users.get(
+ applicationData.user_id
+ );
+
if (application) {
await db.run(
"DELETE FROM applications WHERE id=?",
@@ -208,30 +125,59 @@ export async function setupJoinRequestHandler(shard: Shard) {
application.message_id
);
}
- const user = await client.rest.users.get(
- applicationData.user_id
+
+ const response: Response = JSON.parse(
+ application.responses
);
- await client.rest.channels.createMessage(
+
+ const msg = await client.rest.channels.createMessage(
Constants.REJECTION_CHANNEL_ID,
-
+
## Join request withdrawn
- ### Application
+
{application ? (
- User has applied
+
) : (
+ ### 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)
+ await client.rest.channels.edit(application.thread_id, {
+ locked: true,
+ reason: `${user.tag}'s application has been withdrawn`
+ });
break;
}
}
diff --git a/src/selfappReq.ts b/src/selfappReq.ts
index 3ab9b56..a2d5e11 100644
--- a/src/selfappReq.ts
+++ b/src/selfappReq.ts
@@ -3,12 +3,23 @@ export async function selfappReq(
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE",
data?: object
) {
- return await fetch("https://discord.com/api/v9" + path, {
+ const url =
+ "https://discord.com/api/v9" +
+ path +
+ (() => {
+ if (!data || method !== "GET") return "";
+ // @ts-expect-error
+ return `?${new URLSearchParams(data).toString()}`;
+ })();
+
+ console.log(url);
+
+ return await fetch(url, {
method,
headers: {
Authorization: process.env.USER_TOKEN!,
...(data ? { "Content-Type": "application/json" } : {})
},
- body: data ? JSON.stringify(data || {}) : null
+ body: data && method !== "GET" ? JSON.stringify(data || {}) : null
}).then((e) => e.json());
}