ErisPulse Session Type Standards
This document defines the session type standards supported by ErisPulse, including receiving event types and sending target types.
1. Core Concepts
1.1 Receive Type && Send Type
ErisPulse distinguishes two session types:
- Receive Type: The
detail_typefield used for receiving events - Send Type: The target type used in the
Send.To()method when sending messages
1.2 Type Mapping Relationship
Receive Type (detail_type) Send Type (Send.To)
───────────────── ────────────────
private → user
group → group
channel → channel
guild → guild
thread → thread
user → user
Key Points:
privateis the receive type;usermust be used for sendinggroup,channel,guild, andthreadhave the same type for both receiving and sending- The system automatically performs type conversion, so manual handling is not required (meaning you can directly use the received type for sending). In practice, you don't need to worry about these details, as the wrapper class of Event allows you to directly use the
event.reply()method without considering type conversion.
2. Standard Session Types
2.1 OneBot12 Standard Types
private
- Receive Type:
private - Send Type:
user - Description: One-on-one private chat messages
- ID Field:
user_id - Applicable Platforms: All platforms that support private chats
group
- Receive Type:
group - Send Type:
group - Description: Group chat messages, including various forms of group (e.g., Telegram supergroup)
- ID Field:
group_id - Applicable Platforms: All platforms that support group chats
user
- Receive Type:
user - Send Type:
user - Description: User type, some platforms (e.g., Telegram) represent private chats as
userrather thanprivate - ID Field:
user_id - Applicable Platforms: Telegram and similar platforms
2.2 ErisPulse Extended Types
channel
- Receive Type:
channel - Send Type:
channel - Description: Channel messages, supporting broadcast-style messages to multiple users
- ID Field:
channel_id - Applicable Platforms: Discord, Telegram, Line, etc.
guild
- Receive Type:
guild - Send Type:
guild - Description: Server/community messages, typically used for Discord Guild-level events
- ID Field:
guild_id - Applicable Platforms: Discord and similar platforms
thread
- Receive Type:
thread - Send Type:
thread - Description: Thread/subchannel messages, used for sub-discussion areas within communities
- ID Field:
thread_id - Applicable Platforms: Discord Threads, Telegram Topics, etc.
3. Platform Type Mapping
3.1 Mapping Principles
The adapter is responsible for mapping the native types of platforms to ErisPulse standard types:
Platform native type → ErisPulse standard type → Sending type
3.2 Common Platform Mapping Examples
Telegram
Telegram Type ErisPulse Receive Type Sending Type
───────────────── ──────────────── ───────────
private private user
group group group
supergroup group group # Mapped to group
channel channel channel
Discord
Discord Type ErisPulse Receive Type Sending Type
───────────────── ──────────────── ───────────
Direct Message private user
Text Channel channel channel
Guild guild guild
Thread thread thread
OneBot11
OneBot11 Type ErisPulse Receive Type Sending Type
───────────────── ──────────────── ───────────
private private user
group group group
discuss group group # Mapped to group
4. Custom Type Extension
4.1 Register Custom Type
The adapter can register custom session types:
from ErisPulse.Core.Event import register_custom_type
# Register custom type
register_custom_type(
receive_type="my_custom_type",
send_type="custom",
id_field="custom_id",
platform="MyPlatform"
)
4.2 Use Custom Type
After registration, the system will automatically handle conversion and inference for this type:
# Automatic inference
receive_type = infer_receive_type(event, platform="MyPlatform")
# Returns: "my_custom_type"
# Convert to send type
send_type = convert_to_send_type(receive_type, platform="MyPlatform")
# Returns: "custom"
# Get corresponding ID
target_id = get_target_id(event, platform="MyPlatform")
# Returns: event["custom_id"]
4.3 Unregister Custom Type
from ErisPulse.Core.Event import unregister_custom_type
unregister_custom_type("my_custom_type", platform="MyPlatform")
5. Automatic Type Inference
When an event does not have an explicit detail_type field, the system automatically infers the type based on the available ID fields:
Note
Behavior change in 2.7.0+: detail_type is directly adopted only if it is a known session type (standard or custom). For notice/request events, detail_type (e.g., group_member_increase, friend_increase) is a semantic subtype rather than a session type, and the correct session type will be inferred from the ID field instead.
5.1 Inference Priority
Priority (from highest to lowest):
1. group_id → group
2. channel_id → channel
3. guild_id → guild
4. thread_id → thread
5. user_id → private
5.2 Usage Examples
# Event has only group_id
event = {"group_id": "123", "user_id": "456"}
receive_type = infer_receive_type(event)
# Returns: "group" (group_id is prioritized)
# Event has only user_id
event = {"user_id": "123"}
receive_type = infer_receive_type(event)
# Returns: "private"
# For notice events, detail_type is a semantic subtype; 2.7.0+ will infer from ID fields
event = {"type": "notice", "detail_type": "group_member_increase", "group_id": "123"}
receive_type = infer_receive_type(event)
# Returns: "group" (not "group_member_increase")
6. API Usage Examples
6.1 Sending Messages
from ErisPulse import adapter
# Send to a user
await adapter.myplatform.Send.To("user", "123").Text("Hello")
# Send to a group
await adapter.myplatform.Send.To("group", "456").Text("Hello")
# Automatically convert private → user (not recommended, may cause compatibility issues)
await adapter.myplatform.Send.To("private", "789").Text("Hello")
# Internally automatically converted to: Send.To("user", "789") # Using user as session type directly is a better choice
6.2 Event Reply
from ErisPulse.Core.Event import Event
# Event.reply() automatically handles type conversion
await event.reply("Reply content")
# Internally automatically uses the correct sending type
6.3 Command Handling
from ErisPulse.Core.Event import command
@command(name="test")
async def handle_test(event):
# The system automatically handles session type
# No need to manually determine group_id or user_id
await event.reply("Command executed successfully")
7. Core API Reference
7.1 Type Conversion
from ErisPulse.Core.Event import convert_to_send_type, convert_to_receive_type
# Receive type → Send type
convert_to_send_type("private") # → "user"
convert_to_send_type("group") # → "group"
# Send type → Receive type
convert_to_receive_type("user") # → "private"
convert_to_receive_type("group") # → "group"
7.2 ID Field Query
from ErisPulse.Core.Event import get_id_field, get_receive_type
get_id_field("group") # → "group_id"
get_id_field("private") # → "user_id"
get_receive_type("group_id") # → "group"
get_receive_type("user_id") # → "private"
7.3 One-step Retrieval of Send Information
from ErisPulse.Core.Event import get_send_type_and_target_id
event = {"detail_type": "private", "user_id": "123"}
send_type, target_id = get_send_type_and_target_id(event)
# send_type = "user", target_id = "123"
# Directly used in Send.To()
await adapter.Send.To(send_type, target_id).Text("Hello")
7.4 Retrieve Target ID
from ErisPulse.Core.Event import get_target_id
event = {"detail_type": "group", "group_id": "456"}
get_target_id(event) # → "456"
8. Utility Methods
from ErisPulse.Core.Event import (
is_standard_type,
is_valid_send_type,
get_standard_types,
get_send_types,
clear_custom_types,
)
is_standard_type("private") # True
is_standard_type("custom_type") # False
is_valid_send_type("user") # True
is_valid_send_type("invalid") # False
get_standard_types() # {"private", "group", "channel", "guild", "thread", "user"}
get_send_types() # {"user", "group", "channel", "guild", "thread"}
clear_custom_types() # Clear all
clear_custom_types(platform="discord") # Clear only for the specified platform
9. Best Practices
7.1 Adapter Developers
- Use Standard Mappings: Map to standard types as much as possible, rather than creating new types.
- Correct Conversion: Ensure the mapping relationship between received and sent types is correct.
- Retain Raw Data: Keep the raw event type in
{platform}_raw. - Document Mappings: Explain the type mapping relationships in the adapter documentation.
7.2 Module Developers
- Use Utility Methods: Use utility methods like
get_send_type_and_target_id(). - Avoid Hardcoding: Do not write code like
if group_id else "private". - Consider All Types: Code should support all standard types, not just private/group.
- Flexible Design: Use event wrapper methods, rather than directly accessing fields.
9. Type Inference
- Prefer detail_type: If there is a clear field, do not perform inference.
- Use Inference Judiciously: Only use inference when there is no clear type.
- Pay Attention to Priority: Understand the inference priority to avoid unexpected results.
10. Frequently Asked Questions
Q1: Why is private converted to user when sending?
A: This is a requirement of the OneBot12 specification. private is a concept for receiving, and using user when sending is more semantically appropriate.
Q2: How to support new session types?
A: Register custom types using register_custom_type(), or directly use standard types such as channel and guild.
Q3: What to do if an event does not have a detail_type?
A: The system will automatically infer based on the available ID fields. The priority order is: group > channel > guild > thread > user.
Q4: How does the adapter map Telegram supergroup?
A: In the adapter's conversion logic, map supergroup to the standard group type.
Q5: How to handle special platforms such as email?
A: For non-generic or platform-specific types, use {platform}_raw and {platform}_raw_type to preserve raw data, and let the adapter handle it.
11. Related Documentation
- Event Conversion Standard - Complete event conversion specification
- Send Method Specification - Naming and parameter specification for methods in the Send class
- Adapter Development Guide - Complete guide to adapter development