突破NTQQ消息边界:LLOneBot的JSON卡片与语音消息全解析

突破NTQQ消息边界:LLOneBot的JSON卡片与语音消息全解析

【免费下载链接】LLOneBot 使你的NTQQ支持OneBot11协议进行QQ机器人开发 【免费下载链接】LLOneBot 项目地址: https://gitcode.com/gh_mirrors/ll/LLOneBot

引言:NTQQ机器人开发的痛点与解决方案

你是否还在为NTQQ环境下无法发送富媒体消息而烦恼?作为QQ机器人开发者,你是否渴望在NTQQ平台上实现如JSON卡片、语音消息等高级交互功能?本文将深入解析LLOneBot项目如何突破NTQQ的消息类型限制,全面支持JSON卡片与语音消息,为你的机器人开发提供一站式解决方案。

读完本文,你将获得:

  • 深入理解LLOneBot对JSON卡片消息的完整支持方案
  • 掌握语音消息在NTQQ环境下的处理流程与实现细节
  • 学会使用CQ码构造和解析复杂消息类型
  • 获取在实际项目中应用这些功能的最佳实践与代码示例

LLOneBot项目概述

LLOneBot是一个使NTQQ(New Technology QQ)支持OneBot11协议的开源项目,允许开发者使用熟悉的OneBot标准进行QQ机器人开发。项目基于Electron和TypeScript构建,通过Hook NTQQ的内部API实现对各种消息类型的支持,包括文本、图片、语音和高级的JSON卡片消息。

JSON卡片消息支持解析

JSON卡片消息的结构与优势

JSON卡片(JSON Card)是一种结构化的富媒体消息格式,允许开发者创建包含标题、描述、图片、按钮等元素的交互式消息。相比普通文本消息,JSON卡片具有以下优势:

特性普通文本消息JSON卡片消息
信息组织线性文本流结构化布局
视觉呈现纯文本支持图片、按钮、分栏等
交互能力支持按钮点击事件
信息量有限丰富且层次分明
可读性依赖格式符号自带视觉层次结构

LLOneBot中的JSON卡片实现

LLOneBot通过CQ码(CoolQ Code)扩展实现对JSON卡片的支持。在cqcode.ts文件中,我们可以看到LLOneBot如何解析和生成包含JSON卡片的消息:

// 解析CQ码的核心函数
export function decodeCQCode(source: string): OB11MessageData[] {
  const elements: any[] = []
  let result: ReturnType<typeof from>
  while ((result = from(source))) {
    const { type, data, capture } = result
    if (capture.index) {
      elements.push(h('text', { text: unescape(source.slice(0, capture.index)) }))
    }
    elements.push(h(type, data))
    source = source.slice(capture.index + capture[0].length)
  }
  if (source) elements.push(h('text', { text: unescape(source) }))
  return elements
}

JSON卡片消息的构造与发送

要发送JSON卡片消息,开发者需要使用特定的CQ码格式。以下是一个构造和发送JSON卡片消息的示例:

// 构造JSON卡片CQ码
function createJsonCardCQCode(cardData) {
  return encodeCQCode({
    type: 'json',
    data: {
      content: JSON.stringify(cardData)
    }
  })
}

// 发送群消息示例(SendGroupMsg.ts)
class SendGroupMsg extends SendMsg {
  actionName = ActionName.SendGroupMsg

  protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
    delete (payload as Partial<OB11PostSendMsg>).user_id
    payload.message_type = 'group'
    return super.check(payload)
  }
}

JSON卡片消息的处理流程

LLOneBot处理JSON卡片消息的完整流程如下:

mermaid

语音消息支持解析

语音消息在NTQQ中的处理挑战

NTQQ对语音消息有特殊的格式要求,只支持特定编码的语音文件。LLOneBot需要解决以下挑战:

  • 语音格式转换(支持多种输入格式转为NTQQ兼容格式)
  • 语音时长计算与验证
  • 异步发送与状态跟踪
  • 语音文件的临时存储与清理

LLOneBot的语音处理模块

audio.ts文件中,LLOneBot实现了完整的语音处理功能,包括编码转换、时长计算等核心功能:

// 语音编码转换核心函数
export async function encodeSilk(filePath: string) {
  try {
    const file = await fsPromise.readFile(filePath)
    const pttPath = path.join(TEMP_DIR, randomUUID())
    
    if (!isSilk(file)) {
      log(`语音文件${filePath}需要转换成silk`)
      // 使用FFmpeg进行格式转换
      const convert = () => {
        return new Promise<Buffer>((resolve, reject) => {
          const ffmpegPath = getConfigUtil().getConfig().ffmpeg || process.env.FFMPEG_PATH || 'ffmpeg'
          const cp = spawn(ffmpegPath, ['-y', '-i', filePath, '-ar', '24000', '-ac', '1', '-f', 's16le', pcmPath])
          // ...转换过程处理
        })
      }
      // ...处理逻辑
    } else {
      // 已经是Silk格式,直接处理
      // ...
    }
  } catch (error: any) {
    log('convert silk failed', error.stack)
    return {}
  }
}

语音消息的完整处理流程

LLOneBot处理语音消息的完整流程如下:

mermaid

语音消息的发送实现

LLOneBot通过SendPrivateMsgSendGroupMsg类支持语音消息的发送,这两个类都继承自SendMsg基类:

// 发送私聊消息实现
class SendPrivateMsg extends SendMsg {
  actionName = ActionName.SendPrivateMsg

  protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
    payload.message_type = 'private'
    return super.check(payload)
  }
}

在消息发送过程中,语音文件会经过格式转换、临时存储和清理等步骤,确保符合NTQQ的要求并保持系统清洁。

消息发送的核心流程

消息发送的整体架构

LLOneBot的消息发送系统采用分层架构设计,从OneBot协议解析到底层API调用,形成了完整的调用链:

mermaid

消息发送的状态管理

LLOneBot实现了完善的消息发送状态管理机制,确保消息可靠发送:

// 消息发送状态管理(msg.ts)
export let sendMessagePool: Record<string, ((sendSuccessMsg: RawMessage) => void) | null> = {} // peerUid: callbackFunc
export let sentMessages: Record<string, RawMessage> = {}  // msgId: RawMessage

async function sendWaiter(peer: Peer, waitComplete = true, timeout: number = 10000) {
  // 等待上一个相同的peer发送完
  const peerUid = peer.peerUid
  let checkLastSendUsingTime = 0
  
  const waitLastSend = async () => {
    if (checkLastSendUsingTime > timeout) {
      throw '发送超时'
    }
    let lastSending = sendMessagePool[peer.peerUid]
    if (lastSending) {
      await sleep(500)
      checkLastSendUsingTime += 500
      return await waitLastSend()
    }
  }
  
  await waitLastSend()
  // ...后续实现
}

实战应用:构建复杂消息示例

示例1:发送带按钮的JSON卡片

// 构造JSON卡片数据
const cardData = {
  type: "template",
  data: {
    title: "LLOneBot功能测试",
    content: "这是一个带按钮的JSON卡片示例",
    image: "https://example.com/image.png",
    buttons: [
      {
        text: "查看文档",
        action: "open_url",
        url: "https://github.com/LLOneBot/LLOneBot"
      },
      {
        text: "发送测试消息",
        action: "callback",
        data: "test_action"
      }
    ]
  }
};

// 转换为CQ码
const cqCode = encodeCQCode({
  type: "json",
  data: { content: JSON.stringify(cardData) }
});

// 发送群消息
sendGroupMsg({
  group_id: 123456789,
  message: cqCode
});

示例2:发送语音消息并跟踪状态

// 构造语音CQ码
const voiceCqCode = encodeCQCode({
  type: "record",
  data: {
    file: "local:///path/to/audio.mp3",
    magic: 1,
    cache: 1
  }
});

// 发送私聊消息
const result = await sendPrivateMsg({
  user_id: 987654321,
  message: voiceCqCode
});

// 检查发送状态
if (result.status === "ok") {
  console.log(`语音消息发送成功,消息ID: ${result.data.message_id}`);
  
  // 可以继续跟踪消息状态或进行后续操作
  setTimeout(async () => {
    const msgStatus = await getMessageStatus(result.data.message_id);
    console.log(`语音消息状态: ${msgStatus}`);
  }, 3000);
} else {
  console.error(`语音消息发送失败: ${result.msg}`);
}

最佳实践与性能优化

消息处理性能优化建议

  1. 批量处理消息:对于大量消息发送需求,使用批处理减少API调用次数
  2. 合理设置超时:根据消息类型设置合理的超时时间,语音消息通常需要更长时间
  3. 缓存转换结果:对于重复使用的语音或卡片,缓存转换结果减少资源消耗
  4. 异步处理:使用异步IO和非阻塞操作处理文件转换和网络请求

错误处理与重试策略

// 消息发送重试逻辑示例
async function sendWithRetry(peer, elements, retries = 3, delay = 1000) {
  try {
    return await NTQQMsgApi.sendMsg(peer, elements);
  } catch (error) {
    if (retries > 0) {
      log(`消息发送失败,剩余重试次数: ${retries}`, error);
      await sleep(delay);
      return sendWithRetry(peer, elements, retries - 1, delay * 2); // 指数退避
    }
    throw error;
  }
}

总结与展望

LLOneBot通过创新的技术方案,成功突破了NTQQ对消息类型的限制,为开发者提供了完整的JSON卡片和语音消息支持。本文详细解析了这些功能的实现原理和使用方法,包括:

  1. JSON卡片消息的结构、构造方法和发送流程
  2. 语音消息的格式转换、编码处理和状态管理
  3. 完整的消息发送架构和状态跟踪机制
  4. 实战示例和最佳实践建议

随着项目的不断发展,LLOneBot将继续完善对更多消息类型的支持,包括视频消息、文件传输等高级功能,为NTQQ机器人开发提供更强大的工具集。

鼓励与互动

如果本文对你的NTQQ机器人开发有所帮助,请点赞、收藏并关注项目仓库获取最新更新。如有任何问题或建议,欢迎在项目GitHub仓库提交issue或PR参与项目贡献。

下一篇我们将探讨"LLOneBot的事件系统与消息推送机制",敬请期待!

【免费下载链接】LLOneBot 使你的NTQQ支持OneBot11协议进行QQ机器人开发 【免费下载链接】LLOneBot 项目地址: https://gitcode.com/gh_mirrors/ll/LLOneBot

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值