ZaminDocs

Echo bot

Foydalanuvchi yozgan matnni javob sifatida qaytaradigan, rasmni esa file_id orqali qayta yuboradigan bot. Long polling, xatolarni ushlash va 429'ni to'g'ri qayta ishlashni ko'rsatadi.

Kod

echo_bot.py
import os
import time

import requests

TOKEN = os.environ["ZAMIN_BOT_TOKEN"]
API = f"https://api.zamin.app/bot{TOKEN}"


def call(method, params=None, http_timeout=15):
    """Bot API metodini chaqiradi; 429 bo'lsa kutib qayta urinadi."""
    for _ in range(3):
        r = requests.post(f"{API}/{method}", json=params or {}, timeout=http_timeout)
        try:
            body = r.json()
        except ValueError:
            raise RuntimeError(f"{method}: HTTP {r.status_code}")
        if body.get("ok"):
            return body["result"]
        retry = (body.get("parameters") or {}).get("retry_after")
        if body.get("error_code") == 429 and retry:
            time.sleep(retry)
            continue
        raise RuntimeError(f"{method}: {body.get('error_code')} {body.get('description')}")
    raise RuntimeError(f"{method}: juda ko'p urinish")


def on_message(message):
    chat_id = message["chat"]["id"]
    text = message.get("text")

    if text == "/start" or (text or "").startswith("/start "):
        name = message["from"]["first_name"]
        call("sendMessage", {"chat_id": chat_id, "text": f"Salom, {name}! Menga biror narsa yozing yoki rasm yuboring."})
    elif text:
        call("sendMessage", {"chat_id": chat_id, "text": text, "reply_to_message_id": message["message_id"]})
    elif "photo" in message:
        # Rasmni qayta yuklamasdan, file_id bilan qaytaramiz
        file_id = message["photo"][-1]["file_id"]
        call("sendPhoto", {"chat_id": chat_id, "photo": file_id, "caption": "Mana rasmingiz 📷"})
    else:
        call("sendMessage", {"chat_id": chat_id, "text": "Hozircha faqat matn va rasmni tushunaman."})


def main():
    me = call("getMe")
    print(f"@{me['username']} ishga tushdi")
    call("deleteWebhook")  # getUpdates webhook bilan birga ishlamaydi
    call("setMyCommands", {"commands": [{"command": "start", "description": "Boshlash"}]})

    offset = None
    while True:
        params = {"timeout": 30, "allowed_updates": ["message"]}
        if offset is not None:
            params["offset"] = offset
        try:
            updates = call("getUpdates", params, http_timeout=40)
        except (requests.RequestException, RuntimeError) as e:
            print("getUpdates xatosi:", e)
            time.sleep(3)
            continue
        for update in updates:
            offset = update["update_id"] + 1
            if "message" in update:
                try:
                    on_message(update["message"])
                except (requests.RequestException, RuntimeError) as e:
                    print("Xato:", e)


if __name__ == "__main__":
    main()

Ishga tushirish

Terminal
pip3 install requests
export ZAMIN_BOT_TOKEN="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
python3 echo_bot.py

Qanday ishlaydi

  • call() har bir metodni JSON bilan chaqiradi; 429 kelsa retry_after soniya kutadi.
  • Boshida deleteWebhook: webhook yoqilgan bo'lsa, getUpdates 409 qaytaradi.
  • offset = update_id + 1 — qayta ishlangan yangilanishlar serverdan o'chadi.
  • Long poll 30 soniya, HTTP kutish 40 soniya — doim long poll'dan uzunroq.
  • Rasm photo[-1].file_id bilan qayta yuboriladi — fayl qayta yuklanmaydi.