This commit is contained in:
2026-08-23 09:22:35 +07:00
commit 78939e24f1
8 changed files with 163 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
node_modules/
.env.vars
.env
wrangler.toml
src/feat/birthdays.json
+20
View File
@@ -0,0 +1,20 @@
```
┌─ minute 0
│ ┌─ hour 17
│ │ ┌─ day *
│ │ │ ┌─ month *
│ │ │ │ ┌─ weekday *
│ │ │ │ │
0 17 * * *
```
its in UTC+00, so
```
UTC cron time = UTC+7 desired time − 7 hours
00:00 − 07:00 = 17:00 UTC
17:00 UTC
+ 7 hours
----------
00:00 UTC+7
```
+40
View File
@@ -0,0 +1,40 @@
import type { Env } from "../env"
const DISCORD_API = "https://discord.com/api/v10"
// no embedbuilder cuz fuck you
export interface DiscordEmbed
{
title?: string
description?: string
fields?: Array<{
name: string
value: string
inline?: boolean
}>
footer?: {
text: string
}
}
export async function editMessage(env: Env, content: string | null, embeds: DiscordEmbed[] = []): Promise<void>
{
const response = await fetch(`${DISCORD_API}/channels/${env.DISCORD_CHANNEL_ID}/messages/${env.DISCORD_MESSAGE_ID}`, {
method: "PATCH",
headers: {
"Authorization": `Bot ${env.DISCORD_BOT_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
content,
embeds
})
})
if (!response.ok)
{
const body = await response.text()
throw new Error(`fuckass discord returned ${response.status}: ${body}`)
}
}
+6
View File
@@ -0,0 +1,6 @@
export interface Env
{
DISCORD_BOT_TOKEN: string
DISCORD_CHANNEL_ID: string
DISCORD_MESSAGE_ID: string
}
+25
View File
@@ -0,0 +1,25 @@
import birthdays from "./birthdays.json"
import type { DiscordEmbed } from "../discord/mod"
interface Birthdays
{
[date: string]: string[]
}
export function getBirthdays(date: string): string[]
{
return (birthdays as Birthdays)[date] ?? []
}
export function createBirthdayEmbed(date: string): DiscordEmbed
{
const names = getBirthdays(date)
return {
fields: [{
name: "Today's Birthdays",
value: names.length > 0 ? names.map(name => `- ${name}`).join("\n") : "No birthdays today.",
inline: false
}]
}
}
+41
View File
@@ -0,0 +1,41 @@
import type { Env } from "./env"
import { editMessage } from "./discord/mod"
import { getToday } from "./utils/date"
import { createBirthdayEmbed } from "./feat/birthdays"
async function updateMessage(env: Env): Promise<void>
{
await editMessage(
env,
`Last updated: <t:${Math.floor(Date.now() / 1000)}:F>`,
[ // embeds
createBirthdayEmbed(getToday("Asia/Jakarta"))
]
)
}
export default
{
async fetch(request: Request, env: Env): Promise<Response>
{
const url = new URL(request.url)
if (url.pathname === "/invoke")
{
await updateMessage(env)
return new Response("Discord message updated")
}
return new Response("Not Found", {
status: 404
})
},
async scheduled(_event: ScheduledEvent, env: Env, _ctx: ExecutionContext): Promise<void>
{
await updateMessage(env)
}
}
+12
View File
@@ -0,0 +1,12 @@
export function getToday(timeZone = "Asia/Jakarta"): string
{
/*
* Intl API cuz i can :P
*/
return new Intl.DateTimeFormat("en-US", {
timeZone,
month: "2-digit",
day: "2-digit"
})
.format(new Date())
}
+11
View File
@@ -0,0 +1,11 @@
name = "meowl-cron"
main = "src/index.ts"
compatibility_date = "2025-07-18"
[triggers]
crons = ["0 17 * * *"]
[vars]
DISCORD_CHANNEL_ID = ""
DISCORD_MESSAGE_ID = ""
DISCORD_BOT_TOKEN = ""