Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions db/migrations/20250810031908_init/migration.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ CREATE TABLE "public"."CheckinStreak" (
"first_date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"last_date" TIMESTAMP(3),
"streak" INTEGER NOT NULL DEFAULT 0,
"streak_broken_at" TIMESTAMP(3) DEFAULT NULL,
"updated_at" TIMESTAMP(3),

CONSTRAINT "CheckinStreak_pkey" PRIMARY KEY ("id")
Expand Down
1 change: 1 addition & 0 deletions db/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ model CheckinStreak {
first_date DateTime @default(now())
last_date DateTime?
streak Int @default(0)
streak_broken_at DateTime?
updated_at DateTime?

user User @relation(fields: [user_id], references: [id])
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ services:
condition: service_healthy
volumes:
- ./src:/usr/src/app/src
- ./db:/usr/src/app/db
- ./db/schema.prisma:/usr/src/app/db/schema.prisma
- ./prisma.config.ts:/usr/src/app/prisma.config.ts
- ./package.json:/usr/src/app/package.json
- ./tsconfig.json:/usr/src/app/tsconfig.json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ export default {
const guild = await client.guilds.fetch(process.env.GUILD_ID!)
const channel = await getChannel(guild, GRIND_ASHES_CHANNEL)
ResetGrinderRoles.assertChannel(channel)
const users = await ResetGrinderRoles.getUsersWithLatestCheckin(client.prisma)
const users = await ResetGrinderRoles.getUsersWithLatestStreak(client.prisma)

await ResetGrinderRoles.validateUsers(guild, channel, users)
await ResetGrinderRoles.validateUsers(client.prisma, guild, channel, users)

log.success(ResetGrinderRoles.MSG.JobSuccess)
})
Expand Down
44 changes: 33 additions & 11 deletions src/bot/events/client-ready/jobs/validators/reset-grinder-roles.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import type { PrismaClient } from '@generatedDB/client'
import type { CheckinStreak } from '@type/checkin-streak'
import type { User } from '@type/user'
import type { Guild, GuildMember, TextChannel } from 'discord.js'
import { getGrindRoles, GRINDER_ROLE } from '@config/discord'
import { isDateToday, isDateYesterday } from '@utils/date'
import { sendAsBot } from '@utils/discord'
import { log } from '@utils/logger'
import { ResetGrinderRolesMessage } from '../messages/reset-grinder-roles'

interface UserWithLatestCheckin {
discord_id: string
checkins: {
status: string
created_at: Date
}[]
}

export class ResetGrinderRoles extends ResetGrinderRolesMessage {
static hasValidCheckin(checkin?: { created_at: Date, status: string }): boolean {
if (!checkin)
Expand All @@ -39,14 +33,19 @@ export class ResetGrinderRoles extends ResetGrinderRolesMessage {
}
}

static async validateUsers(guild: Guild, channel: TextChannel, users: UserWithLatestCheckin[]) {
static async validateUsers(prisma: PrismaClient, guild: Guild, channel: TextChannel, users: User[]) {
for (const user of users) {
const lastCheckin = user.checkins?.[0]
if (this.hasValidCheckin(lastCheckin))
continue

const checkinStreak = user.checkin_streaks?.[0]
if (!checkinStreak)
continue

const member = await guild.members.fetch(user.discord_id)
await this.removeGrinderRoles(member)
await this.breakCheckinStreakAt(prisma, checkinStreak)

await sendAsBot(
null,
Expand All @@ -58,7 +57,7 @@ export class ResetGrinderRoles extends ResetGrinderRolesMessage {
}
}

static async getUsersWithLatestCheckin(prisma: PrismaClient): Promise<UserWithLatestCheckin[]> {
static async getUsersWithLatestStreak(prisma: PrismaClient): Promise<User[]> {
const users = await prisma.user.findMany({
select: {
discord_id: true,
Expand All @@ -70,9 +69,32 @@ export class ResetGrinderRoles extends ResetGrinderRolesMessage {
orderBy: { created_at: 'desc' },
take: 1,
},
checkin_streaks: {
orderBy: { first_date: 'desc' },
take: 1,
where: {
streak_broken_at: null,
},
include: {
checkins: {
orderBy: { created_at: 'desc' },
take: 1,
},
},
},
},
}) as UserWithLatestCheckin[]
}) as User[]

return users
}

static async breakCheckinStreakAt(prisma: PrismaClient, checkinStreak: CheckinStreak) {
await prisma.checkinStreak.update({
where: { id: checkinStreak.id },
data: {
streak_broken_at: new Date(),
updated_at: new Date(),
},
})
}
}
1 change: 1 addition & 0 deletions src/types/checkin-streak.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface CheckinStreak {
first_date: Date
last_date?: Date | null
streak: number
streak_broken_at?: Date | null
updated_at?: Date | null

user?: User
Expand Down