Skip to content

Sample bots

These have never been run

The gateway is not deployed, so none of this code has been executed against a live server. It is written to be correct, not verified to be correct. Expect to debug it when the platform comes up. Implementation status.

There is no public sample repository — GROM's source is not hosted anywhere public — so the examples live here, in full, rather than behind a link that would 404.

Echo bot

The smallest useful bot: it repeats what you say. Everything else is a variation.

python
import os, requests

API = f"https://api.casinoplaneta.info/bot{os.environ['GROM_TOKEN']}"
offset = None

while True:
    r = requests.get(f"{API}/getUpdates",
                     params={"offset": offset, "timeout": 50}, timeout=60).json()
    if not r["ok"]:
        print("error:", r["description"])
        continue

    for update in r["result"]:
        offset = update["update_id"] + 1          # +1 or it loops forever
        msg = update.get("message")
        if msg and "text" in msg:
            requests.post(f"{API}/sendMessage",
                          json={"chat_id": msg["chat"]["id"], "text": msg["text"]})

Command bot with buttons

Handles /start, shows an inline keyboard, and answers the press. Note the two things beginners miss: answering the callback, and keeping state out of callback_data.

python
import os, requests

API = f"https://api.casinoplaneta.info/bot{os.environ['GROM_TOKEN']}"
offset = None

def call(method, **params):
    return requests.post(f"{API}/{method}", json=params, timeout=60).json()

KEYBOARD = {"inline_keyboard": [[
    {"text": "Tashkent", "callback_data": "city:tashkent"},
    {"text": "Samarkand", "callback_data": "city:samarkand"},
]]}

while True:
    r = requests.get(f"{API}/getUpdates",
                     params={"offset": offset, "timeout": 50}, timeout=60).json()
    if not r["ok"]:
        continue

    for update in r["result"]:
        offset = update["update_id"] + 1

        if msg := update.get("message"):
            if msg.get("text", "").startswith("/start"):
                call("sendMessage", chat_id=msg["chat"]["id"],
                     text="Pick a city:", reply_markup=KEYBOARD)

        elif cb := update.get("callback_query"):
            city = cb["data"].split(":", 1)[1]

            # Answer FIRST. Until you do, the user watches a spinner.
            call("answerCallbackQuery", callback_query_id=cb["id"])

            call("editMessageText",
                 chat_id=cb["message"]["chat"]["id"],
                 message_id=cb["message"]["message_id"],
                 text=f"You picked {city.title()}.")

callback_data is capped at 64 bytes. Put a short key there and keep the real state in your own storage — serialising a payload into it works right up until it doesn't.

Webhook receiver

For production, once you have a public HTTPS endpoint.

python
import os, hmac
from flask import Flask, request, abort

SECRET = os.environ["WEBHOOK_SECRET"]
app = Flask(__name__)
handled = set()          # use a real store; this one dies with the process

@app.post("/hook")
def hook():
    # Anyone who learns your URL can post to it. This check is not optional.
    if not hmac.compare_digest(
            request.headers.get("X-Grom-Bot-Api-Secret-Token", ""), SECRET):
        abort(403)

    update = request.get_json()

    # Delivery is at-least-once: the same update_id will arrive twice sometimes.
    if update["update_id"] in handled:
        return "", 200
    handled.add(update["update_id"])

    # Acknowledge now, work later — retries key off how fast you answer.
    enqueue(update)
    return "", 200

Register it once:

bash
curl "https://api.casinoplaneta.info/bot$GROM_TOKEN/setWebhook" \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://example.com/hook", "secret_token": "'"$WEBHOOK_SECRET"'"}'

Channel poster

No user interaction at all — the bot is an output device. Add it to the channel as an administrator with the right to post, then:

bash
curl "https://api.casinoplaneta.info/bot$GROM_TOKEN/sendMessage" \
  -H 'Content-Type: application/json' \
  -d '{
        "chat_id": "@my_channel",
        "text": "Build *1.4.2* deployed \\- all checks green",
        "parse_mode": "MarkdownV2",
        "disable_notification": true
      }'

Two things to watch. MarkdownV2 requires escaping _ * [ ] ( ) ~ > # + - = | { } . ! in literal text — the \\- above is not a typo, and an unescaped character from an interpolated variable will break the message or forge a link. And @my_channel is convenient but fragile: usernames can be transferred, and your bot would follow the name to its next owner. Store the numeric id once you have it.