Skip to content

Commit

Permalink
fix: get reminders working again (#6)
Browse files Browse the repository at this point in the history
* fix: get reminders working again

* ci: generate prisma types before formatting
  • Loading branch information
stayradiated authored Jul 21, 2023
1 parent 84f38ad commit d782f81
Show file tree
Hide file tree
Showing 18 changed files with 445 additions and 171 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/test.workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,17 @@ jobs:
- name: Install dependencies
run: pnpm install

- name: Generate DB Types
run: pnpm exec prisma generate

- name: Check Code Formatting
run: pnpm run tidy:check
run: pnpm exec xo

- name: Typescript
run: pnpm run build
run: pnpm exec tsc

- name: Migrate Database
run: pnpm run prisma db push
run: pnpm exec prisma db push

- name: Tests
run: pnpm exec vitest --watch=false
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
"semicolon": false,
"prettier": true,
"rules": {
"@typescript-eslint/naming-convention": "off"
"@typescript-eslint/naming-convention": "off",
"no-empty-pattern": "off"
}
},
"prettier": {
Expand Down
30 changes: 30 additions & 0 deletions src/db/delete-user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { errorBoundary } from '@stayradiated/error-boundary'
import { prisma } from './prisma.js'

type DeleteUserOptions = {
userId: string
}

const deleteUser = async (
options: DeleteUserOptions,
): Promise<void | Error> => {
const { userId } = options
return errorBoundary(async () => {
const deletePostItems = prisma.postItem.deleteMany({
where: { post: { userId } },
})
const deletePosts = prisma.post.deleteMany({ where: { userId } })
const deleteReminder = prisma.reminder.deleteMany({
where: { userId },
})
const deleteUser = prisma.user.delete({ where: { id: userId } })
await prisma.$transaction([
deletePostItems,
deletePosts,
deleteReminder,
deleteUser,
])
})
}

export { deleteUser }
9 changes: 6 additions & 3 deletions src/db/get-active-user-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@ import type { UserWithPosts } from './types.js'

// Find users that have posted something in the last 7 days
type GetActiveUserListOptions = {
activeSince: Date
startDate: Date
endDate: Date
}

const getActiveUserList = async (
options: GetActiveUserListOptions,
): Promise<UserWithPosts[] | Error> => {
const { activeSince } = options
const { startDate, endDate } = options

return errorBoundary(async () =>
prisma.user.findMany({
where: {
posts: {
some: {
date: {
gte: activeSince,
gte: startDate,
lte: endDate,
},
items: {
some: {},
Expand Down
2 changes: 1 addition & 1 deletion src/db/get-post-with-items.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as db from './index.js'

describe('getPostWithItems', () => {
const userId = randomUUID()
const date = '2022-08-15T00:00:00+00:00'
const date = new Date('2022-08-15T00:00:00+00:00')

beforeEach(async () => {
const user = await db.upsertUser({
Expand Down
4 changes: 2 additions & 2 deletions src/db/get-post-with-items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { PostWithItems } from './types.js'

type GetPostWithItemsOptions = {
userId: string
date: string
date: Date
}

const getPostWithItems = async (
Expand All @@ -13,7 +13,7 @@ const getPostWithItems = async (
const { userId, date } = options
return errorBoundary(() =>
prisma.post.findUniqueOrThrow({
where: { userDate: { userId, date: new Date(date) } },
where: { userDate: { userId, date } },
include: {
items: {
orderBy: {
Expand Down
1 change: 1 addition & 0 deletions src/db/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './delete-post-item.js'
export * from './delete-user.js'
export * from './get-active-user-list.js'
export * from './get-format-list.js'
export * from './get-post-list-with-items.js'
Expand Down
12 changes: 10 additions & 2 deletions src/db/upsert-post.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import type { Prisma } from '@prisma/client'
import { errorBoundary } from '@stayradiated/error-boundary'
import { prisma } from './prisma.js'

const upsertPost = async (post: Prisma.PostUncheckedCreateInput) =>
type UpsertPostInput = {
userId: string
date: Date
title: string

channel?: string
ts?: string
}

const upsertPost = async (post: UpsertPostInput) =>
errorBoundary(() =>
prisma.post.upsert({
create: post,
Expand Down
18 changes: 12 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ import {
publishPrivateContentToSlack,
} from './publish-to-slack.js'
import { getDateFromTs, getDateFromMessage } from './date-utils.js'
import { checkAndRemindUsers } from './remind-user.js'
import { checkAndRemindUsers } from './lib/remind/index.js'
import {
SLACK_BOT_TOKEN,
SLACK_APP_TOKEN,
HANDOVER_CHANNEL,
HANDOVER_TITLE,
PORT,
SLACK_SIGNING_SECRET,
HANDOVER_DAILY_REMINDER_TIME,
} from './constants.js'
import * as db from './db/index.js'
import { isCommand, execCommand } from './command/index.js'
Expand Down Expand Up @@ -67,7 +68,8 @@ const addHeading = async (
}

const userList = await db.getActiveUserList({
activeSince: dateFns.subDays(dateFns.parseISO(date), 7),
startDate: dateFns.subDays(dateFns.parseISO(date), 7),
endDate: dateFns.endOfDay(dateFns.parseISO(date)),
})
if (userList instanceof Error) {
return userList
Expand All @@ -79,7 +81,7 @@ const addHeading = async (
const upsertPostResult = await db.upsertPost({
userId: user.id,
title: user.name,
date,
date: dateFns.parseISO(date),
})
if (upsertPostResult instanceof Error) {
return upsertPostResult
Expand Down Expand Up @@ -115,7 +117,7 @@ const updateUserPost = async (

const post = await db.getPostWithItems({
userId,
date,
date: dateFns.parseISO(date),
})
if (!post) {
return new Error('Could not find with post with items')
Expand Down Expand Up @@ -165,7 +167,7 @@ const addPostItem = async (
const post = await db.upsertPost({
userId,
title: postTitle,
date: postDate,
date: dateFns.parseISO(postDate),
})
if (post instanceof Error) {
return post
Expand Down Expand Up @@ -402,7 +404,11 @@ const start = async () => {

// Check if there are any users who need reminding to send their handover.
setInterval(async () => {
const result = await checkAndRemindUsers({ web })
const result = await checkAndRemindUsers({
web,
defaultDailyReminderTime: HANDOVER_DAILY_REMINDER_TIME,
daysSinceLastPostCutOff: 7,
})
if (result instanceof Error) {
console.error(result)
}
Expand Down
48 changes: 48 additions & 0 deletions src/lib/remind/check-and-remind-users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { WebClient } from '@slack/web-api'
import { formatDateAsISODate } from '../../date-utils.js'
import { sendReminderToUser } from './send-reminder-to-user.js'
import { findUsersWhoNeedReminder } from './find-users-who-need-reminder.js'

type CheckAndRemindUsersOptions = {
web: WebClient
daysSinceLastPostCutOff: number
defaultDailyReminderTime: string
}
const checkAndRemindUsers = async (
options: CheckAndRemindUsersOptions,
): Promise<void | Error> => {
const { web, daysSinceLastPostCutOff, defaultDailyReminderTime } = options

const instant = Date.now()

const userList = await findUsersWhoNeedReminder({
daysSinceLastPostCutOff,
defaultDailyReminderTime,
})
if (userList instanceof Error) {
return userList
}

const result = await Promise.all(
userList.map(async (user) => {
const userDate = formatDateAsISODate({
instant,
timeZone: user.timeZone,
})

const sendReminderToUserResult = await sendReminderToUser({
web,
user,
userDate,
daysSinceLastPostCutOff,
})

return sendReminderToUserResult
}),
)
if (result instanceof Error) {
return result
}
}

export { checkAndRemindUsers }
Loading

0 comments on commit d782f81

Please sign in to comment.