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
6 changes: 3 additions & 3 deletions src/bot/commands/checkin/messages/checkin-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Nyala api Tuan/Nona belum dinyalakan hari ini.
🗓 **Date**: ${getParsedNow()}
🔥 **Current Streak**: ${checkinStreak?.streak ?? 0} day(s)
🔎 **Status**: Belum melakukan *check-in*
> *Percikan hari ini belum ditorehkan. Lakukan *check-in* sebelum 23:59 WIB, agar api Tuan/Nona tak meredup.*
> *"Percikan hari ini belum ditorehkan. Lakukan check-in sebelum 23:59 WIB, agar api Tuan/Nona tak meredup."*
`,
WaitingCheckin: (userDiscordId: string, checkin: Checkin) => `
🆔 **Check-In ID**:
Expand All @@ -31,7 +31,7 @@ ${checkin.public_id}
🗓 **Submitted At**: ${getParsedNow(getNow(checkin.created_at))}
🔥 **Current Streak**: ${checkin.checkin_streak!.streak} day(s)
🔎 **Status**: Menunggu peninjauan <@&${FLAMEWARDEN_ROLE}>
> *Percikan telah Tuan/Nona <@${userDiscordId}> titipkan. Mohon menanti sesaat, <@&${FLAMEWARDEN_ROLE}> tengah menakar apakah [nyala tersebut](${checkin.link}) layak menjadi bagian dari perjalanan Tuan/Nona.*
> *"Percikan telah Tuan/Nona <@${userDiscordId}> titipkan. Mohon menanti sesaat, <@&${FLAMEWARDEN_ROLE}> tengah menakar apakah [nyala tersebut](${checkin.link}) layak menjadi bagian dari perjalanan Tuan/Nona."*
`,
ApprovedCheckin: (userDiscordId: string, flamewarden: GuildMember, checkin: Checkin) => `
🆔 **Check-In ID**:
Expand All @@ -45,7 +45,7 @@ ${checkin.public_id}
🗓 **Approved At**: ${getParsedNow(getNow(checkin.updated_at!))}
👀 **Approved By**: ${flamewarden.displayName} (@${flamewarden.user.username})
✍🏻 **${flamewarden.displayName}'(s) Comment**: ${checkin.comment ?? '-'}
> *[Nyala hari ini](${checkin.link}) diterima. Teruslah menenun aksara disiplin, satu hari demi satu hari.*
> *"[Nyala hari ini](${checkin.link}) diterima. Teruslah menenun aksara disiplin, satu hari demi satu hari."*
`,
RejectedCheckin: (userDiscordId: string, flamewarden: GuildMember, checkin: Checkin) => `
🆔 **Check-In ID**:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ Namun jangan berduka, jalan ini selalu terbuka bagi mereka yang bersedia memulai
> Apabila *check-in* Tuan/Nona masih berada dalam status menunggu peninjauan (*waiting*) dan belum memperoleh keputusan hingga mendekati pergantian hari, maka dengan ini disampaikan ketentuan berikut:
> 1. Jangan terlebih dahulu memasuki ⁠<#${IGNITE_PATH_CHANNEL}>, demi menjaga ketertiban alur peninjauan.
> 2. Silakan menjalankan perintah **\`/checkin-status\`** pada <#${AUDIT_FLAME_CHANNEL}> untuk menampilkan status *check-in* terakhir Tuan/Nona.
> 3. Setelah pesan status tersebut muncul, berikan reaksi “❓” pada pesan tersebut.
> 3. Setelah pesan status tersebut muncul, berikan reaksi "❓" pada pesan tersebut.
> 4. Dari reaksi tersebut, sebuah *thread* akan tercipta secara otomatis sebagai ruang klarifikasi dan komunikasi dengan <@&${FLAMEWARDEN_ROLE}>.
> ⏳ Batas waktu penantian atas status WAITING adalah maksimal 1×24 jam sejak *check-in* diajukan.
> ⏳ Batas waktu penantian atas status *WAITING* adalah maksimal 1×24 jam sejak *check-in* diajukan.
`,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ registerGuildMemberUpdateHandler({
if (newHasGrinderRole && !oldHasGrinderRole) {
const channel = await getChannel(newMember.guild, GRIND_ASHES_CHANNEL)
GrinderRole.assertChannel(channel)
const button = GrinderRole.generateButton(newMember.guild.id)

await sendAsBot(
null,
channel,
{ content: GrinderRole.MSG.Greetings(newMember), allowedMentions: { users: [newMember.id], roles: [] } },
{ content: GrinderRole.MSG.Greetings(newMember), components: [button], allowedMentions: { users: [newMember.id], roles: [] } },
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ Sebagai langkah permulaan, perkenankan kami menuntun Tuan/Nona:
Ⅰ. Kunjungilah ⁠<#${CHECKIN_CHANNEL}> untuk menorehkan grind harian pertama kamu.
Ⅱ. Tuliskan apa yang tengah Tuan/Nona tempuh hari ini, entah itu reading, coding, crafting, designing, exercise, ataupun belajar hal baru.
Ⅲ. Nantikan peninjauan dari seorang <@&${FLAMEWARDEN_ROLE}>, yang akan menilai dan mengesahkan *check-in* Tuan/Nona.

`,
WelcomeNotes: `
> Harap diingat dengan saksama:
> Streak Tuan/Nona hanya bermula setelah *check-in* pertama disahkan.
> Apabila hingga pukul 23:59 WIB Tuan/Nona lalai menorehkan *check-in*, maka nyala api akan meredup, dan perjalanan harus dimulai kembali dari awal.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
import { WELCOME_NOTE_BUTTON_ID } from '@events/interaction-create/grinder-role/handlers/button'
import { encodeSnowflake, getCustomId } from '@utils/component'
import { DiscordAssert } from '@utils/discord'
import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js'
import { GrinderRoleMessage } from '../messages'

export class GrinderRole extends GrinderRoleMessage {
static override BASE_PERMS = [
...DiscordAssert.BASE_PERMS,
]

static generateButton(guildId: string): ActionRowBuilder<ButtonBuilder> {
const noteButtonId = getCustomId([WELCOME_NOTE_BUTTON_ID, encodeSnowflake(guildId)])
const noteButton = new ButtonBuilder()
.setCustomId(noteButtonId)
.setLabel('📜 Titah Perjalanan')
.setStyle(ButtonStyle.Primary)

return new ActionRowBuilder<ButtonBuilder>().addComponents(noteButton)
}
}
42 changes: 42 additions & 0 deletions src/bot/events/interaction-create/grinder-role/handlers/button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { TextChannel } from 'discord.js'
import { GrinderRole } from '@events/guild-member-update/grinder-role/validators'
import { EVENT_PATH } from '@events/index'
import { registerInteractionHandler } from '@events/interaction-create/registry'
import { generateCustomId } from '@utils/component'
import { sendReply } from '@utils/discord'
import { DiscordBaseError } from '@utils/discord/error'
import { getModuleName } from '@utils/io'

export class GrinderRoleButtonError extends DiscordBaseError {
constructor(message: string, options?: { cause?: unknown }) {
super('GrinderRoleButtonError', message, options)
}
}

const moduleName = getModuleName(EVENT_PATH, __filename)
export const WELCOME_NOTE_BUTTON_ID = `${generateCustomId(EVENT_PATH, __filename)}`

registerInteractionHandler({
desc: 'Opens welcome note modal for users receiving Grinder roles.',
id: WELCOME_NOTE_BUTTON_ID,
errorTag: () => `${moduleName}: ${GrinderRole.ERR.UnexpectedButton}`,
async exec(_, interaction) {
if (!interaction.isButton())
return

try {
if (!interaction.inCachedGuild())
throw new GrinderRoleButtonError(GrinderRole.ERR.NotGuild)

const channel = interaction.channel as TextChannel
GrinderRole.assertMissPerms(interaction.client.user, channel)

await sendReply(interaction, GrinderRole.MSG.WelcomeNotes)
}
catch (err: any) {
if (err instanceof DiscordBaseError)
await sendReply(interaction, err.message)
else throw err
}
},
})