Skip to content

Commit

Permalink
Merge pull request #10 from theapexlab/APEX-1560-ask-present-ideas-me…
Browse files Browse the repository at this point in the history
…ssage

Apex-1560 - Ask present ideas message
  • Loading branch information
BaDo2001 authored Nov 7, 2023
2 parents 8e383e8 + bf16059 commit 2de4e23
Show file tree
Hide file tree
Showing 24 changed files with 756 additions and 189 deletions.
225 changes: 173 additions & 52 deletions architecture/backend.drawio

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions packages/core/db/queries/getBirthdays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,11 @@ export const getBirthdaysBetween = async (startDate: Dayjs, endDate: Dayjs) => {
where: and(filterStart, filterEnd),
});
};

export const getBirthdays = async (date: Dayjs) =>
db.query.users.findMany({
where: and(
sql`EXTRACT('MONTH' FROM ${users.birthday}) = ${date.month() + 1}`,
sql`EXTRACT('DAY' FROM ${users.birthday}) = ${date.date()}`,
),
});
15 changes: 15 additions & 0 deletions packages/core/db/queries/getTeammates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { and, eq, not } from "drizzle-orm";

import { db } from "@/db/index";
import { users } from "@/db/schema";

export const getTeammates = async (teamId: string, userId: string) => {
const teammates = await db
.select({
id: users.id,
})
.from(users)
.where(and(eq(users.teamId, teamId), not(eq(users.id, userId))));

return teammates.map((teammate) => teammate.id);
};
8 changes: 8 additions & 0 deletions packages/core/events/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ const Events = z.object({
birthday: z.string(),
responseUrl: z.string(),
}),
askPresentIdeasFromTeam: BaseEvent.extend({
birthdayPerson: z.string(),
team: z.string(),
}),
askPresentIdeasFromUser: BaseEvent.extend({
birthdayPerson: z.string(),
user: z.string(),
}),
});

export type Events = z.infer<typeof Events>;
Expand Down
33 changes: 8 additions & 25 deletions packages/core/services/slack/constructAskBirthdayMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import type { ChatPostMessageArguments } from "@slack/web-api";
import type { ChatReplaceMessageArguments } from "@/types/ChatReplaceMessageArguments";
import { pickBirthdayActionId } from "@/types/SlackInteractionRequest";

import { makeTextBlock, makeTextBlockWithDatepicker } from "./messageItems";

type Arguments = {
user: string;
name: string;
Expand All @@ -15,35 +17,16 @@ const constructBaseAskBirthdayMessage = ({
}: Arguments): Omit<ChatPostMessageArguments, "channel"> => ({
text: "Please share your birthday with us! 🥳",
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `Hey ${name}! 👋`,
},
},
{
type: "section",
text: {
type: "mrkdwn",
text: "Please share your birthday with us! 🥳",
},
accessory: {
type: "datepicker",
initial_date: "1995-01-01",
placeholder: {
type: "plain_text",
text: "Select a date",
emoji: true,
},
action_id: pickBirthdayActionId,
},
},
makeTextBlock(`Hey ${name}! 👋`),
makeTextBlockWithDatepicker(
"Please share your birthday with us! 🥳",
pickBirthdayActionId,
),
],
metadata: {
event_type: "askBirthday",
event_payload: {
originalEventId: eventId,
eventId,
},
},
});
Expand Down
34 changes: 34 additions & 0 deletions packages/core/services/slack/constructAskPresentIdeasMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { ChatPostMessageArguments } from "@slack/web-api";

import { makeTextBlock } from "./messageItems";

type Arguments = {
birthdayPerson: string;
user: string;
name: string;
eventId?: string;
};

export const constructAskPresentIdeasMessage = ({
birthdayPerson,
user,
name,
eventId,
}: Arguments): ChatPostMessageArguments =>
({
channel: user,
metadata: {
event_type: "askPresentIdeas",
event_payload: {
eventId: eventId || "",
birthdayPerson,
},
},
text: `Hey, <@${user}>! <@${birthdayPerson}>'s birthday is in 2 months. Do you have any present ideas?`,
blocks: [
makeTextBlock(`Hey ${name}! 👋`),
makeTextBlock(
`It's <@${birthdayPerson}>'s birthday is in 2 months. Do you have any present ideas?`,
),
],
}) satisfies ChatPostMessageArguments;
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
import type { ChatReplaceMessageArguments } from "@/types/ChatReplaceMessageArguments";

import { makeTextBlock } from "./messageItems";

export const constructBirthdayConfirmedMessage =
(): ChatReplaceMessageArguments => ({
replace_original: true,
text: "Thanks for submitting your birthday! 🎉",
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `Thanks for submitting your birthday! 🎉`,
},
},
],
blocks: [makeTextBlock(`Thanks for submitting your birthday! 🎉`)],
});
49 changes: 9 additions & 40 deletions packages/core/services/slack/constructConfirmBirthdayMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,21 @@ import {
birthdayIncorrectActionId,
} from "@/types/SlackInteractionRequest";

import { makeActionsBlock, makeTextBlock } from "./messageItems";

export const constructConfirmBirthdayMessage = (
birthday: string,
): ChatReplaceMessageArguments =>
({
replace_original: true,
text: "Confirm your birthday",
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `Are you sure your birthday is ${birthday}?`,
},
},
{
type: "actions",
elements: [
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: "Yes",
},
style: "primary",
action_id: birthdayConfirmActionId,
value: birthday,
},
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: "No",
},
style: "danger",
action_id: birthdayIncorrectActionId,
value: birthday,
},
],
},
],
metadata: {
event_type: "confirmBirthday",
event_payload: {
makeTextBlock(`Are you sure your birthday is ${birthday}?`),
makeActionsBlock(
birthdayConfirmActionId,
birthdayIncorrectActionId,
birthday,
},
},
"",
),
],
}) satisfies ChatReplaceMessageArguments;
42 changes: 19 additions & 23 deletions packages/core/services/slack/constructIceBreakerQuestion.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { ChatPostMessageArguments, KnownBlock } from "@slack/web-api";

import { makeTextBlock } from "./messageItems";

type Arguments = {
users: string[];
channel: string;
Expand All @@ -10,41 +12,35 @@ const iceBreakerQuestions = [
"Hey Guys! What was the last item that you were window shopping for?",
];

export const constructIceBreakerQuestion = (
args: Arguments,
): ChatPostMessageArguments => {
export const constructIceBreakerQuestion = ({
users,
channel,
eventId,
}: Arguments): ChatPostMessageArguments => {
const randomIceBreakerQuestion =
iceBreakerQuestions[Math.floor(Math.random() * iceBreakerQuestions.length)];

const blocks: KnownBlock[] = [
{
type: "section",
text: {
type: "mrkdwn",
text: `${randomIceBreakerQuestion} Post your picks in the thread! 👇`,
},
},
makeTextBlock(
`${randomIceBreakerQuestion} Post your picks in the thread! 👇`,
),
];

if (args.users.length) {
blocks.push({
type: "section",
text: {
type: "mrkdwn",
text: `Let's see your ones ${args.users
.map((user) => `<@${user}>`)
.join(", ")}!`,
},
});
if (users.length) {
blocks.push(
makeTextBlock(
`Let's see your ones ${users.map((user) => `<@${user}>`).join(", ")}!`,
),
);
}

return {
channel: args.channel,
metadata: args.eventId
channel: channel,
metadata: eventId
? {
event_type: "iceBreakerQuestion",
event_payload: {
eventId: args.eventId,
eventId: eventId,
},
}
: undefined,
Expand Down
59 changes: 59 additions & 0 deletions packages/core/services/slack/messageItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { ActionsBlock, SectionBlock } from "@slack/web-api";

export const makeTextBlock = (text: string): SectionBlock => ({
type: "section",
text: {
type: "mrkdwn",
text,
},
});

export const makeTextBlockWithDatepicker = (
text: string,
actionId: string,
): SectionBlock => ({
...makeTextBlock(text),
accessory: {
type: "datepicker",
initial_date: "1995-01-01",
placeholder: {
type: "plain_text",
text: "Select a date",
emoji: true,
},
action_id: actionId,
},
});

export const makeActionsBlock = (
yesActionId: string,
noActionId: string,
yesValue: string,
noValue: string,
): ActionsBlock => ({
type: "actions",
elements: [
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: "Yes",
},
style: "primary",
action_id: yesActionId,
value: yesValue,
},
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: "No",
},
style: "danger",
action_id: noActionId,
value: noValue,
},
],
});
29 changes: 29 additions & 0 deletions packages/functions/cron/daily.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";

dayjs.extend(utc);

import { getBirthdays } from "@/db/queries/getBirthdays";
import { publishEvent } from "@/utils/eventBridge/publishEvent";
import { cronHandler } from "@/utils/lambda/cronHandler";

export const handler = cronHandler(async (eventId?: string) => {
const today = dayjs().utc().startOf("day");

const users = await getBirthdays(today.add(2, "month"));

await Promise.all(
users.map((user) =>
publishEvent("askPresentIdeasFromTeam", {
team: user.teamId,
birthdayPerson: user.id,
eventId,
}),
),
);

return {
users,
message: users.length ? "Sent present ideas requests" : "No birthdays",
};
});
Loading

0 comments on commit 2de4e23

Please sign in to comment.