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

ErisPulse API Action Standard

This document defines the unified interface specification for OneBot12-standard API actions in ErisPulse adapters, enabling module developers to program against standard interfaces, with adapters responsible for mapping to native platform APIs.

Scope: In the OneBot12 standard actions, ApiDSL provides strongly-typed methods for user/group/channel (Guild)/message management/meta general interfaces (send_message is handled by SendDSL.Raw_ob12). File resource actions (upload_file/get_file/chunking) are only retained for backward compatibility and degraded pass-through, see §3.5 for details. Platform extension actions are called via the escape hatch Api.call("prefix.action", ...). Action parameters and return structures are based on the OneBot12 specification (located in the repository at onebot/specs/interface/).

1. Design Background

In ErisPulse, message segments (message sending and receiving) and event formats have fully followed the OneBot12 standard, but API action calls (such as getting user information, getting group lists, recalling messages, etc.) were not unified previously—module developers had to write different call_api calls for each platform.

ApiDSL solves this issue by providing strongly-typed standard action methods:

Module Code (Cross-platform Consistency)    Adapter Implementation (Platform-specific)
─────────────────────────────────         ──────────────────────────────────
adapter.Api.get_user_info("123")  →  Adapter call_api / Override
adapter.Api.get_group_list()      →  Adapter call_api / Override
adapter.Api.delete_message("id")  →  Adapter call_api / Override

2. Three-layer DSL Parallel Structure

The ErisPulse adapter has three parallel DSL inner classes, each with its own responsibilities:

BaseAdapter
├── Send(SendDSL)       ← Message sending (Text/Image/Raw_ob12)
├── Request(RequestDSL)  ← Request handling (accept/reject)
└── Api(ApiDSL)          ← Standard API actions (user/group/channel/message management/files/metadata) ★
DSL Responsibility Method Style Return Value
Send Sending messages Chainable + asyncio.Task Standard response
Request Handling request events asyncio.Task Standard response
Api Query/management operations async methods Standard response

3. Standard Action List

Method OB12 Action Parameters data Return
get_self_info() get_self_info None user_id, user_name, user_displayname
get_user_info(user_id) get_user_info user_id: str user_id, user_name, user_displayname, user_remark
get_friend_list() get_friend_list None list[get_user_info response]
Method OB12 Action Parameters data Return
get_group_info(group_id) get_group_info group_id: str group_id, group_name
get_group_list() get_group_list None list[get_group_info response]
get_group_member_info(group_id, user_id) get_group_member_info group_id: str, user_id: str user_id, user_name, user_displayname
get_group_member_list(group_id) get_group_member_list group_id: str list[get_group_member_info response]
set_group_name(group_id, group_name) set_group_name group_id: str, group_name: str None
leave_group(group_id) leave_group group_id: str None

3.3 Message Management

Method OB12 Action Parameters Description
delete_message(message_id) delete_message message_id: str Recall/Delete message

Sending Messages (handled by SendDSL.Raw_ob12) is not duplicated in ApiDSL.

OneBot12 guild system consists of two levels: guild and channel.

Method OB12 Action Parameters data Return
get_guild_info(guild_id) get_guild_info guild_id: str guild_id, guild_name
get_guild_list() get_guild_list None list[get_guild_info response]
set_guild_name(guild_id, guild_name) set_guild_name guild_id: str, guild_name: str None
get_guild_member_info(guild_id, user_id) get_guild_member_info guild_id: str, user_id: str user_id, user_name, user_displayname
get_guild_member_list(guild_id) get_guild_member_list guild_id: str list[get_guild_member_info response]
leave_guild(guild_id) leave_guild guild_id: str None
get_channel_info(guild_id, channel_id) get_channel_info guild_id: str, channel_id: str channel_id, channel_name
get_channel_list(guild_id, *, joined_only) get_channel_list guild_id: str, joined_only: bool=false list[get_channel_info response]
set_channel_name(guild_id, channel_id, channel_name) set_channel_name guild_id, channel_id, channel_name None
get_channel_member_info(guild_id, channel_id, user_id) get_channel_member_info guild_id, channel_id, user_id user_id, user_name, user_displayname
get_channel_member_list(guild_id, channel_id) get_channel_member_list guild_id, channel_id list[get_channel_member_info response]
leave_channel(guild_id, channel_id) leave_channel guild_id, channel_id None

The guild system is independent from the group system: platforms such as Discord, QQ Guild, and Kook implement the guild interface, while traditional platforms like QQ and WeChat implement the group interface. Both may coexist or exist independently.

3.5 File Resource Operations

[!WARNING] The file resource model (two-segment file_id) is "downgraded" in ErisPulse: ErisPulse does not use the "upload first, get file_id, then reference" model for file transfer—modules send files using SendDSL.File(file, filename) (direct upload of URL/path/bytes at send time, see Send Method Specification). The actions upload_file, get_file, and segmented actions in this section depend on platform-specific file_id file resource capabilities, which are not universally compatible; only when the adapter backend naturally supports this capability can it be passed through. The framework's built-in adapters do not implement or recommend implementing this, and calls typically return retcode=10002. When modules need to transfer files across platforms, please use SendDSL.File, and do not rely on file_id.

Outlook: Standardizing the file_id resource model to the framework layer is a future direction, but it is not provided in the current version.

Bulk transfer (small files):

Method OB12 Action Parameters data Return
upload_file(*, type, name, ...) upload_file type, name, url/path/data, headers?, sha256? file_id
get_file(file_id, type) get_file file_id: str, type: str name, url/path/data

The type parameter for upload_file:

3.5.1 Segmented Transfer (Large Files, within the above degraded scope)

OneBot12 segmented actions are distinguished by stage. ApiDSL splits the three or two stages of the same action into separate methods (offset is byte offset, data in JSON is Base64); the following table is retained for reference only, and adapters should neither implement nor enforce it:

Three-step segmented upload: prepare → transfer (loop through each segment) → finish

Method Corresponding stage Parameters data Return
upload_file_fragmented_prepare(name, total_size) prepare name: str, total_size: int file_id (used during transfer)
upload_file_fragmented_transfer(file_id, offset, data) transfer file_id, offset: int, data: bytes None
upload_file_fragmented_finish(file_id, sha256) finish file_id, sha256: str (file-wide checksum) file_id
total = os.path.getsize(path)
r = await adapter.Api.upload_file_fragmented_prepare(os.path.basename(path), total)
fid = r["data"]["file_id"]
offset = 0
with open(path, "rb") as f:
    while chunk := f.read(65536):
        await adapter.Api.upload_file_fragmented_transfer(fid, offset, chunk)
        offset += len(chunk)
sha256 = hashlib.sha256(open(path, "rb").read()).hexdigest()
await adapter.Api.upload_file_fragmented_finish(fid, sha256)

Two-step segmented download: prepare → transfer (loop to retrieve segments)

Method Corresponding stage Parameters data Return
get_file_fragmented_prepare(file_id) prepare file_id name, total_size, sha256
get_file_fragmented_transfer(file_id, offset, size) transfer file_id, offset: int, size: int data (bytes of this segment)

3.6 Meta Actions

Meta actions are not specific to a particular account and do not require Using() to specify a Bot.

Method OB12 Action Parameters data Return
get_latest_events(limit, timeout) get_latest_events limit: int=0, timeout: int=0 Array of event objects (excluding meta events)
get_supported_actions() get_supported_actions None list[str] supported action names
get_status() get_status None good: bool, bots: list[{self, online, ...}]
get_version() get_version None impl, version, onebot_version

3.7 General Extension Actions

Method Description
call(action, **params) Escape hatch for platform extension actions, following the OB12 extension naming convention {prefix}.{action}

4. Usage

4.1 Basic Invocation

from ErisPulse import adapter

# Get user information (cross-platform unified)
result = await adapter.myplatform.Api.get_user_info("123456")
if result["status"] == "ok":
    user_name = result["data"]["user_name"]
    print(f"Username: {user_name}")

# Get group list
result = await adapter.myplatform.Api.get_group_list()
groups = result["data"]

# Recall message
await adapter.myplatform.Api.delete_message("msg_123456")

4.2 Specify Bot Account (Multi-account Mode)

# Execute operations using a specified Bot account
info = await adapter.myplatform.Api.Using("bot1").get_self_info()

4.3 Platform Extension Actions

# Call platform-specific extension actions (it is recommended to use the {prefix}.{action} naming convention)
result = await adapter.telegram.Api.call(
    "telegram.send_sticker",
    sticker_id="CAACAgIAAxkBAA...",
)

4.4 Using in Event Handlers

from ErisPulse.Core.Event import message

@message()
async def handle(event):
    # Get sender's detailed information
    user_id = event.get_user_id()
    platform = event.get_platform()

    result = await getattr(adapter, platform).Api.get_user_info(user_id)
    if result["status"] == "ok":
        user_name = result["data"]["user_name"]
        await event.reply(f"Hello, {user_name}!")

5. Adapter Implementation

5.1 Default Behavior (Zero Configuration)

The default implementation of ApiDSL passes the standard action name directly as endpoint to adapter.call_api():

# The default implementation of ApiDSL is equivalent to:
async def get_user_info(self, user_id: str) -> dict:
    return await self._adapter.call_api("get_user_info", user_id=user_id, account_id=self._account_id)

Applicable Scenarios: When the adapter's underlying backend itself follows the OneBot12 standard action protocol, call_api naturally supports standard action names (such as directly connecting to a service that follows this protocol).

5.2 Overriding Standard Methods (Mapping to Platform Native API)

The adapter can override individual standard methods, mapping them to the platform's native API:

class MyAdapter(BaseAdapter):

    class Api(BaseAdapter.Api):
        """Standard API action implementation for MyPlatform"""

        async def get_user_info(self, user_id: str) -> dict:
            # Maps to the platform's native API
            raw = await self._adapter._request("GET", f"/users/{user_id}")
            if raw.get("code") != 0:
                return self._adapter.make_error(retcode=34600, message="User does not exist")

            user = raw["data"]
            return self._adapter.make_response(
                data={
                    "user_id": str(user["id"]),
                    "user_name": user.get("nick", ""),
                    "user_displayname": user.get("display_name", ""),
                    "user_remark": user.get("remark", ""),
                },
                raw=raw,
            )

        async def get_friend_list(self) -> dict:
            raw = await self._adapter._request("GET", "/friends")
            friends = [
                {
                    "user_id": str(u["id"]),
                    "user_name": u.get("nick", ""),
                    "user_displayname": u.get("display_name", ""),
                    "user_remark": u.get("remark", ""),
                }
                for u in raw.get("data", [])
            ]
            return self._adapter.make_response(data=friends, raw=raw)

5.3 Unsupported Actions

Standard methods not overridden by the adapter use the default implementation (delegated to call_api). If call_api does not support the action, it should return a standard error response:

async def call_api(self, endpoint: str, **params):
    if endpoint not in self._supported_endpoints:
        return self.make_error(retcode=10002, message=f"Unsupported action: {endpoint}")
    # ... platform API call

Module developers can determine support by checking the retcode in the returned value:

result = await adapter.myplatform.Api.get_friend_list()
if result["retcode"] == 10002:
    print("This platform does not support retrieving friend list")

6. Response Format

All ApiDSL methods return a standard API response format (see API Response Standard):

{
    "status": "ok",
    "retcode": 0,
    "data": { ... },
    "message_id": "",
    "message": "",
    "myplatform_raw": { ... }
}

Note: For information query actions, message_id is an empty string (only message sending actions have a message_id).

7. Relationship with SendDSL / RequestDSL

Scenario Use DSL Example
Send message Send adapter.Send.To("group", "123").Text("hi")
Accept/deny request Request adapter.Request("req_id").accept()
Get user/group info Api adapter.Api.get_user_info("123")
Recall message Api adapter.Api.delete_message("msg_id")
Leave group Api adapter.Api.leave_group("group_id")

8. Adapter Implementation Checklist

Standard Actions

Extended Actions