Yobi.chat

Игры и приложения в диалогах

Бот может предложить действие для двоих — сыграть партию, порисовать вместе, решить квиз — прямо в личном диалоге двух людей. Пользователь открывает диалог с другом, нажимает 📎 → «Игры и приложения» и выбирает действие вашего бота. Собеседник получает приглашение, принимает его, и у обоих открывается ваше мини-приложение с подписанными данными сессии.

Действия бота появляются в окне только у тех, кто уже запускал бота. Если у собеседника бота ещё нет, Yobi предложит запустить его в один шаг прямо из приглашения: бот получит /start activity_<id> и появится у пользователя в чатах.

Работает только в личном диалоге двух людей: не в группах, каналах, «Избранном» и не в чатах с ботами.

Как это устроено

  1. Бот объявляет действия методом setMyActivities.
  2. Пользователь приглашает собеседника — в диалоге появляется карточка «через @ваш_бот», бот получает activity_session со статусом invited.
  3. Собеседник принимает приглашение — бот получает activity_session со статусом active и данными обоих игроков.
  4. Каждый игрок открывает мини-приложение. В initData есть поле activity_session: номер сессии, действие, роль и игроки. Подпись проверяется так же, как обычно.
  5. Ходы и состояние игры передаёт ваш сервер — Yobi в этом не участвует.
  6. Бот обновляет строку на карточке (editActivitySession) и в конце сообщает итог (finishActivitySession).

Объявить действия

curl https://yobi.chat/bot$TOKEN/setMyActivities -H 'Content-Type: application/json' -d '{
  "activities": [
    {"key": "play",  "title": "Сыграть партию", "emoji": "♟", "description": "Классические шахматы", "url": "https://chess.example/app"},
    {"key": "blitz", "title": "Блиц 5 минут",   "emoji": "⏱", "url": "https://chess.example/app?mode=blitz"}
  ]
}'
ПолеЧто это
keyИдентификатор действия: 1–32 символа, латиница в нижнем регистре, цифры и _
titleНазвание в окне и на карточке, до 32 символов
descriptionПояснение, до 128 символов
emojiЗначок действия
urlАдрес мини-приложения (https). Если не указан — главное мини-приложение бота

До 10 действий. getMyActivities возвращает текущий список, deleteMyActivities удаляет все.

Событие activity_session

{
  "update_id": 42,
  "activity_session": {
    "id": "1873",
    "activity_key": "play",
    "status": "active",
    "chat_instance": "a5120",
    "inviter": {"id": 101, "first_name": "Иван"},
    "invitee": {"id": 102, "first_name": "Маша"},
    "status_text": "Ход 12 · ходит Маша",
    "date": 1792210000
  }
}
СтатусКогда
invitedПриглашение отправлено. Поля invitee нет: бот узнаёт собеседника только после согласия
activeПриглашение принято, можно играть
declinedСобеседник отказался
canceledПригласивший отменил приглашение
expiredНикто не ответил за сутки
finishedБот завершил сессию через finishActivitySession

chat_instance одинаков для всех сессий одного диалога — по нему удобно считать счёт между двумя игроками.

Данные мини-приложения

Мини-приложение открывается с обычным initData. Дополнительные поля:

  • activity_session — JSON: {"id": "1873", "key": "play", "role": "inviter", "status": "active", "players": [{"id": 101, "first_name": "Иван"}, {"id": 102, "first_name": "Маша"}]};
  • start_param — activity_1873;
  • chat_type — private, chat_instance — как в событии.

В скрипте моста сессия доступна как Telegram.WebApp.activitySession. Перед тем как доверять данным, проверьте подпись initData на своём сервере — см. Мини-приложения.

Карточка в диалоге

# Строка состояния на карточке, до 64 символов. Только пока сессия идёт.
curl https://yobi.chat/bot$TOKEN/editActivitySession -d session_id=1873 -d 'status_text=Ход 12 · ходит Маша'

# Итог: текст до 128 символов и победители (необязательно).
curl https://yobi.chat/bot$TOKEN/finishActivitySession -H 'Content-Type: application/json' \
  -d '{"session_id": "1873", "result_text": "Мат — победа: Маша", "winner_user_ids": [102]}'

После завершения на карточке появляются кнопки «Реванш» и «Итоги». «Итоги» снова открывает мини-приложение с той же сессией — покажите там финальную позицию или таблицу.

getActivitySession с session_id возвращает объект сессии, если бот пропустил событие.

Пример: шахматы

В репозитории Yobi есть готовый бот examples/chess-bot на Go без внешних зависимостей. Он объявляет действия, проверяет initData, хранит партии, передаёт ходы игрокам через Server-Sent Events, обновляет карточку после каждого хода и сообщает итог.

cd examples/chess-bot
go build -o chess-bot .
./chess-bot -api https://yobi.chat -token 123456:ABC… -public https://chess.example

Токен выдаёт @BotMaker: /newbot. Флаг -public — адрес, по которому веб-сервер бота доступен пользователям; мини-приложение должно открываться по https (на сервере в режиме разработки допускается http).

Что учесть

  • Приглашение из одного диалога от одного бота может быть только одно: новое отменяет предыдущее.
  • Пользователь может отклонить приглашение с пометкой «Не приглашать меня в этого бота» — тогда новые приглашения от этого бота ему не придут.
  • Не больше 5 приглашений в минуту от одного пользователя.
  • Боту не видна переписка диалога: только сам факт приглашения и игроки.