Skip to main content

ErisPulse的Discord适配模块

Project description

ErisPulse Discord Adapter

English | 中文


English

A Discord Bot adapter for the ErisPulse framework, implementing multi-account support, diverse message types, and platform-specific event handling via Discord Gateway (WebSocket) and REST API v10.

Features

  • Multi-Account: Run multiple Discord Bots simultaneously
  • Gateway WebSocket: Full HELLO / IDENTIFY / Heartbeat / RESUME flow
  • Auto-Reconnect: RESUME session recovery, no message loss
  • REST API v10: Complete Discord HTTP API access
  • Embed Support: Send and receive rich embed messages
  • File Upload: multipart/form-data attachment uploads
  • DM: Auto-create DM channels for private messaging
  • Thread Support: Track and interact with Discord threads

Installation

epsdk install Discord

Configuration

Add to config/config.toml:

[DiscordAdapter.accounts.default]
token = "YOUR_BOT_TOKEN"
intents = 33281
enabled = true

# Multi-account example
[DiscordAdapter.accounts.bot2]
token = "ANOTHER_BOT_TOKEN"
intents = 33281
enabled = true

Configuration Fields

Field Type Required Description
token string Yes Discord Bot Token
intents int No Gateway Intents bitmask (default 33281)
enabled bool No Enable this account (default true)

bot_id is discovered automatically at runtime from the Gateway READY event — no need to configure it.

Intents

Intents is a bitmask, default 33281 = GUILDS | GUILD_MESSAGES | MESSAGE_CONTENT:

Intent Value Description
GUILDS 1 << 0 (1) Guild-related events
GUILD_MEMBERS 1 << 1 (2) Member events (requires Privileged)
GUILD_MESSAGES 1 << 9 (512) Guild message events
MESSAGE_CONTENT 1 << 15 (32768) Message content (requires Privileged)

Note: MESSAGE_CONTENT and GUILD_MEMBERS are Privileged Intents. Enable them in the Discord Developer Portal → Bot → Privileged Gateway Intents.

Inviting the Bot

The bot must be invited to a server before it can send/receive messages. Construct an OAuth2 URL:

https://discord.com/api/oauth2/authorize?client_id=YOUR_BOT_ID&permissions=8&scope=bot
  • client_id = your Bot's Application ID (the bot_id shown in logs after READY)
  • permissions=8 = Administrator (adjust as needed via Discord Permission Calculator)
  • Add applications.commands to scope if using slash commands

Quick Start

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

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

@message.on_message()
async def handle_message(event):
    if event.get_platform() != "discord":
        return

    text = event.get_text()
    channel_id = event.get_channel_id()  # Discord channel ID

    if text == "hello":
        # Reply to the channel where the message was received
        await event.reply("Hello from Discord!")

async def main():
    await sdk.run(keep_running=True)

Sending Messages

Text

# Guild channel message
await discord.Send.To("channel", channel_id).Text("Hello World!")

# Private message (auto-creates DM channel)
await discord.Send.To("user", user_id).Text("DM content")

Embed

embed = {
    "title": "Title",
    "description": "Description",
    "color": 5814783,
    "fields": [
        {"name": "Field", "value": "Value", "inline": False}
    ],
    "footer": {"text": "Footer text"},
}
await discord.Send.To("channel", channel_id).Embed(embed)

Media

# Image (URL)
await discord.Send.To("channel", channel_id).Image("https://example.com/image.png")

# Image (binary)
with open("image.png", "rb") as f:
    image_data = f.read()
await discord.Send.To("channel", channel_id).Image(image_data, filename="photo.png")

# File
await discord.Send.To("channel", channel_id).File("https://example.com/doc.pdf")
await discord.Send.To("channel", channel_id).File(file_bytes, filename="report.pdf")

Reply

# Chain modifier
await discord.Send.To("channel", channel_id).Reply(msg_id).Text("Reply content")

# One-shot
await discord.Send.To("channel", channel_id).Reply("Reply content", msg_id)

Mentions

# @single user
await discord.Send.To("channel", channel_id).At("user_id").Text("Hello")

# @multiple users
await discord.Send.To("channel", channel_id).At("user1").At("user2").Text("Hi everyone")

# @everyone
await discord.Send.To("channel", channel_id).AtAll().Text("Announcement")

Message Operations

# Delete (recall) a message
await discord.Send.To("channel", channel_id).Recall(msg_id)

OneBot12 Format

ob12_msg = [{"type": "text", "data": {"text": "Hello"}}]
await discord.Send.To("channel", channel_id).Raw_ob12(ob12_msg)

Multi-Account

# By bot_id (recommended)
await discord.Send.Using(event.get("self", {}).get("user_id")).To("channel", channel_id).Text("Hello")

# By account name
await discord.Send.Using("bot2").To("channel", channel_id).Text("Hello")

Discord-Specific Event Methods

The event object provides Discord-specific methods (requires platform == "discord"):

@message.on_message()
async def handle(event):
    if event.get_platform() != "discord":
        return

    channel_id = event.get_channel_id()    # Discord channel ID
    guild_id = event.get_guild_id()        # Guild ID (empty for DMs)
    username = event.get_username()         # Sender username
    global_name = event.get_global_name()   # Display name
    is_dm = event.is_dm()                   # Is a DM?
    embeds = event.get_embeds()             # Embed list
    attachments = event.get_attachments()   # Attachment list

Event Types

Message Events

Discord Event OB12 detail_type Description
MESSAGE_CREATE channel / private Guild channel / DM message
MESSAGE_UPDATE channel / private Message edited
MESSAGE_DELETE group_message_delete Message deleted

Notice Events

detail_type Description
group_member_increase Member joined guild
group_member_decrease Member left guild
group_member_update Member info updated
group_role_create / group_role_delete / group_role_update Role changes
channel_create / channel_delete / channel_update Channel changes
group_message_reaction_add / group_message_reaction_remove Reaction changes
typing User typing

Request Events

detail_type Description
interaction Slash command / button interaction

Message Segment Types

Type Description
text Plain text
mention / mention_all @user / @everyone
reply Reply reference
image / file / video / audio Media (URL or bytes)
discord_embed Discord Embed (extension)

Session Types

Scenario Receive detail_type Send type Target ID
Guild channel channel channel channel_id
DM private user user_id

Contributing

Issues and Pull Requests are welcome.

License

MIT


中文

基于 ErisPulse 框架的 Discord Bot 适配器,通过 Discord Gateway (WebSocket) 和 REST API v10 实现多账户支持、多种消息类型收发和平台特有事件处理。

特性

  • 多账户支持:同时运行多个 Discord Bot
  • Gateway WebSocket:完整实现 HELLO / IDENTIFY / 心跳 / RESUME 流程
  • 自动断线重连:支持 RESUME 恢复会话,消息不丢失
  • REST API v10:完整的 Discord HTTP API 调用
  • Embed 支持:发送和接收富文本嵌入消息
  • 文件上传:支持 multipart/form-data 上传附件
  • DM 私信:自动创建 DM 频道,支持私信收发
  • Thread 支持:跟踪和交互 Discord 话题

安装

epsdk install Discord

配置

config/config.toml 中添加:

[DiscordAdapter.accounts.default]
token = "YOUR_BOT_TOKEN"
intents = 33281
enabled = true

# 多账户示例
[DiscordAdapter.accounts.bot2]
token = "ANOTHER_BOT_TOKEN"
intents = 33281
enabled = true

配置字段

字段 类型 必填 说明
token string Discord Bot Token
intents int Gateway Intents 位掩码(默认 33281)
enabled bool 是否启用(默认 true)

bot_id 运行时从 Gateway READY 事件自动发现,无需配置。

Intents 说明

Intents 是位掩码,默认 33281 = GUILDS | GUILD_MESSAGES | MESSAGE_CONTENT

Intent 说明
GUILDS 1 << 0 (1) 服务器相关事件
GUILD_MEMBERS 1 << 1 (2) 成员相关事件(需 Privileged)
GUILD_MESSAGES 1 << 9 (512) 服务器消息事件
MESSAGE_CONTENT 1 << 15 (32768) 消息内容(需 Privileged)

注意MESSAGE_CONTENTGUILD_MEMBERS 是 Privileged Intents,需在 Discord Developer Portal 的 Bot 设置页开启。

邀请机器人

机器人必须先被邀请加入服务器才能收发消息。构造 OAuth2 邀请链接:

https://discord.com/api/oauth2/authorize?client_id=你的BOT_ID&permissions=8&scope=bot
  • client_id = 你的 Bot Application ID(READY 后日志中显示的 bot_id
  • permissions=8 = 管理员权限(可通过 Discord Permission Calculator 自行计算)
  • 如需使用斜杠命令,在 scope 中添加 applications.commands

快速开始

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

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

@message.on_message()
async def handle_message(event):
    if event.get_platform() != "discord":
        return

    text = event.get_text()
    channel_id = event.get_channel_id()  # Discord 频道 ID

    if text == "hello":
        # 回复到收到消息的频道
        await event.reply("Hello from Discord!")

async def main():
    await sdk.run(keep_running=True)

发送消息

文本消息

# 服务器频道消息
await discord.Send.To("channel", channel_id).Text("Hello World!")

# 私信(自动创建 DM 频道)
await discord.Send.To("user", user_id).Text("私信内容")

Embed 嵌入消息

embed = {
    "title": "标题",
    "description": "描述内容",
    "color": 5814783,
    "fields": [
        {"name": "字段名", "value": "字段值", "inline": False}
    ],
    "footer": {"text": "页脚文字"},
}
await discord.Send.To("channel", channel_id).Embed(embed)

媒体消息

# 发送图片(URL)
await discord.Send.To("channel", channel_id).Image("https://example.com/image.png")

# 发送图片(二进制数据)
with open("image.png", "rb") as f:
    image_data = f.read()
await discord.Send.To("channel", channel_id).Image(image_data, filename="photo.png")

# 发送文件
await discord.Send.To("channel", channel_id).File("https://example.com/doc.pdf")
await discord.Send.To("channel", channel_id).File(file_bytes, filename="report.pdf")

回复消息

# 链式修饰回复
await discord.Send.To("channel", channel_id).Reply(msg_id).Text("回复内容")

# 便捷方法(一步发送)
await discord.Send.To("channel", channel_id).Reply("回复内容", msg_id)

链式 @提及

# @单个用户
await discord.Send.To("channel", channel_id).At("user_id").Text("你好")

# @多个用户
await discord.Send.To("channel", channel_id).At("user1").At("user2").Text("大家好")

# @全体
await discord.Send.To("channel", channel_id).AtAll().Text("公告")

消息操作

# 撤回消息
await discord.Send.To("channel", channel_id).Recall(msg_id)

OneBot12 格式消息

ob12_msg = [{"type": "text", "data": {"text": "Hello"}}]
await discord.Send.To("channel", channel_id).Raw_ob12(ob12_msg)

多账户发送

# 通过 bot_id(推荐)
await discord.Send.Using(event.get("self", {}).get("user_id")).To("channel", channel_id).Text("Hello")

# 通过账户名
await discord.Send.Using("bot2").To("channel", channel_id).Text("Hello")

Discord 特有方法

事件对象提供以下 Discord 专属方法(需 platform == "discord"):

@message.on_message()
async def handle(event):
    if event.get_platform() != "discord":
        return

    channel_id = event.get_channel_id()    # Discord 频道 ID
    guild_id = event.get_guild_id()        # 服务器 ID(私信为空)
    username = event.get_username()         # 发送者用户名
    global_name = event.get_global_name()   # 显示名
    is_dm = event.is_dm()                   # 是否私信
    embeds = event.get_embeds()             # Embed 列表
    attachments = event.get_attachments()   # 附件列表

事件类型

消息事件

Discord 事件 OB12 detail_type 说明
MESSAGE_CREATE channel / private 服务器频道 / 私信消息
MESSAGE_UPDATE channel / private 消息编辑
MESSAGE_DELETE group_message_delete 消息删除

通知事件

detail_type 说明
group_member_increase 成员加入服务器
group_member_decrease 成员离开服务器
group_member_update 成员信息更新
group_role_create / group_role_delete / group_role_update 身份组变更
channel_create / channel_delete / channel_update 频道变更
group_message_reaction_add / group_message_reaction_remove 表情回应变更
typing 用户正在输入

请求事件

detail_type 说明
interaction 斜杠命令 / 按钮交互

消息段类型

类型 说明
text 纯文本
mention / mention_all @用户 / @全体
reply 回复引用
image / file / video / audio 媒体(URL 或二进制)
discord_embed Discord Embed(扩展)

会话类型

场景 接收 detail_type 发送类型 目标 ID
服务器频道 channel channel channel_id
私信 private user user_id

贡献

欢迎提交 Issue 和 Pull Request。

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

erispulse_discordadapter-4.0.0.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

erispulse_discordadapter-4.0.0-py3-none-any.whl (18.1 kB view details)

Uploaded Python 3

File details

Details for the file erispulse_discordadapter-4.0.0.tar.gz.

File metadata

  • Download URL: erispulse_discordadapter-4.0.0.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for erispulse_discordadapter-4.0.0.tar.gz
Algorithm Hash digest
SHA256 4d048f9c4d9fc52f03082cb8afe072ffdc75adf0ea0ffa13af3d1466a6347f68
MD5 6c33fc756d114d345055cacfdc67665d
BLAKE2b-256 616ebd9b10a58c71f31e8e8380c16b7c3d2d1c7bad87416b00e17bb42fb36257

See more details on using hashes here.

Provenance

The following attestation bundles were made for erispulse_discordadapter-4.0.0.tar.gz:

Publisher: python-publish.yml on wsu2059q/ErisPulse-DiscordAdapter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file erispulse_discordadapter-4.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for erispulse_discordadapter-4.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 70bb6c5285ea904932d350bdbc1a80d5fd28336f922ba7e56b5700b47ff31f04
MD5 7d2b6ba1322b10b4632cda47191eec2e
BLAKE2b-256 71e6cd3cfa1c1b83506cc9a89e7dd4208c1a3cf8719152d4cbfab86d8e202309

See more details on using hashes here.

Provenance

The following attestation bundles were made for erispulse_discordadapter-4.0.0-py3-none-any.whl:

Publisher: python-publish.yml on wsu2059q/ErisPulse-DiscordAdapter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page