Appearance
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 "", 200Register 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.