export const RELEASE_NEWS_CHANNEL = "1558048830770122772"; // A webhook ID is public; its secret URL/token must never be stored here. export const RELEASE_WEBHOOK_ID = "1561021045211660401"; export type ReleasePost = { id: string; channel_id: string; webhook_id?: string; content: string; timestamp: string; }; export type ChangelogEntry = { id: string; title: string; version: string; kind: "Alpha" | "Beta" | "Production" | "Bug fix"; body: string; publishedAt: string; }; export function parseReleasePost( post: ReleasePost, webhookId = RELEASE_WEBHOOK_ID, ): ChangelogEntry | null { if (post.webhook_id !== webhookId || !/^\d{17,20}$/.test(post.id)) return null; const clean = post.content .replace(/<@&\d+>/g, "") .replace(/(?:^|\n)\s*PLAY THE MINEGEO AT\s*:[\s\S]*$/i, "") .replace(/^[\s,.]+/, "") .trim(); const header = /^#{1,3}[ \t]+MineGeo[ \t]+(\d+\.\d+\.\d+(?:\.\d+)?)[ \t]+(Alpha|Beta|Production|Bug[ -]fix)([ \t]+[—–:-][^\r\n]*)?[ \t]*\r?\n/i.exec( clean, ); if (!header || !Number.isFinite(Date.parse(post.timestamp))) return null; const body = clean.slice(header[0].length).trim(); if (!body) return null; const kind = /^bug/i.test(header[2]) ? "Bug fix" : ((header[2][0].toUpperCase() + header[2].slice(1).toLowerCase()) as ChangelogEntry["kind"]); return { id: post.id, title: `MineGeo ${header[1]} ${kind}${header[3]?.trimEnd() ?? ""}`, version: header[1], kind, body, publishedAt: post.timestamp, }; }