Реакции в приватном диалоге
Что получится
Бот поставит 👍 на сообщение пользователя, а изменения реакции пользователя
придут приложению как durable message_reaction updates с прежним и новым
состоянием.
Что понадобится
- выполненный quickstart по созданию бота и запуску gateway;
- gateway профиля
telegram-v1-core-preview-4наhttp://127.0.0.1:8081; - Python 3,
python-telegram-bot 22.8иSKREPA_BOT_TOKEN; - приватный диалог пользователя с ботом.
message_reaction исключён из default-набора Telegram updates. Его требуется
явно перечислить в allowed_updates; без этого обработчик не увидит реакцию.
Запускаем бота
python3 -m venv .venv
.venv/bin/python -m pip install 'python-telegram-bot==22.8'
Сохраните как reaction_bot.py:
import os
from telegram import ReactionTypeEmoji, Update
from telegram.ext import (
Application,
ContextTypes,
MessageHandler,
MessageReactionHandler,
filters,
)
async def react(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
message = update.effective_message
await context.bot.set_message_reaction(
chat_id=message.chat_id,
message_id=message.message_id,
reaction=[ReactionTypeEmoji("👍")],
)
await message.reply_text("Поставил 👍. Теперь поставьте свою реакцию на этот ответ.")
async def changed(update: Update, _context: ContextTypes.DEFAULT_TYPE) -> None:
change = update.message_reaction
old = [reaction.to_dict() for reaction in change.old_reaction]
new = [reaction.to_dict() for reaction in change.new_reaction]
print(
f"chat_id={change.chat.id} message_id={change.message_id} "
f"old={old} new={new}",
flush=True,
)
application = (
Application.builder()
.token(os.environ["SKREPA_BOT_TOKEN"])
.base_url("http://127.0.0.1:8081/bot")
.base_file_url("http://127.0.0.1:8081/file/bot")
.build()
)
application.add_handler(
MessageHandler(filters.TEXT & filters.ChatType.PRIVATE, react)
)
application.add_handler(MessageReactionHandler(changed))
application.run_polling(
allowed_updates=["message", "message_reaction"]
)
Запустите .venv/bin/python reaction_bot.py.
Действия в клиенте Скрепы
- Отправьте боту любое текстовое сообщение.
- Убедитесь, что на сообщении появилась 👍.
- Поставьте или смените реакцию на сообщении бота.
- Снимите эту реакцию.
Для каждого фактического изменения терминал покажет old=[...] new=[...].
При снятии реакции new будет пустым. Повторная установка уже выбранного emoji
и повторное снятие являются идемпотентными и второго update не создают.
Снять реакцию программно можно пустым списком:
await context.bot.set_message_reaction(
chat_id=chat_id,
message_id=message_id,
reaction=[],
)
Проверяем через curl
Подставьте chat_id и message_id из входящего message update:
set -o pipefail
curl --fail-with-body -sS \
-H 'content-type: application/json' \
-d '{
"chat_id": 217020518514230,
"message_id": 391284761928,
"reaction": [{"type": "emoji", "emoji": "👍"}]
}' \
"http://127.0.0.1:8081/bot${SKREPA_BOT_TOKEN}/setMessageReaction" | jq .
Ответ {"ok":true,"result":true} означает, что новое состояние принято.
Типичные ошибки
- Пользовательские реакции видны в клиенте, но обработчик молчит:
message_reactionотсутствует вallowed_updates. 400наsetMessageReaction: emoji отсутствует в текущем каталоге, передано несколько реакций,custom_emoji, paid reaction илиis_big=true.404для сообщения:chat_idилиmessage_idвзят из другого диалога либо бот ещё не знает это сообщение.- При старте пришли старые updates: подтвердите обработанные события обычным polling offset; библиотека делает это в штатном polling lifecycle.
Границы поддержки
Бот устанавливает одну обычную emoji-реакцию или снимает её в private E2E-DM.
Входящая реакция пользователя может содержать ReactionTypeCustomEmoji, хотя
бот сам такую реакцию установить пока не может. Реакции групп и каналов,
несколько одновременных реакций, paid reactions, anonymous counts и
message_reaction_count в текущий профиль не входят.