Skip to content

回复消息段

回复消息段用于回复特定的消息,形成对话的上下文关联。

类型定义

typescript
interface ReplyElement {
  type: 'reply'
  id?: string
  event_id?: string
}

参数说明

参数名类型必选说明
typestring消息段类型,固定为 reply
idstring被回复消息的 ID
event_idstring被回复事件的 ID

参数说明

  • 使用 id 来回复具体的消息
  • 使用 event_id 来回复特定的事件
  • 两个参数都是可选的,但通常至少需要提供其中一个

使用示例

基础回复

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 回复特定消息
await bot.client.sendMessage(channelId, [
  segment.reply('message_id_123'),
  segment.text('收到了,谢谢!')
])

带详细信息的回复

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 包含更多回复信息
await bot.client.sendMessage(channelId, [
  segment.reply('message_id_123', {
    user_id: 'user_456',
    content: '原消息内容预览',
    timestamp: Date.now()
  }),
  segment.text('这是我的回复内容')
])

回复与@组合

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 回复消息并@发送者
await bot.client.sendMessage(channelId, [
  segment.reply('message_id_123'),
  segment.at('user_456'),
  segment.text(' 你说得对!')
])

回复并发送图片

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 回复消息并发送图片
await bot.client.sendMessage(channelId, [
  segment.reply('message_id_123'),
  segment.text('看看这个:'),
  segment.image('./photo.jpg')
])

在事件处理中使用

自动回复消息

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 监听消息并自动回复
bot.on('message.guild', async (event) => {
  const content = event.content?.toLowerCase()
  
  if (content?.includes('你好')) {
    await bot.guildService.sendChannelMessage(event.channel_id, [
      segment.reply(event.id),
      segment.text('你好!很高兴见到你 '),
      segment.face(14) // 微笑表情
    ])
  }
})

智能问答回复

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 问答系统
const qaDatabase: Record<string, string> = {
  '天气怎么样': '今天天气很好,适合出门',
  '时间': '现在时间是 ' + new Date().toLocaleString(),
  '帮助': '我可以回答各种问题,试试问我关于天气、时间等'
}

bot.on('message.guild', async (event) => {
  const content = event.content?.trim()
  
  if (content && qaDatabase[content]) {
    await bot.guildService.sendChannelMessage(event.channel_id, [
      segment.reply(event.id),
      segment.text(qaDatabase[content])
    ])
  }
})

回复链式对话

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 跟踪对话历史
const conversationHistory = new Map<string, string[]>()

bot.on('message.guild', async (event) => {
  const userId = event.author.id
  const content = event.content
  
  if (!content) return
  
  // 获取用户对话历史
  const history = conversationHistory.get(userId) || []
  history.push(content)
  
  // 保持最近5条对话
  if (history.length > 5) {
    history.shift()
  }
  conversationHistory.set(userId, history)
  
  // 根据对话历史智能回复
  if (content.includes('之前说什么')) {
    const previousMessage = history[history.length - 2]
    
    await bot.guildService.sendChannelMessage(event.channel_id, [
      segment.reply(event.id),
      segment.text(`你之前说的是: "${previousMessage || '暂无历史记录'}"`)
    ])
  }
})

在不同服务中使用

群聊服务

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 群聊中回复消息
await bot.groupService.sendMessage(groupId, [
  segment.reply('message_id_123'),
  segment.text('群友说得对!')
])

// 群聊管理回复
bot.on('message.group', async (event) => {
  if (event.content?.includes('违规')) {
    await bot.groupService.sendMessage(event.group_id, [
      segment.reply(event.id),
      segment.text('请注意群规,文明交流')
    ])
  }
})

私聊服务

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 私聊中回复消息
await bot.friendService.sendMessage(userId, [
  segment.reply('message_id_123'),
  segment.text('明白了,我会处理的')
])

// 私聊客服回复
bot.on('message.private', async (event) => {
  if (event.content?.includes('咨询')) {
    await bot.friendService.sendMessage(event.user_id, [
      segment.reply(event.id),
      segment.text('请问有什么可以帮您的吗?')
    ])
  }
})

频道服务

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 频道中回复消息
await bot.guildService.sendChannelMessage(channelId, [
  segment.reply('message_id_123'),
  segment.text('感谢分享!')
])

// 频道互动回复
bot.on('message.guild', async (event) => {
  if (event.content?.includes('签到')) {
    await bot.guildService.sendChannelMessage(event.channel_id, [
      segment.reply(event.id),
      segment.text('签到成功!'),
      segment.face(76) // 点赞
    ])
  }
})

高级回复功能

条件回复

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 根据用户权限回复
async function conditionalReply(event: any, message: string) {
  const userRole = await bot.guildService.getMemberRole(event.guild_id, event.author.id)
  
  if (userRole === 'admin') {
    await bot.guildService.sendChannelMessage(event.channel_id, [
      segment.reply(event.id),
      segment.text(`管理员您好!${message}`)
    ])
  } else {
    await bot.guildService.sendChannelMessage(event.channel_id, [
      segment.reply(event.id),
      segment.text(message)
    ])
  }
}

延迟回复

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 延迟几秒后回复
async function delayedReply(channelId: string, messageId: string, content: string, delay: number) {
  setTimeout(async () => {
    await bot.client.sendMessage(channelId, [
      segment.reply(messageId),
      segment.text(content)
    ])
  }, delay * 1000)
}

// 使用示例
bot.on('message.guild', async (event) => {
  if (event.content?.includes('思考')) {
    await delayedReply(event.channel_id, event.id, '我想到了一个好主意!', 3)
  }
})

多条回复

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

// 分多条消息回复
async function multiPartReply(channelId: string, messageId: string, parts: string[]) {
  for (let i = 0; i < parts.length; i++) {
    await bot.client.sendMessage(channelId, [
      i === 0 ? segment.reply(messageId) : null,
      segment.text(`${i + 1}. ${parts[i]}`)
    ].filter(Boolean))
    
    // 间隔发送
    if (i < parts.length - 1) {
      await new Promise(resolve => setTimeout(resolve, 1000))
    }
  }
}

// 使用示例
const steps = [
  '首先打开应用',
  '然后找到设置页面',
  '最后修改相关配置'
]

await multiPartReply(channelId, messageId, steps)

回复消息统计

typescript
class ReplyTracker {
  private replyCount = new Map<string, number>()
  private userReplies = new Map<string, string[]>()
  
  trackReply(userId: string, messageId: string) {
    // 统计用户回复次数
    const count = this.replyCount.get(userId) || 0
    this.replyCount.set(userId, count + 1)
    
    // 记录用户回复的消息
    const replies = this.userReplies.get(userId) || []
    replies.push(messageId)
    this.userReplies.set(userId, replies)
  }
  
  getUserReplyCount(userId: string): number {
    return this.replyCount.get(userId) || 0
  }
  
  getMostActiveUsers(limit: number = 5): Array<{userId: string, count: number}> {
    return Array.from(this.replyCount.entries())
      .map(([userId, count]) => ({ userId, count }))
      .sort((a, b) => b.count - a.count)
      .slice(0, limit)
  }
}

const replyTracker = new ReplyTracker()

bot.on('message.guild', async (event) => {
  // 检查是否包含回复
  const hasReply = event.message_reference?.message_id
  
  if (hasReply) {
    replyTracker.trackReply(event.author.id, event.id)
  }
})

回复消息验证

检查消息是否存在

typescript
import { Bot, segment } from 'qq-official-bot'

const bot = new Bot(config)

async function safeReply(channelId: string, replyToId: string, content: string) {
  try {
    // 尝试获取被回复的消息
    const originalMessage = await bot.client.getMessage(channelId, replyToId)
    
    if (originalMessage) {
      await bot.client.sendMessage(channelId, [
        segment.reply(replyToId),
        segment.text(content)
      ])
    } else {
      // 消息不存在,发送普通消息
      await bot.client.sendMessage(channelId, [
        segment.text(content)
      ])
    }
  } catch (error) {
    console.error('回复消息失败:', error)
    
    // 回退到普通消息
    await bot.client.sendMessage(channelId, [
      segment.text(content)
    ])
  }
}

回复权限检查

typescript
async function checkReplyPermission(userId: string, channelId: string): Promise<boolean> {
  try {
    const permissions = await bot.guildService.getMemberPermissions(channelId, userId)
    return permissions.includes('SEND_MESSAGES')
  } catch (error) {
    return false
  }
}

bot.on('message.guild', async (event) => {
  const canReply = await checkReplyPermission(bot.config.app_id, event.channel_id)
  
  if (canReply && event.content?.includes('求助')) {
    await bot.guildService.sendChannelMessage(event.channel_id, [
      segment.reply(event.id),
      segment.text('我来帮您!请详细描述问题。')
    ])
  }
})

最佳实践

回复内容相关性

typescript
// ✅ 好的做法 - 回复内容与原消息相关
bot.on('message.guild', async (event) => {
  if (event.content?.includes('天气')) {
    await bot.guildService.sendChannelMessage(event.channel_id, [
      segment.reply(event.id),
      segment.text('今天天气很好,适合外出活动')
    ])
  }
})

// ❌ 避免的做法 - 回复内容与原消息无关
bot.on('message.guild', async (event) => {
  await bot.guildService.sendChannelMessage(event.channel_id, [
    segment.reply(event.id),
    segment.text('随机回复内容') // 与原消息无关
  ])
})

避免回复循环

typescript
const recentReplies = new Set<string>()

bot.on('message.guild', async (event) => {
  // 避免回复机器人自己的消息
  if (event.author.bot) return
  
  // 避免短时间内重复回复
  const key = `${event.channel_id}:${event.author.id}`
  if (recentReplies.has(key)) return
  
  recentReplies.add(key)
  setTimeout(() => recentReplies.delete(key), 30000) // 30秒后允许再次回复
  
  if (event.content?.includes('帮助')) {
    await bot.guildService.sendChannelMessage(event.channel_id, [
      segment.reply(event.id),
      segment.text('有什么可以帮助您的吗?')
    ])
  }
})

组合规则

回复消息段可以与以下消息段组合使用:

  • 文本消息段 - 最常见的组合
  • @消息段 - 回复并@用户
  • 图片消息段 - 回复并发送图片
  • 视频消息段 - 回复并发送视频
  • 音频消息段 - 回复并发送语音
  • 表情消息段 - 回复并发送表情
  • 其他所有消息段 - 回复可以与任何内容组合

限制说明

  1. 不可单独发送:回复消息段必须与其他消息段组合使用
  2. 消息存在性:被回复的消息必须存在且可访问
  3. 权限要求:需要有发送消息的权限
  4. 消息ID有效性:回复的消息 ID 必须是有效的
  5. 时效性:过旧的消息可能无法回复
  6. 每条消息限制:一条消息中只能包含一个回复消息段