简体中文 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)と Request DSL(approve/reject)
送信メソッド 送信メソッド規格 Send クラスメソッドの命名、パラメータ、修飾子、逆変換(OB12→プラットフォーム)
会話タイプ 会話タイプ標準 user/group/channel/guild/dms などの会話タイプの定義とマッピング
API 応答 API 応答標準 標準応答構造と retcode の約束事

3. 標準化ワークフロー(新規機能が標準に取り込まれる方法)

プラットフォーム固有の機能({platform}_ 前綴)
        │  2 つ以上のプラットフォームで同様の機能が出現
        ▼
共通性の識別(共通概念とパラメータのサブセットの抽出)
        │
        ▼
標準草案(命名 + パラメータ + 戻り値 + 各プラットフォームのマッピング表)
        │  審査
        ▼
本ガイドライン/各分野の標準文書に記載 + フレームワークの基底クラス/アダプタによる互換性層の実装
        │
        ▼
標準セグメント/アクション(前綴なし)——モジュールがプラットフォーム間で再利用可能

例:ボタンは当初、各プラットフォームで独立して実装されていた(telegram_inline_keyboard / 雲湖 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 keyboard
アクションマッピング 標準アクション名 → プラットフォームアクション名 get_self_info → get_login_info(OB11)
フィールド標準化 プラットフォームのレスポンス → 標準フィールド getMe() → {user_id, user_name, user_displayname}
合成識別子 プラットフォームに固有識別子がない場合、一意なIDを生成 TG join request にIDがない → tjr_{chat}_{user}_{date}
機能の降格 対応していない場合、テキスト化/返却値10002 Kook に keyboard がない → alt_message でテキスト化;get_friend_list → 10002
正規化 プラットフォームの不純なデータ → 標準フォーマット QQBot @マーク openid → bot_id(名前の正規化)
二重軌道互換 標準構造とプラットフォーム固有構造の両方を受け入れる .Keyboard() は一般的な rows またはプラットフォーム固有構造を受け入れる

5. 交互コンポーネント標準

5.1 コンポーネント一覧とステータス

コンポーネント 標準セグメント type ステータス 対応プラットフォーム
ボタン/キーボード(keyboard) keyboard ✅ 標準化済み Telegram / 云湖 / QQBot
ドロップダウン選択(select) select 📋 保留中(構造は §5.4 参照) Discord / Telegram(bot)
カード(card) card 📋 保留中(§5.5 参照) Kook / 云湖(html)
モーダル(modal) modal 📋 保留中 Discord

修飾子の階層規約:汎用のインタラクティブコンポーネントの Send 修飾子はアダプターの 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 2次元配列 はい 各サブ配列が1行のボタンを表す
rows[][].label str はい ボタンに表示されるテキスト
rows[][].type str はい callback(クリック時にデータを返す)/ link(URLに飛ぶ)
rows[][].data str はい コールバック用データ(callback)または飛ぶURL(link)
rows[][].* Any いいえ プラットフォーム固有のオプションフィールド(例:web_app、menus)は、アダプターが対応度に応じてマッピングまたは無視する

各プラットフォームのマッピング照会

プラットフォーム 標準セグメント → ネイティブ構造 ネイティブ構造の参考
Telegram reply_markup.inline_keyboard:[{text, callback_data | url}] callback→callback_data(≤64バイト)、link→url
云湖 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 クラスで実装)

汎用修飾子は各アダプターが独自の 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 / 云湖 は実装済み(修飾子 + 標準セグメント変換);新規アダプターは本文書に従って実装すればよい(§7 Checklist 参照)。

5.3 インタラクティブコールバックイベント(ボタンクリック後)

ユーザーがボタンをクリックした後に、プラットフォームが送信するイベントは必ず以下の標準フィールドを提供する必要がある(detail_type はプラットフォーム固有の名前を保持してもよい):

標準フィールド 型 必須 説明
interaction_id str はい このインタラクションのID(返信に使用可能、例:回転アイコン/通知)
button_data str はい ボタンが返すデータ(§5.2 の data)
button_label str いいえ ボタンに表示されるテキスト
user_id str はい クリックしたユーザー
message_id str いいえ ボタンが含まれるメッセージ
group_id / channel_id str いいえ 送信元の会話

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_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(select menu)、Telegram(keyboard 切り替え)。未実装のプラットフォームは、このセグメントを受け取ったら alt_message でテキストリストに降格する。

5.5 card カード(保留中、標準化は保留)

カードの構造は非常に多様(Kook のフル機能カードモジュール vs 云湖の html vs QQ markdown+keyboard)で、現時点では強制的な標準化は行わない。提案:


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/パス/バイト直送、送信メソッド規格 §2.1 参照);file_id モデルは後端が天然に備えている場合にのみ透過的に使用、API 動作標準 §3.5 参照
カード card Kook / 云湖 低 構造の差が大きい、§5.5 を参照
フォーム form 云湖 低 プラットフォーム固有、{platform}_ プレフィックスを保持
メディア変換/サイズ検出 各プラットフォーム 低 アダプタ内部での実装、外部には標準化しない

7. 新しいアダプター開発者の標準チェックリスト

新しいアダプターを開発する際は、以下のチェックリストを確認して実装してください(★ は必須、その他の項目は推奨):

8. 関連ドキュメント