跳转到主要内容
消息段是构成消息的基本单元,支持文本、图片、语音、视频、表情等多种类型。

概述

所有消息段都继承自 OB11Segment 基类:
sealed class OB11Segment
使用 message DSL 构造消息:
val msg = message {
    text("Hello")
    image("https://example.com/pic.jpg")
    at(123456789L)
}.build()

文本消息

Text

纯文本消息段。
data class Text(val data: TextData) : OB11Segment()

data class TextData(
    val text: String  // 文本内容
)
DSL 使用
message {
    text("纯文本内容")
}

提及消息

At

@某人消息段。
data class At(val data: AtData) : OB11Segment()

data class AtData(
    val qq: Long  // QQ 号,0 或 "all" 表示全体
)
DSL 使用
message {
    at(123456789L)  // @指定用户
    at(0L)          // @全体成员
}

Reply

回复消息段。
data class Reply(val data: ReplyData) : OB11Segment()

data class ReplyData(
    val id: Long  // 回复的消息 ID
)
DSL 使用
message {
    reply(messageId)
    text("回复内容")
}

媒体消息

Image

图片消息段。
data class Image(val data: ImageData) : OB11Segment()

data class ImageData(
    val file: String? = null,  // 文件路径
    val url: String? = null    // 图片 URL
)
支持格式
  • URL: https://example.com/image.jpg
  • 文件路径: /path/to/image.jpg
  • Base64: base64://iVBORw0KGgo...
DSL 使用
message {
    image("https://example.com/pic.jpg")
    image("C:/images/pic.png")
    image("base64://iVBORw0KGgo...")
}

Record

语音消息段。
data class Record(val data: RecordData) : OB11Segment()

data class RecordData(
    val file: String? = null,  // 文件路径
    val url: String? = null    // 语音 URL
)
DSL 使用
message {
    record("https://example.com/audio.amr")
}

Video

视频消息段。
data class Video(val data: VideoData) : OB11Segment()

data class VideoData(
    val file: String? = null,  // 文件路径
    val url: String? = null    // 视频 URL
)
DSL 使用
message {
    video("https://example.com/video.mp4")
}

File

文件消息段。
data class File(val data: FileData) : OB11Segment()

data class FileData(
    val file: String? = null,  // 文件路径
    val url: String? = null    // 文件 URL
)

表情消息

Face

QQ 表情消息段。
data class Face(val data: FaceData) : OB11Segment()

data class FaceData(
    val id: Int  // 表情 ID
)
常用表情 ID
ID表情ID表情
14微笑1惊讶
2撇嘴178爱心
179心碎66拥抱
DSL 使用
message {
    face(14)  // 微笑
}

Mface

商城表情消息段。
data class Mface(val data: MfaceData) : OB11Segment()

data class MfaceData(
    val id: Long,
    val text: String? = null,
    val emoji_id: String? = null,
    val emoji_package_id: String? = null,
    val key: String? = null
)

Poke

戳一戳消息段。
data class Poke(val data: PokeData) : OB11Segment()

data class PokeData(
    val type: String? = null,
    val id: Long? = null,
    val name: String? = null,
    val card: String? = null
)
DSL 使用
message {
    poke(1, 123456789L)
}

分享消息

Music

音乐分享消息段。
data class Music(val data: MusicData) : OB11Segment()

data class MusicData(
    val type: String? = null,      // 音乐类型
    val id: Long? = null,          // 音乐 ID
    val url: String? = null,       // 音乐 URL
    val audio: String? = null,     // 音频 URL
    val title: String? = null,     // 标题
    val content: String? = null,   // 描述
    val image: String? = null      // 封面
)
音乐类型
  • qq - QQ 音乐
  • 163 - 网易云音乐
  • xm - 虾米音乐
DSL 使用
message {
    music("qq", "123456")
}

Share

链接分享消息段。
data class Share(val data: ShareData) : OB11Segment()

data class ShareData(
    val url: String,
    val title: String?,
    val content: String?,
    val image: String?
)
DSL 使用
message {
    share(
        url = "https://example.com",
        title = "标题"
    )
}

Location

位置分享消息段。
data class Location(val data: LocationData) : OB11Segment()

data class LocationData(
    val lat: Float,
    val lon: Float,
    val title: String? = null,
    val content: String? = null
)
DSL 使用
message {
    location(
        lat = 39.9042f,
        lon = 116.4074f,
        title = "北京"
    )
}

Contact

联系人分享消息段。
data class Contact(val data: ContactData) : OB11Segment()

data class ContactData(
    val type: String,  // "qq" 或 "group"
    val id: Long,
    val name: String? = null
)
DSL 使用
message {
    contact("qq", 123456789L)
}

卡片消息

Json

JSON 卡片消息段。
data class Json(val data: JsonData) : OB11Segment()

data class JsonData(
    val data: String  // JSON 数据
)
DSL 使用
val jsonData = """{"app":"com.tencent.miniapp"}"""
message {
    json(jsonData)
}

Xml

XML 卡片消息段。
data class Xml(val data: XmlData) : OB11Segment()

data class XmlData(
    val data: String  // XML 数据
)
DSL 使用
val xmlData = """<msg>...</msg>"""
message {
    xml(xmlData)
}

游戏消息

Dice

骰子消息段。
data class Dice(val data: DiceData) : OB11Segment()

data class DiceData(
    val result: Int? = null  // 结果 1-6
)

Rps

猜拳消息段。
data class Rps(val data: RpsData) : OB11Segment()

data class RpsData(
    val result: Int? = null  // 1=石头, 2=剪刀, 3=布
)

特殊消息

Forward

合并转发消息段。
data class Forward(val data: ForwardData) : OB11Segment()

data class ForwardData(
    val id: String  // 转发消息 ID
)
合并转发需使用专门的 sendGroupForwardMsg 等 API,不在普通消息中使用。

消息构造 DSL

message 函数

使用 message DSL 构造消息:
val msg = message {
    text("文本")
    at(123456789L)
    image("https://example.com/pic.jpg")
    face(14)
}.build()

可用方法

文本与提及
text(content: String)           // 文本
at(qq: Long)                    // @用户
atAll()                         // @全体
reply(messageId: Long)          // 回复
媒体
image(file: String)             // 图片
record(file: String)            // 语音
video(file: String)             // 视频
face(id: Int)                   // 表情
分享
music(type: String, id: String)         // 音乐
share(url: String, title: String)       // 链接
location(lat: Float, lon: Float)        // 位置
contact(type: String, id: Long)         // 联系人
特殊
json(data: String)              // JSON 卡片
xml(data: String)               // XML 卡片
poke(type: Int, id: Long)       // 戳一戳

消息段操作

遍历消息段

event.message.forEach { segment ->
    when (segment) {
        is OB11Segment.Text -> {
            println("文本: ${segment.data.text}")
        }
        is OB11Segment.Image -> {
            println("图片: ${segment.data.url}")
        }
        is OB11Segment.At -> {
            println("@了: ${segment.data.qq}")
        }
    }
}

查找特定类型

// 检查是否包含图片
val hasImage = event.message.any { it is OB11Segment.Image }

// 获取所有图片
val images = event.message.filterIsInstance<OB11Segment.Image>()

// 提取纯文本
val text = event.message
    .filterIsInstance<OB11Segment.Text>()
    .joinToString("") { it.data.text }

完整示例

图文消息

val msg = message {
    text("【今日天气】\n")
    text("温度:25°C\n")
    text("天气:晴朗\n")
    image("https://example.com/weather.jpg")
    text("\n祝您有个好心情!")
    face(178)
}.build()

messageApi?.sendGroupMessage(groupId, msg)

回复消息

val reply = message {
    reply(event.messageId)
    at(event.userId)
    text(" 您的命令已执行")
}.build()

富文本消息

val menu = message {
    text("【功能菜单】\n")
    text("━━━━━━━━━━━\n")
    text("1. 签到 - 每日签到\n")
    text("2. 查询 - 查询信息\n")
    text("3. 帮助 - 获取帮助\n")
    text("━━━━━━━━━━━\n")
    at(userId)
    text(" 输入对应数字即可")
    face(14)
}.build()

处理收到的消息

pluginContext.onGroupMessage { event ->
    // 提取所有图片
    val images = event.message.filterIsInstance<OB11Segment.Image>()
    
    if (images.isNotEmpty()) {
        val reply = message {
            reply(event.messageId)
            text("检测到 ${images.size} 张图片")
        }.build()
        messageApi?.sendGroupMessage(event.groupId, reply)
    }
    
    // 检查是否 @ 了机器人
    val atBot = event.message
        .filterIsInstance<OB11Segment.At>()
        .any { it.data.qq == event.selfId.toString() }
    
    if (atBot) {
        val reply = message {
            at(event.userId)
            text(" 你叫我?")
        }.build()
        messageApi?.sendGroupMessage(event.groupId, reply)
    }
}

注意事项

  • 消息段顺序即为发送顺序,不可随意调整
  • 单条消息图片数量有限制(通常 ≤ 10)
  • 图片、语音、视频有大小限制
  • @全体成员需要管理员权限
  • 消息长度限制通常为 5000 字符
  • 大图建议使用 URL 而非 Base64
  • 合并转发使用专门 API,不在普通消息中构造
  • 媒体文件支持本地路径、URL 和 Base64
  • 使用 filterIsInstance 高效过滤消息段