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
- Corresponding Module Version: 4.2.0
- Maintainer: ErisPulse
Basic Information
- Platform Overview: Matrix is an open, decentralized communication protocol that supports various scenarios, including private chats and group chats.
- Adapter Name: MatrixAdapter
- Multi-account Support: Supports configuring multiple Matrix accounts simultaneously.
- Connection Method: Long Polling (via Matrix Sync API
/sync) - Authentication Method: Token-based authentication using
access_tokenor login withuser_idandpasswordto obtain a token. - Chained Modifiers Support: Supports chained modifier methods such as
.Reply(),.At(), and.AtAll(). - OneBot12 Compatibility: Supports sending OneBot12 formatted messages.
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 toaccounts.default.
Configuration Item Descriptions (per account):
homeserver: Matrix server address (required), default ishttps://matrix.orgaccess_token: Access token, which can be obtained from a Matrix client. If you already have a token, simply fill it inuser_id: Matrix user ID (e.g.,@bot:matrix.org), used together withpasswordfor loginpassword: Matrix user password, used for automatic login to obtain the access tokenauto_accept_invites: Whether to automatically accept room invitations, default istrueenabled: Whether to enable this account (optional, default is true)
Authentication Methods:
- Method 1 (Recommended): Provide
access_tokendirectly - Method 2: Provide
user_idandpassword, the adapter will automatically call the login API to obtain the token
v5 Paradigm Update (4.2.0)
- BaseConverter Inheritance: Common fields of converters are built by the framework's build_base_event
- Api DSL: get_self_info/get_user_info/get_group_info/get_group_list/get_group_member_list/leave_group/delete_message(redact) + meta actions
- Message Event Supplement message_id (event_id); Message registration table supports delete_message
- spawn_background Task Ownership: Synchronous/heartbeat tasks now use runtime.spawn_background
- Framework Soft Dependency: Runtime checks for ErisPulse>=2.7.1 and provides warnings; Version logs are output on startup
- Matrix lacks native button capabilities, so standard keyboard segments are gracefully ignored (without errors)
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
- Events: Message events (m.room.message: text/image/file/audio/video/reply/edit), member addition/removal (m.room.member), room name change, and other state events
- Conversations: Direct messages (DM rooms auto-discovered) / group chats (rooms); support sending Text/Image/File/Voice/Video/Markdown/Raw_ob12
- APIs: whoami/profile/joined_rooms/room status/member list/leave/redact (see above Api DSL)
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:
.Text(text: str)- Sends plain text messages..Image(file: bytes | str)- Sends image messages, supporting file paths, URLs, MXC URIs, and binary data..Voice(file: bytes | str)- Sends voice messages, supporting file paths, URLs, MXC URIs, and binary data..Video(file: bytes | str)- Sends video messages, supporting file paths, URLs, MXC URIs, and binary data..File(file: bytes | str, filename: str = "")- Sends file messages, supporting file paths, URLs, MXC URIs, and binary data..Notice(text: str)- Sends notification messages (Matrix's m.notice type)..Html(html: str, fallback: str = "")- Sends HTML formatted messages, supporting rich text content..Raw_ob12(message: List[Dict], **kwargs)- Sends OneBot12 formatted messages.
Fluent Modifier Methods (Combinable)
Modifier methods return self, enabling fluent method chaining. They must be called before the final sending method:
.Reply(message_id: str)- Replies to a specified message (using Matrix'sm.in_reply_torelationship)..At(user_id: str)- Mentions a specified user (using Matrix'sm.mentionsfield)..AtAll()- Mentions everyone in the room (using Matrix's@roommention).
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
- 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. - 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.
- Long Polling Sync: Uses the
/syncAPI for long polling to retrieve new events instead of WebSocket. - MXC URI: Media files are referenced using the
mxc://server.domain/media_idformat. - HTML Rich Text: Supports sending HTML-formatted messages via
formatted_body. - Reaction Emojis: Supports message-level emoji reactions (Reaction), distinct from traditional reply messages.
- Message Editing: Supports editing previously sent messages via the
m.replacerelationship. - Message Retraction: Supports retracting or deleting messages via
m.room.redaction.
Extended Fields
- All platform-specific fields are prefixed with
matrix_. - Original data is retained in the
matrix_rawfield. matrix_raw_typeindicates the original Matrix event type (e.g.,m.room.message,m.room.member).
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
- Authenticate using
access_tokenoruser_id+password - Call
/_matrix/client/v3/account/whoamito getbot_user_id - Send a
connectmetadata event - Perform initial sync (
/_matrix/client/v3/sync?timeout=0) to get thenext_batchtoken - Discover DM rooms (
/_matrix/client/v3/user/{user_id}/account_data/m.direct) - Start Long Polling synchronization loop (
/_matrix/client/v3/sync?since={next_batch}&timeout=30000) - Process new events returned from each sync and convert them for emission
Heartbeat Mechanism
- The adapter sends a
heartbeatmetadata event every 30 seconds - The adapter sends a
connectmetadata event upon successful connection - The adapter sends a
disconnectmetadata event upon disconnection
Room Invitations
- When receiving a room invitation (room with
invitestate), if theauto_accept_invitesconfiguration is set totrue(default), the adapter will automatically join the room - Joining the room calls the
/_matrix/client/v3/join/{room_id}API
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}")