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

Matrix Platform Features Document

MatrixAdapter is an adapter built based on the Matrix protocol, integrating all core functional modules of the Matrix protocol and providing a unified interface for event handling and message operations.


Documentation Information

Basic Information

Configuration Instructions

MatrixAdapter supports multi-account configuration, with each account having its own homeserver and authentication information.

# config.toml
# Account 1
[Matrix_Adapter.accounts.default]
homeserver = "https://matrix.org"          # Matrix server address (required)
access_token = "YOUR_ACCESS_TOKEN"          # Access token (choose either this or user_id+password)
user_id = ""                                # Matrix user ID (e.g., @bot:matrix.org)
password = ""                               # Matrix user password
auto_accept_invites = true                  # Whether to automatically accept room invitations (optional, default is true)
enabled = true                              # Whether to enable this account (optional, default is true)

# Account 2
[Matrix_Adapter.accounts.bot2]
homeserver = "https://matrix.example.com"
access_token = "ANOTHER_TOKEN"
enabled = true

Backward compatibility: If an old single-account [Matrix_Adapter] configuration (including access_token) is detected, it will be automatically migrated to accounts.default.

Configuration Item Descriptions (per account):

Authentication Methods:

v5 Paradigm Update (4.2.0)

Standard Api Action Examples

from ErisPulse import sdk
matrix = sdk.adapter.get("matrix")
result = await matrix.Api.get_self_info()            # /account/whoami
result = await matrix.Api.get_group_info(room_id)    # m.room.name
result = await matrix.Api.get_group_list()           # /joined_rooms
await matrix.Api.delete_message(event_id)            # redact (registration table completes room_id)

Supported Platform Capabilities

Supported Message Sending Types

All sending methods are implemented using a fluent interface, for example:

from ErisPulse.Core import adapter
matrix = adapter.get("matrix")

await matrix.Send.To("group", room_id).Text("Hello World!")

The supported sending types include:

Fluent Modifier Methods (Combinable)

Modifier methods return self, enabling fluent method chaining. They must be called before the final sending method:

Fluent Chaining Examples

# Basic send
await matrix.Send.To("user", dm_room_id).Text("Hello")

# Reply to message
await matrix.Send.To("group", room_id).Reply("$event_id").Text("Reply message")

# Mention user
await matrix.Send.To("group", room_id).At("@user:matrix.org").Text("Hello")

# Mention everyone
await matrix.Send.To("group", room_id).AtAll().Text("Announcement")

# Combinable: Reply + Mention
await matrix.Send.To("group", room_id).Reply("$event_id").At("@user:matrix.org").Text("Composite message")

# Send HTML message
await matrix.Send.To("group", room_id).Html("<h1>Title</h1><p>Content</p>", fallback="Title\nContent")

# Send notification message
await matrix.Send.To("group", room_id).Notice("System notification")

OneBot12 Message Support

The adapter supports sending OneBot12 formatted messages, facilitating cross-platform message compatibility:

# Send OneBot12 formatted message
ob12_msg = [{"type": "text", "data": {"text": "Hello"}}]
await matrix.Send.To("user", dm_room_id).Raw_ob12(ob12_msg)

# Combinable with modifiers
ob12_msg = [{"type": "text", "data": {"text": "Reply message"}}]
await matrix.Send.To("group", room_id).Reply("$event_id").Raw_ob12(ob12_msg)

# Complex message
ob12_msg = [
    {"type": "text", "data": {"text": "Look at this image: "}},
    {"type": "image", "data": {"file": "https://example.com/image.png"}},
    {"type": "text", "data": {"text": "Isn't it great?"}}
]
await matrix.Send.To("group", room_id).Raw_ob12(ob12_msg)

Send Method Return Values

All send methods return a Task object, which can be awaited directly to obtain the send result. The returned result follows the ErisPulse adapter's standardized return specification:

{
    "status": "ok",           // Execution status: "ok" or "failed"
    "retcode": 0,             // Return code
    "data": {...},            // Response data
    "message_id": "$event_id", // Matrix event ID
    "message": "",            // Error message
    "matrix_raw": {...}       // Raw response data
}

Error Code Description

retcode Description
0 Success
32000 Request timeout or media upload failed
33000 API call exception
34000 API returned unexpected format or business error

Platform-Specific Event Types

Platform-specific features require platform=="matrix" detection before use.

Core Differences

  1. Decentralized Architecture: Matrix is a decentralized communication protocol. User IDs are formatted as @user:server.domain, and room IDs are formatted as !room_id:server.domain.
  2. Room Concept: Matrix does not distinguish between group chats and private chats; all conversations are "rooms." The adapter automatically identifies private chat rooms through DM (Direct Message) account data.
  3. Long Polling Sync: Uses the /sync API for long polling to retrieve new events instead of WebSocket.
  4. MXC URI: Media files are referenced using the mxc://server.domain/media_id format.
  5. HTML Rich Text: Supports sending HTML-formatted messages via formatted_body.
  6. Reaction Emojis: Supports message-level emoji reactions (Reaction), distinct from traditional reply messages.
  7. Message Editing: Supports editing previously sent messages via the m.replace relationship.
  8. Message Retraction: Supports retracting or deleting messages via m.room.redaction.

Extended Fields

Special Field Examples

# Group message
{
  "type": "message",
  "detail_type": "group",
  "user_id": "@user:matrix.org",
  "group_id": "!room_id:matrix.org",
  "matrix_room_id": "!room_id:matrix.org"
}

# Private chat message
{
  "type": "message",
  "detail_type": "private",
  "user_id": "@user:matrix.org",
  "matrix_room_id": "!dm_room_id:matrix.org"
}

# Reaction emoji
{
  "type": "notice",
  "detail_type": "matrix_reaction",
  "matrix_reaction_event_id": "$reacted_msg_id",
  "matrix_reaction_key": "👍"
}

# Message retraction
{
  "type": "notice",
  "detail_type": "matrix_redaction",
  "matrix_redacted_event_id": "$deleted_msg_id"
}

# Message editing
{
  "type": "message",
  "detail_type": "group",
  "matrix_edit": true,
  "matrix_original_event_id": "$original_event_id"
}

# Thread message
{
  "type": "message",
  "detail_type": "group",
  "thread_id": "$thread_root_id"
}

Message Segment Types

Matrix messages are automatically converted into corresponding message segments based on msgtype:

msgtype Converted Type Description
m.text text Text message
m.notice text Notice message
m.emote text Action message
m.image image Image message
m.audio voice Audio message
m.video video Video message
m.file file File message
m.location location Location message

Example message segment structure:

// Text message (with HTML)
{
  "type": "text",
  "data": {
    "text": "Plain text content",
    "html": "<b>HTML content</b>"
  }
}

// Image message
{
  "type": "image",
  "data": {
    "url": "mxc://matrix.org/abc123",
    "filename": "photo.png",
    "matrix_mxc": "mxc://matrix.org/abc123",
    "info": {
      "mimetype": "image/png",
      "w": 800,
      "h": 600,
      "size": 123456
    }
  }
}

// Location message
{
  "type": "location",
  "data": {
    "latitude": 0.0,
    "longitude": 0.0,
    "matrix_geo_uri": "geo:39.9,116.4",
    "text": "Beijing, China"
  }
}

Event Mixin Methods

The MatrixAdapter registers the following event mixin methods, which can be directly called in event handling:

Method Return Type Description
get_room_id() str Get room ID
get_matrix_event_type() str Get original Matrix event type
get_matrix_sender() str Get original sender ID
get_reaction_key() str Get reaction emoji
is_edited() bool Determine if the message is edited
is_notice() bool Determine if the message is of type m.notice
@message.on_message()
async def handle_message(event):
    if event.get("platform") != "matrix":
        return

    room_id = event.get_room_id()
    event_type = event.get_matrix_event_type()
    sender = event.get_matrix_sender()
    is_edited = event.is_edited()
    is_notice = event.is_notice()

Sync API Connection

Synchronization Flow

  1. Authenticate using access_token or user_id + password
  2. Call /_matrix/client/v3/account/whoami to get bot_user_id
  3. Send a connect metadata event
  4. Perform initial sync (/_matrix/client/v3/sync?timeout=0) to get the next_batch token
  5. Discover DM rooms (/_matrix/client/v3/user/{user_id}/account_data/m.direct)
  6. Start Long Polling synchronization loop (/_matrix/client/v3/sync?since={next_batch}&timeout=30000)
  7. Process new events returned from each sync and convert them for emission

Heartbeat Mechanism

Room Invitations

Usage Examples

Handling Group Messages

from ErisPulse.Core.Event import message
from ErisPulse import sdk

matrix = sdk.adapter.get("matrix")

@message.on_message()
async def handle_group_msg(event):
    if event.get("platform") != "matrix":
        return
    if event.get("detail_type") != "group":
        return

    text = event.get_text()
    room_id = event.get("group_id")

    if text == "hello":
        await matrix.Send.To("group", room_id).Reply(
            event.get("message_id")
        ).Text("Hello!")

Handling Reaction Events

from ErisPulse.Core.Event import notice

@notice.on_notice()
async def handle_reaction(event):
    if event.get("platform") != "matrix":
        return

    if event.get("detail_type") == "matrix_reaction":
        reaction_key = event.get("matrix_reaction_key")
        reacted_event_id = event.get("matrix_reaction_event_id")
        room_id = event.get_room_id()
        # Handle reaction event...

Sending Media Messages

# Sending an image (URL)
await matrix.Send.To("group", room_id).Image("https://example.com/image.png")

# Sending an image (MXC URI)
await matrix.Send.To("group", room_id).Image("mxc://matrix.org/abc123")

# Sending an image (binary data)
with open("image.png", "rb") as f:
    image_bytes = f.read()
await matrix.Send.To("group", room_id).Image(image_bytes)

# Sending an image (local file path)
await matrix.Send.To("group", room_id).Image("/path/to/image.png")

# Sending a file (with filename)
await matrix.Send.To("group", room_id).File("/path/to/document.pdf", filename="document.pdf")

Handling Message Edits

@message.on_message()
async def handle_edited_message(event):
    if event.get("platform") != "matrix":
        return

    if event.is_edited():
        original_id = event.get("matrix_original_event_id")
        # Handle edited message...

Listening to Member Changes

@notice.on_notice()
async def handle_member_change(event):
    if event.get("platform") != "matrix":
        return

    detail_type = event.get("detail_type")

    if detail_type == "group_member_increase":
        user_id = event.get("user_id")
        nickname = event.get("user_nickname")
        print(f"User {nickname} ({user_id}) joined the room")

    elif detail_type == "group_member_decrease":
        user_id = event.get("user_id")
        operator_id = event.get("operator_id")
        print(f"User {user_id} was removed, operator: {operator_id}")