Skip to content

Commit c1916fb

Browse files
DashDeipayanvvaibhavdesaiRitikJaiswal75
authored
Sync dev to main (#72)
* feat: mention each command with series support (#69) * feat: registering commands * feat: add commands * feat: add types for command * feat: adding logic for mention each * feat: mention each logic to respond with users who have role mentioned in the message * feat: adding types because i have to :O * feat: sweet logic which returns me the users who have roles mentioned in the command * feat: changed the input args for the function * feat: tested with cases * feat: tested with cases * refact: imports and some beauties XD * created: types file cause had to * nuked: cause renamed ito * feat: common who doesnt like smaller util functions? * refact: imports * chore: to handle pre hooks * chore: annoying linter * chore: annoying linter * refactor: resolving PR comments * refactor: sorting imports as well as fix for pr comments * chore: because lint decided to be pain in my code * chore: resolving comments for PR * chore: XD * Member data validation (#70) * added controller to get user details * added endpoint for getting discord member details * added new test * changed user-id to discord-id --------- Co-authored-by: Vaibhav Desai <[email protected]> Co-authored-by: Ritik Jaiswal <[email protected]>
1 parent 9eb00b8 commit c1916fb

15 files changed

+464
-8
lines changed

src/constants/commands.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,63 @@ export const VERIFY = {
88
description:
99
"Generate a link with user specific token to link with RDS backend.",
1010
};
11+
12+
export const MENTION_EACH = {
13+
name: "mention",
14+
description: "mention each user with this role",
15+
options: [
16+
{
17+
name: "list",
18+
description: "get user in list",
19+
type: 2, // 2 is type SUB_COMMAND_GROUP
20+
options: [
21+
{
22+
name: "get",
23+
description: "get me the role ",
24+
type: 1, // 1 is type SUB_COMMAND
25+
options: [
26+
{
27+
name: "user",
28+
description: "The user to get",
29+
type: 9, // 6 is type USER
30+
required: true,
31+
},
32+
{
33+
name: "message",
34+
description: "What message to send to user ?",
35+
type: 3, // 7 is type CHANNEL
36+
required: true,
37+
},
38+
],
39+
},
40+
],
41+
},
42+
{
43+
name: "series",
44+
description: "get user in series",
45+
type: 2,
46+
options: [
47+
{
48+
name: "get",
49+
description: "get me the role",
50+
type: 1,
51+
options: [
52+
{
53+
name: "user",
54+
description: "The user to get",
55+
type: 9, // 8 is type ROLE
56+
required: true,
57+
},
58+
{
59+
name: "message",
60+
description:
61+
"The channel permissions to get. If omitted, the guild permissions will be returned",
62+
type: 3,
63+
required: true,
64+
},
65+
],
66+
},
67+
],
68+
},
69+
],
70+
};

src/controllers/baseHandler.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
1-
import { HELLO, VERIFY } from "../constants/commands";
2-
import { env } from "../typeDefinitions/default.types";
3-
import { discordMessageRequest } from "../typeDefinitions/discordMessage.types";
4-
import { getCommandName } from "../utils/getCommandName";
5-
import JSONResponse from "../utils/JsonResponse";
6-
import { lowerCaseMessageCommands } from "../utils/lowerCaseMessageCommand";
71
import { commandNotFound } from "./commandNotFound";
82
import { helloCommand } from "./helloCommand";
93
import { verifyCommand } from "./verifyCommand";
4+
import { mentionEachUser } from "./mentionEachUser";
5+
6+
import { getCommandName } from "../utils/getCommandName";
7+
import JSONResponse from "../utils/JsonResponse";
8+
import { lowerCaseMessageCommands } from "../utils/lowerCaseMessageCommand";
9+
10+
import { env } from "../typeDefinitions/default.types";
11+
import {
12+
discordMessageRequest,
13+
messageRequestDataOptions,
14+
} from "../typeDefinitions/discordMessage.types";
15+
16+
import { HELLO, MENTION_EACH, VERIFY } from "../constants/commands";
1017

1118
export async function baseHandler(
1219
message: discordMessageRequest,
1320
env: env
1421
): Promise<JSONResponse> {
1522
const command = lowerCaseMessageCommands(message);
23+
1624
switch (command) {
1725
case getCommandName(HELLO): {
1826
return helloCommand(message.member.user.id);
@@ -26,6 +34,17 @@ export async function baseHandler(
2634
env
2735
);
2836
}
37+
case getCommandName(MENTION_EACH): {
38+
const data = message.data?.options as Array<messageRequestDataOptions>;
39+
40+
return await mentionEachUser(
41+
{
42+
displayType: data[0].name,
43+
options: data[0].options[0].options,
44+
},
45+
env
46+
);
47+
}
2948
default: {
3049
return commandNotFound();
3150
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import * as response from "../constants/responses";
2+
import { env } from "../typeDefinitions/default.types";
3+
import JSONResponse from "../utils/JsonResponse";
4+
import { IRequest } from "itty-router";
5+
import { verifyAuthToken } from "../utils/verifyAuthToken";
6+
import { getGuildMemberDetails } from "../utils/getGuildMemberDetails";
7+
8+
export async function getGuildMemberDetailsHandler(
9+
request: IRequest,
10+
env: env
11+
) {
12+
const authHeader = request.headers.get("Authorization");
13+
if (!authHeader) {
14+
return new JSONResponse(response.BAD_SIGNATURE);
15+
}
16+
try {
17+
await verifyAuthToken(authHeader, env);
18+
19+
const { id: discordId } = request.params;
20+
21+
const res = await getGuildMemberDetails(discordId, env);
22+
return new JSONResponse(res);
23+
} catch (err) {
24+
return new JSONResponse(response.BAD_SIGNATURE);
25+
}
26+
}

src/controllers/mentionEachUser.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { discordTextResponse } from "../utils/discordResponse";
2+
import { filterUserByRoles } from "../utils/filterUsersByRole";
3+
import { getMembersInServer } from "../utils/getMembersInServer";
4+
5+
import { env } from "../typeDefinitions/default.types";
6+
import {
7+
UserArray,
8+
MentionEachUserOptions,
9+
} from "../typeDefinitions/filterUsersByRole";
10+
import { checkDisplayType } from "../utils/checkDisplayType";
11+
12+
export async function mentionEachUser(
13+
message: { displayType: string; options: Array<MentionEachUserOptions> },
14+
env: env
15+
) {
16+
const getMembersInServerResponse = await getMembersInServer(env);
17+
18+
// displaytype is list or series & options is first level of options array on desctructure
19+
const { displayType, options } = message;
20+
const [roleToBeTaggedObj, displayMessageObj] = options;
21+
22+
const roleId = roleToBeTaggedObj.value;
23+
const msgToBeSent = displayMessageObj.value;
24+
25+
const usersWithMatchingRole = filterUserByRoles(
26+
getMembersInServerResponse as UserArray[],
27+
roleId
28+
);
29+
30+
const responseData = checkDisplayType({
31+
displayType,
32+
msgToBeSent,
33+
usersWithMatchingRole,
34+
});
35+
return discordTextResponse(responseData);
36+
}

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from "./controllers/guildRoleHandler";
1313
import { getMembersInServerHandler } from "./controllers/getMembersInServer";
1414
import { changeNickname } from "./controllers/changeNickname";
15+
import { getGuildMemberDetailsHandler } from "./controllers/getGuildMemberDetailsHandler";
1516

1617
const router = Router();
1718

@@ -29,6 +30,8 @@ router.put("/roles/add", addGroupRoleHandler);
2930

3031
router.get("/discord-members", getMembersInServerHandler);
3132

33+
router.get("/member/:id", getGuildMemberDetailsHandler);
34+
3235
router.post("/", async (request, env) => {
3336
const message: discordMessageRequest = await request.json();
3437
if (message.type === InteractionType.PING) {

src/register.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { HELLO, VERIFY } from "./constants/commands";
1+
import { HELLO, MENTION_EACH, VERIFY } from "./constants/commands";
22
import { config } from "dotenv";
33
import { DISCORD_BASE_URL } from "./constants/urls";
44
import { registerCommands } from "./utils/registerCommands";
@@ -17,7 +17,7 @@ async function registerGuildCommands(
1717
discordApplicationId?: string,
1818
discordGuildId?: string
1919
) {
20-
const commands = [HELLO, VERIFY];
20+
const commands = [HELLO, VERIFY, MENTION_EACH];
2121

2222
try {
2323
if (!discordBotToken) throw new Error("Please provide a BOT TOKEN");

src/typeDefinitions/discordMessage.types.d.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface messageRequestDataOptions {
1414
name: string;
1515
type: number;
1616
value: string;
17+
options: Array<messageRequestDataOptions>;
1718
}
1819

1920
export interface messageRequestMember {
@@ -52,3 +53,30 @@ export interface guildRoleResponse {
5253
mentionable: boolean;
5354
tags?: object;
5455
}
56+
57+
export interface discordMemberDetails {
58+
avatar: string;
59+
communication_disabled_until: string;
60+
flags: number;
61+
joined_at: string;
62+
nick: string;
63+
pending: boolean;
64+
premium_since: string;
65+
roles: Array<string>;
66+
user: {
67+
id: string;
68+
username: string;
69+
avatar: string;
70+
discriminator: string;
71+
public_flags: number;
72+
flags: number;
73+
banner: string;
74+
accent_color: string;
75+
global_name: string;
76+
avatar_decoration: string;
77+
display_name: string;
78+
banner_color: string;
79+
};
80+
mute: boolean;
81+
deaf: boolean;
82+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export type UserArray = {
2+
user: {
3+
id: string;
4+
};
5+
roles: string[];
6+
};
7+
8+
export type MentionEachUserOptions = {
9+
name: string;
10+
type: number;
11+
value: string;
12+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
export interface commandTypes {
22
name: string;
33
description: string;
4+
type?: number;
5+
required?: boolean;
6+
options?: commandTypes[];
47
}

src/utils/checkDisplayType.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export function checkDisplayType({
2+
displayType,
3+
msgToBeSent,
4+
usersWithMatchingRole,
5+
}: {
6+
displayType: string;
7+
msgToBeSent: string;
8+
usersWithMatchingRole: string[];
9+
}) {
10+
if (displayType === "list") {
11+
return `Coming soon. We are working on this feature. We feel sorry for not serving you what you expect this command to do for now.(T_T)`;
12+
} else {
13+
if (usersWithMatchingRole.length > 0) {
14+
return `${displayType && msgToBeSent} ${usersWithMatchingRole}`;
15+
} else {
16+
return `Sorry no user found under this role.`;
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)