posts "question of the day" to a discord webhook

Updated dev.ts, main.ts and discordUtils.ts to reflect changes

+62 -71
+14 -28
dev.ts
··· 15 15 */ 16 16 17 17 import { sendDiscordNotification } from "./utils/discordUtils.ts"; 18 - import { getTheme } from "./utils/themes.ts"; 18 + import { 19 + drawNextQuestion, 20 + fetchData, 21 + getAvailableThemes, 22 + } from "./utils/themeUtils.ts"; 19 23 import { parseArgs } from "@std/cli"; 20 24 import { load } from "@std/dotenv"; 21 25 ··· 32 36 index: undefined, 33 37 }, 34 38 }); 35 - 36 - const endpoint = Deno.env.get("SHEET_ENDPOINT"); 37 - if (!endpoint) { 38 - throw new Error("SHEET_ENDPOINT environment variable is not set"); 39 - } 40 39 41 40 let date: Temporal.PlainDate | undefined; 42 41 if (args.date) { ··· 49 48 } 50 49 } 51 50 52 - const { themeName, theme } = getTheme(date); 53 - 54 - const response = await fetch(endpoint); 55 - const data: QuestionsData = await response.json(); 56 - const deck = data[themeName].filter((item) => item.question.trim() !== ""); 57 - 58 - let index: number; 59 - if (args.index) { 60 - index = +args.index; 61 - } else { 62 - // @ts-ignore Deno.openKv is unstable, run with --unstable-kv flag 63 - const kv = await Deno.openKv( 64 - `https://api.deno.com/databases/${ 65 - Deno.env.get("DENO_KV_DATABASE_ID") 66 - }/connect`, 67 - ); 68 - const current = await kv.get<number>(theme.kvKey); 69 - index = current.value ?? 0; 70 - } 51 + const { themes, questions } = await fetchData(); 52 + const available = getAvailableThemes(date, themes); 53 + const { themeName, theme, question } = await drawNextQuestion( 54 + available, 55 + questions, 56 + ); 71 57 72 58 await sendDiscordNotification( 73 - deck[index].question, 74 - deck[index].by, 59 + question, 60 + theme, 75 61 themeName, 76 62 ); 77 63 console.log( 78 - `Dev test: posted ${themeName} question of index ${index} to Discord.`, 64 + `Dev test: posted ${themeName} question of index ${theme.index} to Discord.`, 79 65 );
+25 -28
main.ts
··· 1 1 import { sendDiscordNotification } from "./utils/discordUtils.ts"; 2 - import { getTheme } from "./utils/themes.ts"; 2 + import { 3 + drawNextQuestion, 4 + fetchData, 5 + getAvailableThemes, 6 + } from "./utils/themeUtils.ts"; 3 7 import { load } from "@std/dotenv"; 4 8 5 9 await load({ export: true }); 6 10 7 - const endpoint = Deno.env.get("SHEET_ENDPOINT"); 8 - if (!endpoint) { 9 - throw new Error("SHEET_ENDPOINT environment variable is not set"); 10 - } 11 + Deno.cron("QOTD", Deno.env.get("CRON_STRING")!, async () => { 12 + const date = Temporal.Now.plainDateISO(); 13 + const { themes, questions } = await fetchData(); 14 + const available = getAvailableThemes(date, themes); 15 + const { themeName, theme, question } = await drawNextQuestion( 16 + available, 17 + questions, 18 + ); 11 19 12 - // @ts-ignore Deno.cron is unstable, run with --unstable-cron flag 13 - Deno.cron("QOTD", Deno.env.get("CRON_STRING"), async () => { 14 - const { themeName, theme } = getTheme(); 15 - 16 - // Fetch data 17 - const response = await fetch(endpoint); 18 - const data: QuestionsData = await response.json(); 19 - const deck = data[themeName].filter((item) => item.question.trim() !== ""); 20 - 21 - // Open KV and fetch last index 20 + await sendDiscordNotification( 21 + question, 22 + theme, 23 + themeName, 24 + ); 25 + console.log( 26 + `Cron: posted ${themeName} question of index ${theme.index} to Discord.`, 27 + ); 28 + 22 29 // @ts-ignore Deno.openKv is unstable, run with --unstable-kv flag 23 30 const kv = await Deno.openKv(); 24 - const current = await kv.get<number>(theme.kvKey); 31 + const current = await kv.get<number>([theme.kvKey]); 25 32 const index = current.value ?? 0; 26 - const nextIndex = (index + 1) % deck.length; 33 + const nextIndex = (index + 1) % theme.questionCount!; 27 34 28 35 // Perform atomic operation to update index 29 36 const result = await kv.atomic() 30 37 .check(current) // Ensure the value hasn't changed 31 - .set(theme.kvKey, nextIndex) 38 + .set([theme.kvKey], nextIndex) 32 39 .commit(); 33 40 34 41 if (!result.ok) { 35 42 console.log("Another instance already updated the index, skipping"); 36 43 return; 37 44 } 38 - 39 - // Post to Discord webhook 40 - await sendDiscordNotification( 41 - deck[index].question, 42 - deck[index].by, 43 - themeName, 44 - ); 45 - console.log( 46 - `Cron: posted ${themeName} question of index ${index} to Discord.`, 47 - ); 48 45 });
+23 -15
utils/discordUtils.ts
··· 1 - import { themes } from "./themes.ts"; 2 1 import { load } from "@std/dotenv"; 3 2 4 3 await load({ export: true }); 5 4 6 5 export async function sendDiscordNotification( 7 - question: string, 8 - by?: string, 9 - season: string = "default", 6 + question: Question, 7 + theme: Theme, 8 + themeName?: string, 10 9 ) { 11 - const theme = themes[season] ?? themes.default; 12 - 13 10 const embed1 = { 14 - color: theme.color, 15 - image: theme.image, 11 + color: parseInt(theme.primaryColor), 12 + image: { url: theme.image }, 16 13 }; 17 14 18 15 const embed2 = { 19 - author: theme.author, 20 16 title: theme.title, 21 - color: theme.color, 22 - description: question, 17 + url: "https://tangled.sh/@timtinkers.online/discord-qotd-webhook", 18 + color: parseInt(theme.secondaryColor), 19 + description: question.question, 23 20 fields: [] as Array<{ name: string; value: string; inline: boolean }>, 24 - thumbnail: theme.thumbnail, 25 - footer: theme.footer, 21 + thumbnail: { url: theme.thumbnail }, 22 + footer: { text: theme.footer }, 26 23 }; 27 24 28 - if (by) { 25 + if (question.by) { 29 26 embed2.fields.push( 30 27 { 31 28 name: "question by:", 32 - value: by, 29 + value: question.by, 30 + inline: true, 31 + }, 32 + ); 33 + } 34 + 35 + if (themeName && themeName !== "default") { 36 + embed2.fields.push( 37 + { 38 + name: "deck:", 39 + value: themeName, 33 40 inline: true, 34 41 }, 35 42 ); ··· 58 65 body: JSON.stringify({ 59 66 embeds: [embed1, embed2], 60 67 components: [button], 68 + username: theme.author, 61 69 }), 62 70 }); 63 71