简体中文 English 繁體中文 日本語 Русский
本文为静态镜像,内容以交互版为准 在交互式文档中心打开 →

Руководство по стандартизации адаптеров (общие положения)

Данный документ представляет собой общее положение стандартизации адаптеров ErisPulse: устанавливает принципы и стандарты стандартизации для кроссплатформенного использования, карту стандартов, режимы обработки различий, процесс введения новых возможностей в стандарт и дает полное определение стандартов интерактивных компонентов (кнопки/клавиатура, выпадающий выбор и т.д.) и событий обратного вызова интерактивных действий. Любые разработчики адаптеров при реализации новых функций должны в первую очередь использовать стандартные определения, чтобы разработчики модулей могли получить последовательный опыт на любой платформе с помощью одного и того же кода — с одинаковыми именами, параметрами и возвращаемыми значениями.


1. Принципы стандартизации

  1. Единообразное наименование: Одно и то же понятие на всех платформах должно иметь одинаковое наименование (например, отмена сообщения — delete_message, набор кнопок — keyboard), не завися от платформы.
  2. Единообразные параметры: Структура параметров стандартных действий/сегментов/методов должна оставаться одинаковой на всех платформах; платформенно-специфичные параметры предоставляются как необязательные расширенные параметры или расширенные поля, не загрязняя стандартный сигнатуру.
  3. Единообразные возвращаемые значения: Все вызовы API/отправки должны возвращать стандартную структуру ответа (status/retcode/data/message_id/message), стандартные поля в data (например, user_id/user_name) должны иметь одинаковую семантику; платформенно-специфичные данные помещаются в {platform}_raw.
  4. Обоснованное расширение: Платформенно-специфичные возможности должны иметь префикс {platform}_ (сегмент: yunhu_form; действие: yunhu.board; поле события: qqbot_button_id), четко указывая, что они не являются кроссплатформенными.
  5. Абсорбция различий на уровне адаптера: Модульный код должен быть ориентирован на стандартное программирование, а различия между платформами должны обрабатываться адаптером (маппинг параметров, стандартизация полей, снижение возможностей), без необходимости написания платформенно-специфичных ветвлений в модуле.
  6. Не критическое снижение возможностей: При отсутствии поддержки какой-либо стандартной возможности платформой, должна происходить элегантная деградация (возвращается retcode=10002, компоненты преобразуются в текст и помещаются в alt_message), без выброса исключений и прерывания логики модуля.

2. Стандартные карты

Область Стандартный документ Охватываемое содержимое
Преобразование событий Стандарт преобразования событий Структура событий, стандартные сегменты сообщений (text/image/mention/reply/keyboard и др.), стандартные расширения платформы
Интерактивные компоненты Этот документ §5 Кнопки/клавиатуры, выпадающие списки, карточки, стандартные поля событий обратной связи, соглашения о модификаторах, сопоставление с платформами
API-действия Стандарт API-действий Стандартные действия OneBot12 (управление пользователями/группами/каналами/сообщениями/мета-действия) с единым интерфейсом и ApiDSL
Запросы и операции Спецификация запросов и операций Поля событий запроса (request_id) и DSL запросов (approve/reject)
Методы отправки Спецификация методов отправки Назначение, параметры, модификаторы и обратное преобразование (OB12→платформа) методов класса Send
Типы сессий Стандарт типов сессий Определения и сопоставления типов сессий (user/group/channel/guild/dms)
Ответы API Стандарт ответов API Стандартная структура ответа и соглашение о retcode

3. Стандартизированный рабочий процесс (Как новые возможности попадают в стандарт)

Платформенные специфические возможности ({platform}_ префикс)
        │  ≥2 платформы имеют подобные возможности
        ▼
Выявление общих черт (извлечение общих концепций и подмножества параметров)
        │
        ▼
Проект стандарта (название + параметры + возвращаемое значение + таблица соответствия для каждой платформы)
        │  Обзор
        ▼
Включение в общее руководство / документы по стандартам для различных областей + реализация базового класса фреймворка / адаптеров для обеспечения совместимости
        │
        ▼
Стандартные сегменты / действия (без префикса) — модули могут использоваться на разных платформах

Пример: Кнопка изначально реализовывалась независимо на каждой платформе (telegram_inline_keyboard / Yunhu buttons / QQBot keyboard) → появляется на ≥3 платформах → извлекается общая структура (label/type/data + rows) → публикуется стандартный сегмент keyboard → адаптеры реализуют слой совместимости (декоратор принимает общую структуру + преобразование стандартного сегмента + прямая передача оригинального сегмента).

3.1 Правила именования

Объект Правило Пример
Стандартный сегмент сообщения Нижний регистр, общая концепция без префикса keyboard, select, mention
Расширенный сегмент платформы Префикс {platform}_ telegram_sticker, yunhu_form
Стандартное API действие Стандартное имя OB12 (snake_case) get_group_info, delete_message
Расширенное действие платформы Префикс {platform}. или общее имя протокола yunhu.board, send_poke (расширение OB11)
Декоратор PascalCase, общая возможность в базовом классе фреймворка .Keyboard(rows), .At(uid)
Стандартное поле события Общая концепция без префикса interaction_id, button_data, request_id
Поле события платформы Префикс {platform}_ qqbot_event_id, telegram_chat_id

3.2 Правила параметров и возвращаемых значений

4. Режимы обработки различий (уровень адаптера)

Режим Описание Пример
Отображение параметров Стандартные параметры → параметры платформы delete_message(message_id) → TG deleteMessage(chat_id, message_id) (дополнение chat_id из регистра)
Преобразование структуры Стандартный сегмент → структура платформы Сегмент keyboard → inline_keyboard / buttons / клавиатура QQBot
Отображение действий Стандартное имя действия → имя действия платформы get_self_info → get_login_info (OB11)
Стандартизация полей Ответ платформы → стандартные поля getMe() → {user_id, user_name, user_displayname}
Синтез идентификатора Генерация определенного ID, когда платформа не имеет оригинального идентификатора Запрос на присоединение TG без ID → tjr_{chat}_{user}_{date}
Деградация возможностей Текстуализация / возврат 10002 при отсутствии поддержки Kook без клавиатуры → alt_message в текстовом формате; get_friend_list → 10002
Нормализация Платформенные "грязные" данные → стандартный формат Отметка @ в QQBot openid → bot_id (нормализация имени)
Двухмаршрутная совместимость Стандартная структура и структура платформы одновременно принимаются .Keyboard() принимает общие rows или оригинальную структуру

5. Стандартные интерактивные компоненты

5.1 Список компонентов и состояния

Компонент Стандартный тип сегмента Состояние Поддерживаемые платформы
Кнопка/клавиатура (keyboard) keyboard ✅ Стандартизирован Telegram / Yunhu / QQBot
Выпадающий список (select) select 📋 Зарезервировано (структура см. §5.4) Discord / Telegram(bot)
Карточка (card) card 📋 Зарезервировано (см. §5.5) Kook / Yunhu(html)
Модальное окно (modal) modal 📋 Зарезервировано Discord

Правила иерархии модификаторов: Модификаторы отправки для общих интерактивных компонентов реализуются в Send-классе адаптера (базовый класс фреймворка не содержит их), именование следует §5.2, параметры соответствуют стандартной структуре данного документа.

5.2 keyboard Кнопка/внутренняя клавиатура

Структура сегмента сообщения (направление отправки)

{
  "type": "keyboard",
  "data": {
    "rows": [
      [
        {"label": "Опция A", "type": "callback", "data": "vote:A"},
        {"label": "Официальный сайт", "type": "link", "data": "https://example.com"}
      ]
    ]
  }
}
Поле Тип Обязательно Описание
data.rows Двумерный массив Да Каждый подмассив — строка кнопок
rows[][].label str Да Текст, отображаемый на кнопке
rows[][].type str Да callback (возврат данных при нажатии) / link (переход по URL)
rows[][].data str Да Данные для вызова (callback) или адрес перехода (link)
rows[][].* Any Нет Платформенно-специфичные дополнительные поля (например web_app, menus), адаптер отображает или игнорирует по возможностям

Сопоставление с платформами

Платформа Стандартный сегмент → оригинальная структура Оригинальная структура
Telegram reply_markup.inline_keyboard: [{text, callback_data | url}] callback→callback_data (≤64 байт), link→url
Yunhu content.buttons: [{label, action_type}] callback→action_type:2 + action + value, link→action_type:1 + url
QQBot keyboard.content.rows: [{label, type, data}] callback→type:2 + data, link→type:0 + data (сообщение должно быть в формате markdown)
Kook Модуль action-group карточки: [{type, text, value, click}] callback→click:return + value, link→click:link + url
Discord components[].components: [{label, style, custom_id | url}] callback→style:1 + custom_id, link→style:5 + url

Модификаторы отправки (реализуются в Send-классе каждого адаптера)

Общие модификаторы реализуются в Send-классе каждого адаптера (базовый класс фреймворка не изменяется):

# Одна и та же кодовая база, произвольная платформа (адаптеры реализуют модификаторы и преобразование)
rows = [[{"label": "Лайк", "type": "callback", "data": "like:1"},
         {"label": "Главная", "type": "link", "data": "https://example.com"}]]
await adapter.Send.To("group", gid).Keyboard(rows).Text("Пожалуйста, выберите")

Список совместимых адаптеров: QQBot / Telegram / Yunhu реализованы (модификаторы + преобразование стандартных сегментов); новые адаптеры реализуют по данному документу (см. §7 Checklist).

5.3 События интерактивного ответа (после нажатия кнопки)

События, отправляемые платформой после нажатия кнопки, должны содержать следующие стандартные поля (detail_type может сохранять оригинальное название платформы):

Стандартное поле Тип Обязательно Описание
interaction_id str Да ID текущей интеракции (используется для ответа, например, индикатор загрузки/уведомление)
button_data str Да Данные, возвращаемые кнопкой (см. §5.2 data)
button_label str Нет Текст, отображаемый на кнопке
user_id str Да ID пользователя, нажавшего
message_id str Нет ID сообщения, в котором находится кнопка
group_id / channel_id str Нет ID сессии/чат-канала

Поле detail_type: сохраняется оригинальное название платформы (qqbot_interaction / telegram_callback_query / yunhu_a2ui_button и т.д.), но стандартные поля должны быть заполнены — модули могут использовать event.get("button_data") для получения данных на кроссплатформенной основе.

Рекомендуемые расширения Event (предоставляются EventMixin адаптера):

def get_button_data(self) -> str: ...     # button_data
def get_interaction_id(self) -> str: ...  # interaction_id

Ответ на интеракцию (в зависимости от возможностей платформы): adapter.reply_interaction(interaction_id, code=0) (QQBot) / answerCallbackQuery (Telegram) и т.д., именование следует семейству методов платформы, не обязательно унифицировать.

Сопоставление событий интеракции по платформам

Платформа Оригинальное событие detail_type Источник interaction_id Источник button_data
Telegram callback_query telegram_callback_query (notice) callback_query.id callback_query.data
Yunhu Событие нажатия кнопки yunhu_button_click / yunhu_a2ui_button buttonId / sourceComponentId value / actionName
QQBot INTERACTION_CREATE qqbot_interaction interaction.id data.resolved.button_data
Kook Событие нажатия кнопки kook_button_click msg_id+value value
Discord INTERACTION_CREATE discord_interaction interaction.id data.custom_id

5.4 select Выпадающий список (зарезервировано)

{
  "type": "select",
  "data": {
    "placeholder": "Выберите",
    "options": [
      {"label": "Опция A", "data": "opt:A"},
      {"label": "Опция B", "data": "opt:B"}
    ],
    "min_values": 1,
    "max_values": 1
  }
}

События ответа повторяют поля из §5.3 (button_data = выбранный data, при множественном выборе — JSON-массив). Платформы с первоочередной реализацией: Discord (выпадающее меню), Telegram (переключение клавиатуры). Платформы без реализации должны в alt_message заменить сегмент текстовым списком.

5.5 card Карточка (зарезервирована, отложена стандартизация)

Структура карточек сильно различается (Kook — полнофункциональный модуль карточек, Yunhu — html, QQ — markdown+keyboard), стандартизация пока не проводится. Рекомендации:


docs/ru/quick-start.md

6. Кандидаты на будущее (Roadmap)

Следующие функции уже появляются или ожидается появление на ≥2 платформах, и их стандартизация будет осуществляться в порядке приоритета:

Кандидат Платформы Приоритет Примечание
Выпадающий список выбора (select) Discord / Telegram Высокий Структурный черновик см. в §5.4
Реакции/эмодзи (reactions) QQBot / Telegram / Discord / Kook Высокий Стандартизация действий и событий с обеих сторон
Действия по управлению группой (мут/кик/одобрение) QQBot / Облако-Озеро / OB11 Высокий Большинство уже реализовано как платформенные действия, ожидается стандартизация подписей
Анонсы/доска объявлений Облако-Озеро / Telegram / Discord Средний Действия типа set_announcement
Модель ресурсов файлов (двухчастный file_id) Все платформы Низкий (отложено) Отправка прямой передачи SendDSL.File(file, filename) уже является стандартным путем (URL/путь/bytes прямая передача, см. спецификацию методов отправки §2.1); модель file_id передается только при наличии на стороне сервера, см. стандарт API-действий §3.5
Карточки (card) Kook / Облако-Озеро Низкий Структурные различия, см. §5.5
Формы (form) Облако-Озеро Низкий Платформенно-специфичный, сохраняется префикс {platform}_
Транскодирование/определение размера медиа Все платформы Низкий Реализуется внутри адаптера, не стандартизируется для внешнего использования

7. Стандартный чек-лист для разработчиков новых адаптеров

При разработке нового адаптера, пожалуйста, сверьтесь с этим списком (★ обязательные пункты, остальные рекомендуемые):

8. Связанные документы