Telegram cron bot
Two cron jobs: one polls Telegram and captures messages into quik.md; the other posts the morning open-todos digest back to your private chat.
Setup
Create a Telegram bot via @BotFather, grab the token. Mint a quik.md API key in Settings → Developer. Drop both into a Cloudflare Worker / Vercel cron / your own box.
Capture loop (every minute)
// poll-telegram.mjs — run on a 1-minute cron
const TG = process.env.TELEGRAM_BOT_TOKEN
const QK = process.env.QUIK_KEY
let offset = Number(globalThis.OFFSET ?? 0)
const updates = await fetch(
`https://api.telegram.org/bot${TG}/getUpdates?offset=${offset}&timeout=0`,
).then((r) => r.json())
for (const u of updates.result ?? []) {
offset = u.update_id + 1
const text = u.message?.text
if (!text) continue
await fetch("https://quik.md/api/v1/capture", {
method: "POST",
headers: {
Authorization: `Bearer ${QK}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ text, organize: true, source: "api" }),
})
}
globalThis.OFFSET = offsetVoice messages: download the file via getFile, then forward the bytes to /api/v1/voice/transcribe; pipe the resulting text back into /api/v1/capture.
Morning digest (07:30 daily)
// morning-digest.mjs — daily cron
const QK = process.env.QUIK_KEY
const TG = process.env.TELEGRAM_BOT_TOKEN
const CHAT = process.env.TELEGRAM_CHAT_ID
const today = new Date()
today.setHours(23, 59, 59, 999)
const r = await fetch(
`https://quik.md/api/v1/items/search?status=todo&due_before=${today.toISOString()}&limit=20`,
{ headers: { Authorization: `Bearer ${QK}` } },
).then((r) => r.json())
const lines = r.items.map((i) => `• ${i.title || i.content_md.slice(0, 80)}`)
const text = lines.length
? `Today's plan:\n${lines.join("\n")}`
: "Inbox zero. Take it easy."
await fetch(`https://api.telegram.org/bot${TG}/sendMessage`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ chat_id: CHAT, text }),
})Toggle from Telegram
Bot replies to the digest message can call POST /api/v1/items/:id/toggle by parsing the item id from the digest line. Or use search → bulk-toggle to mark multiple done from a single message.