Utility Libraries
Helper libraries for everyday work — formatting, numbers, validation, and small no-key utilities. Most are pure (no network); a few (prices, shorten, fx_rates) call a free public API, so attach on error { }. Import and call like any library:
import format from "format"
let { result } = await format.money(amount: 9.5, symbol: "$") // "$9.50"
units — crypto unit conversion
Pairs with apirone. Converts between display units and smallest units.
| Subflow | Signature → outputs |
|---|---|
satoshi_to_btc | (sats) → {btc, display} |
btc_to_satoshi | (btc) → {sats} |
sun_to_trx | (sun) → {trx, display} |
trx_to_sun | (trx) → {sun} |
format_crypto | (amount, decimals, symbol) → {result} |
fee_pct | (amount, pct) → {fee, net} |
shorten_address | (addr, edge) → {result} |
import units from "units"
let { display } = await units.satoshi_to_btc(sats: 50000000)
send.text(`You received ${display} BTC`)
math_x — advanced numeric helpers
Beyond the math.* builtins. Pure arithmetic.
| Subflow | Signature → outputs |
|---|---|
percentage | (part, whole) → {pct} |
percent_of | (value, pct) → {result} |
round_to | (value, decimals) → {result} |
safe_divide | (a, b) → {result} (0 when b is 0) |
lerp | (a, b, t) → {result} |
ratio | (a, b) → {result} |
avg3 / sum3 / min3 / max3 | (a, b, c) → {result} |
tip | (amount, tip_pct) → {tip_amount, total} |
discount | (price, discount_pct) → {saved, final} |
simple_interest | (principal, rate_pct, years) → {interest, total} |
compound_interest | (principal, rate_pct, years) → {total, interest} |
import math_x from "math_x"
let { tip_amount, total } = await math_x.tip(amount: 42, tip_pct: 18)
send.text(`Tip: ${tip_amount}, total: ${total}`)
validate — input validation
Predicate helpers (best-effort, no regex engine). All pure.
| Subflow | Signature → outputs |
|---|---|
is_empty | (s) → {result} |
is_number | (s) → {result} |
in_range | (n, min, max) → {result} |
length_between | (s, min, max) → {result} |
matches_prefix | (s, prefix) → {result} |
is_email | (s) → {result} |
is_url | (s) → {result} |
is_phone | (s) → {result} |
email_check | (s) → {valid, reason} |
import validate from "validate"
let { valid, reason } = await validate.email_check(s: flow.input)
when !valid { send.text(`Invalid email: ${reason}`) }
is_email, is_url, and is_phone are best-effort heuristics — they catch obvious mistakes but aren't RFC-compliant. For stricter checks use regex.test (see Security & validation).
format — display formatting
| Subflow | Signature → outputs |
|---|---|
money | (amount, symbol) → {result} (e.g. "$9.50") |
percent | (ratio) → {result} (0–1 → "12.3%") |
truncate | (s, n) → {result} |
pad_number | (n, width) → {result} (e.g. "0007") |
yes_no | (b) → {result} ("Yes"/"No") |
pluralize | (n, singular, plural) → {result} |
ordinal | (n) → {result} ("1st", "22nd") |
import format from "format"
let { result } = await format.pluralize(n: user.points, singular: "point", plural: "points")
send.text(`You have ${user.points} ${result}`)
text — string utilities
| Subflow | Signature → outputs |
|---|---|
slugify | (input) → {result} |
clamp | (value, min, max) → {result} |
capitalize | (s) → {result} |
strip_prefix | (s, prefix) → {result} |
ensure_suffix | (s, suffix) → {result} |
word_count | (s) → {count} |
mask_secret | (s, visible) → {result} |
initials | (full_name) → {result} |
title_case | (s) → {result} |
datetime — date/time helpers
Named wrappers around time.*. Time values are opaque.
| Subflow | Signature → outputs |
|---|---|
now_unix | () → {ts} |
format_date | (t, fmt) → {result} |
days_between | (t1, t2) → {days} |
add_duration | (t, dur) → {result} |
is_past | (t) → {result} |
age_from | (birthdate) → {years} |
humanize_seconds | (sec) → {result} |
import datetime from "datetime"
let { result } = await datetime.add_duration(t: time.unix(user.start_ts), dur: "30d")
let { days } = await datetime.days_between(t1: result, t2: time.now())
send.text(`${days} days left`)
antispam — spam heuristics
Pure message-content checks (no network, no state). Score a single message; your bot owns the rate/flood state in shared.* vars.
| Subflow | Signature → outputs |
|---|---|
check | (text, max_links, max_mentions) → {spam, score, reason} |
normalize | (text) → {clean} (folds confusables, lowercases) |
count_links | (text) → {count} |
matches_blocklist | (text, pattern) → {blocked} (regex pattern) |
looks_similar | (a, b, threshold) → {similar, score} (fuzzy near-dupe) |
import antispam from "antispam"
flow guard on message [text] {
let { spam, reason } = await antispam.check(text: message.text, max_links: 2, max_mentions: 5)
when spam {
delete(message)
send.text(`🚫 Removed (${reason})`, chat_id: global.mod_log_id)
}
}
Reference blueprint: group-antispam.botgami.
prices — crypto prices
Live crypto prices via the CoinGecko public API (no key; rate-limited). coin is a CoinGecko id ("bitcoin", "ethereum"); vs is a fiat/crypto code ("usd", "eur", "btc").
| Subflow | Signature → outputs |
|---|---|
get | (coin, vs) → {price, change_24h, symbol, name} |
simple | (coin, vs) → {price} |
import prices from "prices"
flow price on command "/price" {
let { price, change_24h, name } = await prices.get(coin: "bitcoin", vs: "usd") on error {
send.text("Couldn't fetch the price.")
stop
}
send.text(`${name}: $${price} (${change_24h}% 24h)`)
}
shorten — URL shortener
Shorten links via is.gd (no key).
| Subflow | Signature → outputs |
|---|---|
url | (long) → {short} |
custom | (long, slug) → {short} (custom slug) |
import shorten from "shorten"
flow short on command "/short" {
link = ask.text("Send a URL to shorten:")
let { short } = await shorten.url(long: link) on error {
send.text("Couldn't shorten that link.")
stop
}
send.text(`🔗 ${short}`)
}
qr — QR-code images
Build QR-code image URLs (no key — returns a URL you send with send.photo).
| Subflow | Signature → outputs |
|---|---|
image | (data, size) → {url} (QR for arbitrary text, size×size px) |
wifi | (ssid, password, size) → {url} (QR that joins a Wi-Fi network when scanned) |
import qr from "qr"
flow qr on command "/qr" {
let { url } = await qr.image(data: `https://t.me/${bot.username}`, size: 300)
send.photo(url, caption: "Scan to open the bot")
}
See also
- Builtins — lower-level functions these wrap
- Integrations