Skip to content

Commit cdf3f54

Browse files
vinit717fakhruddinkwsahsisunnyshreya-mishraprakashchoudhary07
authored
Dev to Main Sync (RealDevSquad#141)
* Auto fetch task which are overdue * added type definitions for taskoverdue, refactored the code and removed the use of any * fixed return type of scheduled func * added fixtures and tests for getDiscordIds func * updated type def for user backend * removed public key from .toml and removed kick command from baseHandler * removed public key * added error message in getDiscordIds.ts * added fixture for taskOverdue, written test for taskOverDue, restructured the code of scheduleEventHandler, altered tests for getDiscordIds, refactored code for taskOverDueDiscordMembers, refactored code for getDiscordIds * forgot to add updated typeDefinitions for taskOverdue * extracted url to url.ts * resolved comments by:bharti * resolving comments * keeping schedule event under comments * error handling in scheduledEventHandler * resolved comments by:bharti * resolving comments by:dipayan * replaced staging url with production * inserted tracking channel id in url * extracted super user discord id to constants * BugFix: /listening (RealDevSquad#126) * bug fix * refactored te code * major fixes * resolved the comments --------- Co-authored-by: Prakash Choudhary <[email protected]> * FEATURE: Add /task command (RealDevSquad#127) * FEATURE: add code changes for /task command * feat(utils): add formatDate and formatTask utility * feat(message): update response format * FEATURE: add code changes for /task command * FEAT: add TASK command to register * Update src/utils/getNickName.ts * REFACTOR: change var name and add try-catch to getNickName fun * TEST: add tet for formatDate and formatStatusToTitleCase function * REFACTOR: extract fetchTasks fun * TEST: add test for fetchTasks * TEST(FIX): fix formatDate test * TEST: improve test coverage of fetchTasks function * TEST: add test for formatTasks function * TEST: fix failed test * TEST: fix failed test * remove console from getNickName.ts * TEST: add test for fetchTask funtion * REFACTOR: changes position of status var * REFACTOR: add try catch to fetchTasks function * FIX: lint * Making Auto fetch Overdue task live (RealDevSquad#134) * Refactor : Task command (RealDevSquad#137) * REFACTOR: add function to get RDS user data and replace formatDate function * TEST: add test for changes * TEST: add more test * REFACTOR: change date format * REFACTOR: change type file extension * FORMAT: fix prettier * /OOO command to get user OOO details (RealDevSquad#129) --------- Co-authored-by: FMK2312 <[email protected]> Co-authored-by: Sunny Sahsi <[email protected]> Co-authored-by: Fakhruddin KW <[email protected]> Co-authored-by: SHREYA MISHRA <[email protected]> Co-authored-by: Prakash Choudhary <[email protected]>
1 parent 0a9df25 commit cdf3f54

File tree

11 files changed

+244
-1
lines changed

11 files changed

+244
-1
lines changed

src/constants/commands.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,16 @@ export const TASK = {
5353
},
5454
],
5555
};
56+
57+
export const OOO = {
58+
name: "ooo",
59+
description: "out-of-office data of the mentioned user",
60+
options: [
61+
{
62+
name: "username",
63+
description: "tag user for that",
64+
type: 6,
65+
required: true,
66+
},
67+
],
68+
};

src/constants/responses.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,5 @@ export const INVALID_NICKNAME_ERROR =
5353
export const NO_TASKS_FOUND = `No tasks found for **{{username}}**.`;
5454
export const TASKS_FETCH_FAILED = "An error occurred while fetching tasks.";
5555
export const FAILED_TO_FETCH_TASKS = `Failed to fetch tasks for **{{assignee}}**.`;
56+
export const USER_NOT_FOUND = `User Not Found`;
57+
export const USER_STATUS_NOT_FOUND = "No Status Found";

src/controllers/baseHandler.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { helloCommand } from "./helloCommand";
33
import { verifyCommand } from "./verifyCommand";
44
import { mentionEachUser } from "./mentionEachUser";
55
import { taskCommand } from "./taskCommand";
6+
import { oooCommand } from "./oooCommand";
67

78
import { getCommandName } from "../utils/getCommandName";
89
import JSONResponse from "../utils/JsonResponse";
@@ -20,6 +21,7 @@ import {
2021
MENTION_EACH,
2122
VERIFY,
2223
TASK,
24+
OOO,
2325
} from "../constants/commands";
2426
import { updateNickName } from "../utils/updateNickname";
2527
import { discordEphemeralResponse } from "../utils/discordEphemeralResponse";
@@ -116,6 +118,10 @@ export async function baseHandler(
116118
const data = message.data?.options as Array<messageRequestDataOptions>;
117119
return await taskCommand(data[0].value, env);
118120
}
121+
case getCommandName(OOO): {
122+
const data = message.data?.options as Array<messageRequestDataOptions>;
123+
return await oooCommand(data[0].value);
124+
}
119125
default: {
120126
return commandNotFound();
121127
}

src/controllers/oooCommand.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { discordTextResponse } from "../utils/discordResponse";
2+
import { formatOOOMessage } from "../utils/formatOOOMessage";
3+
import { getUserOOODetails } from "../utils/getUserOOODetails";
4+
import { UserStatus } from "../typeDefinitions/userStatus.type";
5+
import { USER_NOT_FOUND } from "../constants/responses";
6+
import { getUserDetails } from "../utils/getUserDetails";
7+
8+
export async function oooCommand(discordId: string) {
9+
try {
10+
const userResponse = await getUserDetails(discordId);
11+
if (!userResponse.user) {
12+
return discordTextResponse(USER_NOT_FOUND);
13+
}
14+
const userId = userResponse?.user?.id as string;
15+
const userStatusResponse = await getUserOOODetails(userId);
16+
const responseuser = formatOOOMessage(userStatusResponse as UserStatus);
17+
return discordTextResponse(responseuser);
18+
} catch (error: any) {
19+
return discordTextResponse(USER_NOT_FOUND);
20+
}
21+
}

src/register.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
VERIFY,
55
LISTENING,
66
TASK,
7+
OOO,
78
} from "./constants/commands";
89
import { config } from "dotenv";
910
import { DISCORD_BASE_URL } from "./constants/urls";
@@ -23,7 +24,7 @@ async function registerGuildCommands(
2324
discordApplicationId?: string,
2425
discordGuildId?: string
2526
) {
26-
const commands = [HELLO, VERIFY, MENTION_EACH, LISTENING, TASK];
27+
const commands = [HELLO, VERIFY, MENTION_EACH, LISTENING, TASK, OOO];
2728

2829
try {
2930
if (!discordBotToken) throw new Error("Please provide a BOT TOKEN");
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export interface UserStatus {
2+
id: string;
3+
userId: string;
4+
data: {
5+
userId: string;
6+
currentStatus: {
7+
from: TimeStamp;
8+
until: TimeStamp;
9+
state: "IDLE" | "OOO" | "ACTIVE";
10+
updatedAt: TimeStamp;
11+
message: string;
12+
};
13+
futureStatus?: {
14+
from: TimeStamp;
15+
until: TimeStamp;
16+
state: "IDLE" | "OOO" | "ACTIVE";
17+
updatedAt: TimeStamp;
18+
message: string;
19+
};
20+
monthlyHours?: {
21+
committed: number;
22+
updatedAt: TimeStamp;
23+
};
24+
};
25+
message: string;
26+
}

src/utils/formatOOOMessage.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { UserStatus } from "../typeDefinitions/userStatus.type";
2+
3+
export function formatOOOMessage(userStatusData: UserStatus) {
4+
let msg: string;
5+
const currentStatusState = userStatusData.data.currentStatus.state;
6+
const futureStatusState = userStatusData.data.futureStatus?.state;
7+
if (currentStatusState === "OOO") {
8+
const currentFromDate = new Date(
9+
userStatusData.data.currentStatus.from
10+
).toDateString();
11+
const currentToDate = new Date(
12+
userStatusData.data.currentStatus.until
13+
).toDateString();
14+
msg = `**Current**:\n${currentFromDate} - ${currentToDate}\n ${userStatusData.data.currentStatus.message}\n\n`;
15+
} else if (futureStatusState === "OOO") {
16+
const futureFromDate = new Date(
17+
userStatusData.data.futureStatus?.from
18+
).toDateString();
19+
const futureToDate = new Date(
20+
userStatusData.data.futureStatus?.until
21+
).toDateString();
22+
msg = `**Upcoming**:\n${futureFromDate} - ${futureToDate}\n${userStatusData.data.futureStatus?.message}\n`;
23+
} else {
24+
msg = `User is currently **${currentStatusState}**`;
25+
}
26+
return msg;
27+
}

src/utils/getUserOOODetails.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { USER_STATUS_NOT_FOUND } from "../constants/responses";
2+
import { RDS_BASE_API_URL } from "../constants/urls";
3+
import { UserStatus } from "../typeDefinitions/userStatus.type";
4+
5+
export const getUserOOODetails = async (id: string) => {
6+
try {
7+
const userStatus = await fetch(`${RDS_BASE_API_URL}/users/status/${id}`);
8+
const userStatusData: UserStatus = await userStatus.json();
9+
return userStatusData;
10+
} catch (err) {
11+
return USER_STATUS_NOT_FOUND;
12+
}
13+
};

tests/fixtures/fixture.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import { InteractionType } from "discord-interactions";
88
import { UserBackend } from "../../src/typeDefinitions/userBackend.types";
99
import { TaskOverdueResponse } from "../../src/typeDefinitions/taskOverdue.types";
10+
import { UserStatus } from "../../src/typeDefinitions/userStatus.type";
1011

1112
export const dummyHelloMessage: discordMessageRequest = {
1213
type: InteractionType.APPLICATION_COMMAND,
@@ -194,3 +195,50 @@ export const taskOverdueMock: TaskOverdueResponse = {
194195
},
195196
],
196197
};
198+
199+
export const userStatusMock: UserStatus = {
200+
id: "someId",
201+
userId: "someUserId",
202+
data: {
203+
userId: "someUserId",
204+
currentStatus: {
205+
state: "OOO",
206+
updatedAt: 1691398400000,
207+
from: 1691398400000,
208+
until: 1691484800000,
209+
message: "Out of office message for today",
210+
},
211+
monthlyHours: {
212+
committed: 40,
213+
updatedAt: 1690956800000,
214+
},
215+
},
216+
message: "User Status found successfully.",
217+
};
218+
219+
export const userFutureStatusMock: UserStatus = {
220+
id: "someId",
221+
userId: "someUserId",
222+
data: {
223+
userId: "someUserId",
224+
currentStatus: {
225+
state: "ACTIVE",
226+
updatedAt: 1691398400000,
227+
from: 1691398400000,
228+
until: 1691484800000,
229+
message: "Out of office message for today",
230+
},
231+
futureStatus: {
232+
state: "OOO",
233+
updatedAt: 1691030400000,
234+
from: 1691030400000,
235+
until: 1691116800000,
236+
message: "Upcoming out of office message",
237+
},
238+
monthlyHours: {
239+
committed: 40,
240+
updatedAt: 1690956800000,
241+
},
242+
},
243+
message: "User Status found successfully.",
244+
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { UserStatus } from "../../../src/typeDefinitions/userStatus.type";
2+
import { formatOOOMessage } from "../../../src/utils/formatOOOMessage";
3+
import { userStatusMock, userFutureStatusMock } from "../../fixtures/fixture";
4+
5+
describe("formatOOOMessage", () => {
6+
it("formats an OOO message correctly when current status is OOO", () => {
7+
const currentStatus = userStatusMock.data.currentStatus;
8+
const currentFromDate = new Date(currentStatus.from).toDateString();
9+
const currentToDate = new Date(currentStatus.until).toDateString();
10+
11+
const expectedMessage = `**Current**:\n${currentFromDate} - ${currentToDate}\n${currentStatus.message}\n`;
12+
const result = formatOOOMessage(userStatusMock);
13+
14+
expect(result.replace(/\s/g, "")).toEqual(
15+
expectedMessage.replace(/\s/g, "")
16+
);
17+
});
18+
19+
it("formats an OOO message correctly when the future status is OOO", () => {
20+
const futureStatus = userFutureStatusMock.data.futureStatus;
21+
22+
const futureFromDate = new Date(futureStatus?.from).toDateString();
23+
const futureToDate = new Date(futureStatus?.until).toDateString();
24+
25+
const expectedMessage = `**Upcoming**:\n${futureFromDate} - ${futureToDate}\n${futureStatus?.message}\n`;
26+
const result = formatOOOMessage(userFutureStatusMock);
27+
28+
expect(result).toEqual(expectedMessage);
29+
});
30+
31+
it('returns "No data found!" when no OOO statuses are provided', () => {
32+
const userStatusData: UserStatus = {
33+
...userStatusMock,
34+
data: {
35+
...userStatusMock.data,
36+
currentStatus: {
37+
state: "ACTIVE",
38+
updatedAt: 1691398400000,
39+
from: 1691398400000,
40+
until: 1691484800000,
41+
message: "Active status message",
42+
},
43+
},
44+
};
45+
46+
const expectedMessage = `User is currently **${userStatusData.data.currentStatus.state}**`;
47+
const result = formatOOOMessage(userStatusData);
48+
expect(result).toEqual(expectedMessage);
49+
});
50+
});

0 commit comments

Comments
 (0)