Skip to main content

Recipes

Recipes are pre-built, parameterized building blocks for common bot patterns β€” guards, confirmations, pagination, retries, broadcasts. Each takes named parameters and provides named handler blocks you fill in.

Editor shortcuts

The recipe insertion palette offers preset templates β€” pre-filled calls with sensible defaults β€” so you can drop in a recipe and edit only what differs. The editor also detects common verbose patterns and suggests the equivalent recipe. For example, if you write send.answer_callback(...) immediately followed by edit.text(...), the editor offers to replace the pair with a single telegram.answerAndEditOrigin call.

guard.adminOnly() {
body { send.text("Secret admin command ran.") }
onDeny { send.text("🚫 Admins only.") }
}

A recipe's handlers (body, onDeny, on_select, …) are written as blocks inside the call. Parameters with ! are required.

Guards​

Gate a body so it runs only when a condition holds; otherwise the deny handler runs.

RecipeSignatureHandlers
guard.adminOnly()β€”body, onDeny
guard.groupOnly()β€”body, onDeny
guard.privateChatOnly()β€”body, onDeny
guard.subscribedOnly()β€”body, onDeny
guard.callbackPayloadMatches(pattern!)pattern: stringbody, onDeny
flow secret on command "/secret" {
guard.adminOnly() {
body { send.text("πŸ” The launch code is 1234.") }
onDeny { send.text("🚫 You can't run this.") }
}
}

Flow helpers​

RecipeSignatureHandlers
flow.confirm(prompt!, yesLabel, noLabel, timeout)a yes/no dialogon_confirm, on_cancel
flow.paginate(items!, page_size, header, doneLabel, timeout)a paginated liston_select, on_done
flow.rateLimit(key!, max!)a shared counter gatebody, on_limited
flow.validateInput(prompt!, validatorExpr!, errorPrompt, max_retries, timeout, localName)ask + validate with retrieson_valid, on_exhausted
flow delete_all on command "/wipe" {
flow.confirm(prompt: "Delete everything? This can't be undone.", yesLabel: "Yes, delete", noLabel: "Cancel", timeout: "60s") {
on_confirm {
set { user.items = [] }
send.text("πŸ—‘ All items deleted.")
}
on_cancel { send.text("Cancelled.") }
}
}
flow set_age on command "/age" {
flow.validateInput(prompt: "How old are you?", validatorExpr: "types.int(value) >= 13", errorPrompt: "Please enter a number 13 or older.", max_retries: 3, timeout: "120s", localName: "age") {
on_valid { send.text(`Thanks! You're ${age}.`) }
on_exhausted { send.text("Too many invalid tries β€” start over with /age.") }
}
}

HTTP​

RecipeSignatureHandlers
http.retry(url!, method, body, headers, max_attempts, backoff, localName)request with backoffonSuccess, onFailed
http.retry(url: "https://api.example.com/data", method: "GET", max_attempts: 3, backoff: "2s", localName: "res") {
onSuccess { send.text(`βœ… ${res.status_code}`) }
onFailed { send.text("❌ Still failing after retries.") }
}

Telegram helpers​

RecipeSignatureNotes
telegram.broadcastMessage(text!)broadcast text to the audience (paced)β€”
telegram.broadcastMedia()broadcast a photo/video/documentβ€”
telegram.broadcastFlow()run a subflow per audience memberβ€”
telegram.statusMessage(text!)send a status message, capture its ref for editingβ€”
telegram.safeEdit(text!, messageRef, fallbackSend)edit a message, fall back to sending if it failsβ€”
telegram.replyAndAutoDelete(text!, ttl)reply, then auto-delete after a delayβ€”
telegram.answerAndEditOrigin(newText!, callbackText)answer a callback and edit its origin messageβ€”
flow loading on command "/work" {
telegram.statusMessage(text: "⏳ Working…")
// … do the work …
telegram.safeEdit(text: "βœ… Done!", fallbackSend: true)
}

See also​