🛡️ Скрепа

Inline-поиск

Что получится

Пользователь вызовет бота из поля ввода обычного клиента Скрепы, увидит текстовые варианты и отправит выбранный результат в текущий диалог. Бот также получит chosen_inline_result.

Что понадобится

Inline session всегда инициирует обычный клиент. Вызов answerInlineQuery отвечает на уже открытую сессию и сам по себе её не создаёт.

Запускаем inline-бота

python3 -m venv .venv
.venv/bin/python -m pip install 'python-telegram-bot==22.8'

Сохраните как inline_bot.py:

import os
import uuid

from telegram import InlineQueryResultArticle, InputTextMessageContent, Update
from telegram.ext import (
    Application,
    ChosenInlineResultHandler,
    ContextTypes,
    InlineQueryHandler,
)


async def search(update: Update, _context: ContextTypes.DEFAULT_TYPE) -> None:
    query = update.inline_query.query.strip()
    shown = query or "пустой запрос"
    await update.inline_query.answer(
        [
            InlineQueryResultArticle(
                id=uuid.uuid4().hex,
                title=f"Отправить: {shown}",
                description="Текст попадёт в текущий диалог",
                input_message_content=InputTextMessageContent(
                    f"Результат inline-поиска: {shown}"
                ),
            )
        ],
        is_personal=True,
        cache_time=0,
    )


async def chosen(update: Update, _context: ContextTypes.DEFAULT_TYPE) -> None:
    result = update.chosen_inline_result
    print(
        f"chosen result_id={result.result_id} query={result.query!r}",
        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(InlineQueryHandler(search))
application.add_handler(ChosenInlineResultHandler(chosen))
application.run_polling(
    allowed_updates=["inline_query", "chosen_inline_result"]
)

Запустите .venv/bin/python inline_bot.py.

Действия в клиенте Скрепы

  1. Откройте любой приватный диалог обычного пользователя.
  2. В поле ввода наберите @username_бота поисковая фраза.
  3. Выберите появившуюся карточку.
  4. Убедитесь, что в диалог отправлен текст Результат inline-поиска: поисковая фраза.

В терминале бота должна появиться строка chosen result_id=.... Выбор закрывает inline session. Gateway сохраняет cursor в state_dir, поэтому его рестарт не создаёт второй update для той же сессии.

Как проверить HTTP-контракт

Если вы обрабатываете updates вручную, найдите inline_query.id через getUpdates, затем ответьте:

set -o pipefail
curl --fail-with-body -sS \
  -H 'content-type: application/json' \
  -d "$(jq -n --arg id "$INLINE_QUERY_ID" '{
    inline_query_id: $id,
    results: [{
      type: "article",
      id: "curl-result-1",
      title: "Ответ curl",
      input_message_content: {
        message_text: "Inline-результат из curl"
      }
    }]
  }')" \
  "http://127.0.0.1:8081/bot${SKREPA_BOT_TOKEN}/answerInlineQuery" | jq .

INLINE_QUERY_ID относится к конкретному боту и активен пять минут.

Типичные ошибки

Границы поддержки

Профиль принимает inline results типа article с InputTextMessageContent. Media results, inline media upload и другие типы результатов пока не поддерживаются. Выбранный текст отправляет клиент по обычному E2E-пути после выбора.