diff --git a/docs/changelogs/CHANGELOG.v1.8.3.md b/docs/changelogs/CHANGELOG.v1.8.3.md deleted file mode 100644 index f91b4439..00000000 --- a/docs/changelogs/CHANGELOG.v1.8.3.md +++ /dev/null @@ -1,13 +0,0 @@ -# v1.8.3 - -QQ Version: Windows 9.9.15-26702 / Linux 3.2.12-26702 - -## 启动的方式 -Way03/Way05 - -## 新增与调整 -1. 输入状态变更事件加入 -2. Way05 支持Bat启动 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.3.3.md b/docs/changelogs/old/CHANGELOG.v1.3.3.md deleted file mode 100644 index 25c0dab4..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.3.3.md +++ /dev/null @@ -1,17 +0,0 @@ -# v1.3.3 - -QQ Version: Windows 9.9.9-23424 / Linux 3.2.7-23361 - -## 修复与优化 -* 尝试修复多开崩溃问题 -* 修复群列表更新问题 -* 修复兼容性问题支持Win7 -* 修复下载 http 资源缺少UA -* 优化少量消息合并转发速度 -* 修复加载群通知时出现 getUserDetailInfo timeout 导致程序崩溃 - -## 新增与调整 -* 新增设置群公告 Api: /_send_group_notice -* 新增重启实现 包括重启快速登录/普通重启 副作用: 原进程 无法清理 - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.3.5.md b/docs/changelogs/old/CHANGELOG.v1.3.5.md deleted file mode 100644 index 15c66f55..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.3.5.md +++ /dev/null @@ -1,18 +0,0 @@ -# v1.3.5 - -QQ Version: Windows 9.9.9-23424 / Linux 3.2.7-23361 - -## 修复与优化 -* 优化启动脚本 -* 修复非管理时群成员减少事件上报 **无法获取操作者与操作类型** -* 修复快速重启进程清理问题 -* 优化配置文件格式 支持自动更新配置 但仍然建议 **备份配置** -* 修复正向反向ws多个客户端周期多次心跳问题 - -## 新增与调整 -* 支持WebUi热重载 -* 新增启动输出WEBUI秘钥 -* 新增群荣誉信息 /get_group_honor_info -* 支持获取群系统消息 /get_group_system_msg - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.3.6.md b/docs/changelogs/old/CHANGELOG.v1.3.6.md deleted file mode 100644 index 35bf957b..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.3.6.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.3.6 - -QQ Version: Windows 9.9.9-23424 / Linux 3.2.7-23361 - -## 修复与优化 -* 修复戳一戳多次上报问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.3.8.md b/docs/changelogs/old/CHANGELOG.v1.3.8.md deleted file mode 100644 index 0ca8103a..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.3.8.md +++ /dev/null @@ -1,15 +0,0 @@ -# v1.3.8 - -QQ Version: Windows 9.9.9-23873 / Linux 3.2.7-23361 - -## 修复与优化 -* 优化打包后体积问题 -* 修复QQ等级获取 -* 兼容 9.7.x 版本换行符 统一为 \n -* 修复处理加群请求 字段异常情况 -* 修复退群通知问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.3.9.md b/docs/changelogs/old/CHANGELOG.v1.3.9.md deleted file mode 100644 index 5376a3ad..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.3.9.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.3.9 - -QQ Version: Windows 9.9.10-23873 / Linux 3.2.7-23361 - -## 修复与优化 -* 修复QQ等级获取与兼容性问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.4.0.md b/docs/changelogs/old/CHANGELOG.v1.4.0.md deleted file mode 100644 index 043e336f..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.0.md +++ /dev/null @@ -1,12 +0,0 @@ -# v1.4.0 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 - -## 新增与调整 -* 支持空间Cookies获取 -* 支持获取在线设备 API /get_online_clients -* 支持图片OCR API: /.ocr_image /ocr_image - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.4.1.md b/docs/changelogs/old/CHANGELOG.v1.4.1.md deleted file mode 100644 index cf7021a6..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.1.md +++ /dev/null @@ -1,14 +0,0 @@ -# v1.4.1 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 提高部分Api兼容性 -* 优化日志膨胀问题 -* 在线状态刷新问题修复 -## 新增与调整 -* 支持非管理群 本地记录时间数据 (建议 **备份配置 清空配置 重新配置**) -* 新增英译中接口 Api: /translate_en2zh -* 新增群文件管理相关扩展接口 Api: /get_group_file_count /get_group_file_list /set_group_file_folder /del_group_file /del_group_file_folder - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.4.2.md b/docs/changelogs/old/CHANGELOG.v1.4.2.md deleted file mode 100644 index 4f8c6737..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.2.md +++ /dev/null @@ -1,12 +0,0 @@ -# v1.4.2 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 修复获取群文件列表Api -* 修复退群通知问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.4.3.md b/docs/changelogs/old/CHANGELOG.v1.4.3.md deleted file mode 100644 index 1d4ee689..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.3.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.4.3 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 修复名片通知 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.4.4.md b/docs/changelogs/old/CHANGELOG.v1.4.4.md deleted file mode 100644 index a69d2962..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.4.md +++ /dev/null @@ -1,10 +0,0 @@ -# v1.4.4 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 更新 -* **重大更新:**更新了版本号 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) - diff --git a/docs/changelogs/old/CHANGELOG.v1.4.5.md b/docs/changelogs/old/CHANGELOG.v1.4.5.md deleted file mode 100644 index f1278b7c..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.5.md +++ /dev/null @@ -1,12 +0,0 @@ -# v1.4.5 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 紧急修复二维扫码问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) - diff --git a/docs/changelogs/old/CHANGELOG.v1.4.6.md b/docs/changelogs/old/CHANGELOG.v1.4.6.md deleted file mode 100644 index 985cdc63..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.6.md +++ /dev/null @@ -1,12 +0,0 @@ -# v1.4.6 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 优化整体稳定性 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) - diff --git a/docs/changelogs/old/CHANGELOG.v1.4.7.md b/docs/changelogs/old/CHANGELOG.v1.4.7.md deleted file mode 100644 index ef888b49..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.7.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.4.7 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 临时扩展 Api: GoCQHTTPUploadGroupFile folder_id字段 用于选择文件夹 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) \ No newline at end of file diff --git a/docs/changelogs/old/CHANGELOG.v1.4.8.md b/docs/changelogs/old/CHANGELOG.v1.4.8.md deleted file mode 100644 index 0b573cfa..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.8.md +++ /dev/null @@ -1,12 +0,0 @@ -# v1.4.8 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 优化Guid的生成方式 -* 支持临时消息获取群来源 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.4.9.md b/docs/changelogs/old/CHANGELOG.v1.4.9.md deleted file mode 100644 index b54dfbab..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.4.9.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.4.9 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 修复接口调用问题 接口标准化 API:set_group_add_request - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.5.0.md b/docs/changelogs/old/CHANGELOG.v1.5.0.md deleted file mode 100644 index 7000abd6..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.0.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.5.0 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 修正各Api默认值 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.5.1.md b/docs/changelogs/old/CHANGELOG.v1.5.1.md deleted file mode 100644 index 70d6df60..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.1.md +++ /dev/null @@ -1,12 +0,0 @@ -# v1.5.1 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 支持 新Api: set_self_profile 可设置个性签名 -* 修复 Api: get_group_system_msg -* 整理日志、添加颜色、使用统一的日志函数以提高日志可读性 -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.5.2.md b/docs/changelogs/old/CHANGELOG.v1.5.2.md deleted file mode 100644 index d470a1cc..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.2.md +++ /dev/null @@ -1,13 +0,0 @@ -# v1.5.2 - -QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361 - -## 修复与优化 -* 替换Uid/Uin为内部实现 -* 增加HttpApi调用稳定性 -* 修复 GetMsg 兼容性 - -## 新增与调整 -* 支持真正意义上的陌生人信息获取 Api: GoCQHTTP_GetStrangerInfo - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.5.3.md b/docs/changelogs/old/CHANGELOG.v1.5.3.md deleted file mode 100644 index 19db608e..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.3.md +++ /dev/null @@ -1,15 +0,0 @@ -# v1.5.3 - -QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-23568 - -## 修复与优化 -* 修复引用消息id问题 -* 修复添加好友的通知 - -## 新增与调整 -* 扩展群分享Json生成 -* 扩展关于收藏的一系列接口 -* 支持专属群头衔获取 -* 支持视频获取直链 - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) \ No newline at end of file diff --git a/docs/changelogs/old/CHANGELOG.v1.5.4.md b/docs/changelogs/old/CHANGELOG.v1.5.4.md deleted file mode 100644 index 46830850..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.4.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.5.4 - -QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-23568 - -## 修复与优化 -* 紧急修复视频与文件问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) \ No newline at end of file diff --git a/docs/changelogs/old/CHANGELOG.v1.5.5.md b/docs/changelogs/old/CHANGELOG.v1.5.5.md deleted file mode 100644 index 1f4b55e5..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.5.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.5.5 - -QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-23568 - -## 修复与优化 -* 紧急修复一些问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) \ No newline at end of file diff --git a/docs/changelogs/old/CHANGELOG.v1.5.6.md b/docs/changelogs/old/CHANGELOG.v1.5.6.md deleted file mode 100644 index ef74e349..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.6.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.5.6 - -QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-24568 - -## 修复与优化 -* 修复一些问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) \ No newline at end of file diff --git a/docs/changelogs/old/CHANGELOG.v1.5.7.md b/docs/changelogs/old/CHANGELOG.v1.5.7.md deleted file mode 100644 index 294e8158..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.7.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.5.7 - -QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-24568 - -## 修复与优化 -* 修复一些问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) \ No newline at end of file diff --git a/docs/changelogs/old/CHANGELOG.v1.5.8.md b/docs/changelogs/old/CHANGELOG.v1.5.8.md deleted file mode 100644 index 1ceab5ff..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.8.md +++ /dev/null @@ -1,14 +0,0 @@ -# v1.5.8 - -QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-24568 - -## 修复与优化 -* 修复视频文件残留问题 -* 重构 getcookies接口 支持大部分常见域 - -## 新增与调整 -* 日志大小限制 -* 支持 QQ音乐 卡片 无签名支持时 启用内置方法(缺点没有封面 限速1min/条) -* 支持Window X86-32机器 - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.5.9.md b/docs/changelogs/old/CHANGELOG.v1.5.9.md deleted file mode 100644 index a3a611c5..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.5.9.md +++ /dev/null @@ -1,12 +0,0 @@ -# v1.5.9 - -QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815 - -## 修复与优化 -* 优化缓存问题 -* 修复poke异常上报 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.6.0.md b/docs/changelogs/old/CHANGELOG.v1.6.0.md deleted file mode 100644 index 1efb93b2..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.6.0.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.6.0 - -QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815 - -## 修复与优化 - - -## 新增与调整 -* 新增图片subtype属性 区分表情图片与商城图片 - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.6.1.md b/docs/changelogs/old/CHANGELOG.v1.6.1.md deleted file mode 100644 index d7359c71..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.6.1.md +++ /dev/null @@ -1,11 +0,0 @@ -# v1.6.1 - -QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815 - -## 修复与优化 - - -## 新增与调整 -* 修复poke异常事件 - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.6.2.md b/docs/changelogs/old/CHANGELOG.v1.6.2.md deleted file mode 100644 index 1a47b5c6..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.6.2.md +++ /dev/null @@ -1,13 +0,0 @@ -# v1.6.2 - -QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815 - -## 修复与优化 -* 修复获取Cookies异常崩溃问题 -* 尝试修复成员退群缓存问题 -* 修复自身退群后群缓存清理问题 - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.6.3.md b/docs/changelogs/old/CHANGELOG.v1.6.3.md deleted file mode 100644 index 508177b8..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.6.3.md +++ /dev/null @@ -1,13 +0,0 @@ -# v1.6.3 - -QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815 - -## 修复与优化 -* 修复带有groupid的私聊消息异常发送到群聊消息 -* 尝试修复rws热重载失效问题 -* 尝试修复进群事件无法正常获取uin - -## 新增与调整 - - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.6.4.md b/docs/changelogs/old/CHANGELOG.v1.6.4.md deleted file mode 100644 index 210fa094..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.6.4.md +++ /dev/null @@ -1,18 +0,0 @@ -# v1.6.4 - -QQ Version: Windows 9.9.12-26000 / Linux 3.2.9-26000 -## 使用前警告 -1. 在最近版本由于QQ本体大幅变动,为了保证NapCat可用性,NapCat近期启动与安装方式将将大幅变动,请关注文档和社群获取。 -2. 在Core上完全执行开源,请不要用于违法用途,如此可能造成NapCat完全停止更新。 -3. 针对原启动方式的围堵,NapCat研发了多种方式,除此其余理论与扩展的分析和思路将部分展示于Docs,以便各位参与开发与维护NapCat。 -## 其余·备注 -启动方式: WayBoot.03 (Electron Main进程为Node 直接注入代码 同理项目: LiteLoader) - -## 修复与优化 -1. 支持Win平台 9.9.12 -2. 修复部分发送图片下载异常情况 - -## 新增与调整 -没有哦 - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.6.5.md b/docs/changelogs/old/CHANGELOG.v1.6.5.md deleted file mode 100644 index 061cab68..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.6.5.md +++ /dev/null @@ -1,18 +0,0 @@ -# v1.6.5 - -QQ Version: Windows 9.9.12-26000 / Linux 3.2.9-26000 -## 使用前警告 -1. 在最近版本由于QQ本体大幅变动,为了保证NapCat可用性,NapCat近期启动与安装方式将将大幅变动,请关注文档和社群获取。 -2. 在Core上完全执行开源,请不要用于违法用途,如此可能造成NapCat完全停止更新。 -3. 针对原启动方式的围堵,NapCat研发了多种方式,除此其余理论与扩展的分析和思路将部分展示于Docs,以便各位参与开发与维护NapCat。 -## 其余·备注 -启动方式: WayBoot.03 (Electron Main进程为Node 直接注入代码 同理项目: LiteLoader) - -## 修复与优化 -1. 优化了WrapperNative载入代码 -2. 优化缓存 - -## 新增与调整 -没有哦 - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/changelogs/old/CHANGELOG.v1.6.6.md b/docs/changelogs/old/CHANGELOG.v1.6.6.md deleted file mode 100644 index f941418a..00000000 --- a/docs/changelogs/old/CHANGELOG.v1.6.6.md +++ /dev/null @@ -1,17 +0,0 @@ -# v1.6.6 - -QQ Version: Windows 9.9.12-26000 / Linux 3.2.9-26000 -## 使用前警告 -1. 在最近版本由于QQ本体大幅变动,为了保证NapCat可用性,NapCat近期启动与安装方式将将大幅变动,请关注文档和社群获取。 -2. 在Core上完全执行开源,请不要用于违法用途,如此可能造成NapCat完全停止更新。 -3. 针对原启动方式的围堵,NapCat研发了多种方式,除此其余理论与扩展的分析和思路将部分展示于Docs,以便各位参与开发与维护NapCat。 -## 其余·备注 -启动方式: WayBoot.03 (Electron Main进程为Node 直接注入代码 同理项目: LiteLoader) - -## 修复与优化 -1. 修复了一些问题 - -## 新增与调整 -没有哦 - -新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api) diff --git a/docs/develop/Image.NTAndroid.md b/docs/develop/Image.NTAndroid.md deleted file mode 100644 index 91354b69..00000000 --- a/docs/develop/Image.NTAndroid.md +++ /dev/null @@ -1,49 +0,0 @@ - - public static final int C2C_PIC_DOWNLOAD = 1004; - public static final String C2C_PIC_DOWNLOAD_DOMAIN = "c2cpicdw.qpic.cn"; - public static final String C2C_PIC_DOWNLOAD_QUIC_DOMAIN = "c2cpicdw.quic.qpic.cn"; - public static final int FLAG_NOT_UPLOAD = 3; - public static final int FLAG_UPLOADINFO_ERROR = 4; - public static final int GROUP_PIC_DOWNLOAD = 1000; - public static final String GROUP_PIC_DOWNLOAD_DOMAIN = "gchat.qpic.cn"; - public static final String GROUP_PIC_DOWNLOAD_QUIC_DOMAIN = "gchat.quic.qpic.cn"; - public static final String GUILD_PIC_DOWNLOAD_DOMAIN = "gchat.qpic.cn/qmeetpic"; - public static final boolean NEW_STORE_FLAG = true; - public static final String PTT_VIDEO_DOWNLOAD_DOMAIN = "grouptalk.c2c.qq.com"; - - protected static final int AVIF_DECODE_EXCEPTION = 4; - protected static final int AVIF_DECODE_FAIL = 1; - protected static final int AVIF_DECODE_FAIL_SO_FAIL = 2; - protected static final int AVIF_DECODE_FAIL_UNKNOWN = 6; - protected static final int AVIF_DECODE_FILETYPE_ERROR = 5; - protected static final int AVIF_DECODE_OOM = 3; - protected static final int AVIF_DECODE_RENAME_FAIL = 7; - protected static final int AVIF_DECODE_SUC = 0; - public static final String AVIF_FILE_SUFFIX = ".avif"; - public static final int AVIF_REQ_APPRUNTIME_NULL = 12; - public static final int AVIF_REQ_CODEC_UNSURPPORT = 5; - protected static final int AVIF_REQ_DENSITY_UNSURPPORT = 10; - protected static final int AVIF_REQ_FLASH_PHOTO = 9; - protected static final int AVIF_REQ_HAS_TMP_AVIF = 7; - protected static final int AVIF_REQ_INVALID_MSG_RECORD = 2; - protected static final int AVIF_REQ_IS_RAW_PHOTO = 3; - protected static final int AVIF_REQ_OUTPUTSTREAM_UNSURPPORT = 11; - protected static final int AVIF_REQ_OVERSIZE = 6; - protected static final int AVIF_REQ_RETRY = 1; - public static final int AVIF_REQ_SO_DOWNLOAD_FAILED = 8; - protected static final int AVIF_REQ_SUC = 0; - public static final int AVIF_REQ_SWITCH_CLOSE = 4; - public static final String C2C_PIC_DOWNLOAD_ERROR_CODE = "C2CPicDownloadErrorCode"; - static final int DOWNLOAD_ST_COMPLETE = 1; - static final int DOWNLOAD_ST_HEAD = 2; - static final int DOWNLOAD_ST_LEFT = 4; - static final int DOWNLOAD_ST_PART = 3; - private static final int ENCRYPT_APPID = 1600000226; - public static final String GROUP_PIC_DOWNLOAD_ERROR_CODE = "GroupPicDownloadErrorCode"; - public static final String KEY_PIC_DOWNLOAD_ERROR_CODE = "param_detail_code"; - protected static final int QUIC_FAIL_IP_LIST_EMPTY = 1; - protected static final int QUIC_FAIL_REQUEST_HTTPS = 3; - protected static final int QUIC_FAIL_REQUEST_QUIC = 2; - protected static final int QUIC_FAIL_SO_LOAD = 4; - public static final String REPORT_TAG_DIRECT_DOWNLOAD_FAIL = "report_direct_download_fail"; - public static final String REQ_PARAM_AVIF = "tp=avif"; diff --git a/docs/develop/Msg常量NTAndroid.md b/docs/develop/Msg常量NTAndroid.md deleted file mode 100644 index 1f208142..00000000 --- a/docs/develop/Msg常量NTAndroid.md +++ /dev/null @@ -1,444 +0,0 @@ -```java -MsgConstant - int ARKSTRUCTELEMENTSUBTYPETENCENTDOCFROMMINIAPP = 1; - int ARKSTRUCTELEMENTSUBTYPETENCENTDOCFROMPLUSPANEL = 2; - int ARKSTRUCTELEMENTSUBTYPEUNKNOWN = 0; - int ATTYPEALL = 1; - int ATTYPECATEGORY = 512; - int ATTYPECHANNEL = 16; - int ATTYPEME = 4; - int ATTYPEONE = 2; - int ATTYPEONLINE = 64; - int ATTYPEROLE = 8; - int ATTYPESUMMON = 32; - int ATTYPESUMMONONLINE = 128; - int ATTYPESUMMONROLE = 256; - int ATTYPEUNKNOWN = 0; - int CALENDARELEMSUBTYPECOMMON = 3; - int CALENDARELEMSUBTYPESTRONG = 1; - int CALENDARELEMSUBTYPEUNKNOWN = 0; - int CALENDARELEMSUBTYPEWEAK = 2; - int FACEBUBBLEELEMSUBTYPENORMAL = 1; - int FACEBUBBLEELEMSUBTYPEUNKNOWN = 0; - int FETCHLONGMSGERRCODEMSGEXPIRED = 196; - int FILEELEMENTSUBTYPEAI = 16; - int FILEELEMENTSUBTYPEAPP = 11; - int FILEELEMENTSUBTYPEAUDIO = 3; - int FILEELEMENTSUBTYPEDOC = 4; - int FILEELEMENTSUBTYPEEMOTICON = 15; - int FILEELEMENTSUBTYPEEXCEL = 6; - int FILEELEMENTSUBTYPEFOLDER = 13; - int FILEELEMENTSUBTYPEHTML = 10; - int FILEELEMENTSUBTYPEIPA = 14; - int FILEELEMENTSUBTYPENORMAL = 0; - int FILEELEMENTSUBTYPEPDF = 7; - int FILEELEMENTSUBTYPEPIC = 1; - int FILEELEMENTSUBTYPEPPT = 5; - int FILEELEMENTSUBTYPEPSD = 12; - int FILEELEMENTSUBTYPETXT = 8; - int FILEELEMENTSUBTYPEVIDEO = 2; - int FILEELEMENTSUBTYPEZIP = 9; - int GRAYTIPELEMENTSUBTYPEAIOOP = 15; - int GRAYTIPELEMENTSUBTYPEBLOCK = 14; - int GRAYTIPELEMENTSUBTYPEBUDDY = 5; - int GRAYTIPELEMENTSUBTYPEBUDDYNOTIFY = 9; - int GRAYTIPELEMENTSUBTYPEEMOJIREPLY = 3; - int GRAYTIPELEMENTSUBTYPEESSENCE = 7; - int GRAYTIPELEMENTSUBTYPEFEED = 6; - int GRAYTIPELEMENTSUBTYPEFEEDCHANNELMSG = 11; - int GRAYTIPELEMENTSUBTYPEFILE = 10; - int GRAYTIPELEMENTSUBTYPEGROUP = 4; - int GRAYTIPELEMENTSUBTYPEGROUPNOTIFY = 8; - int GRAYTIPELEMENTSUBTYPEJSON = 17; - int GRAYTIPELEMENTSUBTYPELOCALMSG = 13; - int GRAYTIPELEMENTSUBTYPEPROCLAMATION = 2; - int GRAYTIPELEMENTSUBTYPEREVOKE = 1; - int GRAYTIPELEMENTSUBTYPEUNKNOWN = 0; - int GRAYTIPELEMENTSUBTYPEWALLET = 16; - int GRAYTIPELEMENTSUBTYPEXMLMSG = 12; - int INLINEKEYBOARDBUTTONRENDERSTYLEBLUEBLACKGROUND = 4; - int INLINEKEYBOARDBUTTONRENDERSTYLEBLUEBORDER = 1; - int INLINEKEYBOARDBUTTONRENDERSTYLEGRAYBORDER = 0; - int INLINEKEYBOARDBUTTONRENDERSTYLENOBORDER = 2; - int INLINEKEYBOARDBUTTONRENDERSTYLEREDCHARACTER = 3; - int INPUTSTATUSTYPECANCEL = 2; - int INPUTSTATUSTYPESPEAK = 3; - int INPUTSTATUSTYPETEXT = 1; - int KACTIVITYMSG = 22; - int KADDLOCALMSGEXTINFOTYPEPROLOGUEMSG = 1; - int KANONYMOUSATMEMSGTYPEINMSGBOX = 1001; - int KANONYMOUSFLAGFROMOTHERPEOPLE = 1; - int KANONYMOUSFLAGFROMOWN = 2; - int KANONYMOUSFLAGINVALID = 0; - int KAPPCHANNELMSG = 16; - int KATALLMSGTYPEINMSGBOX = 2000; - int KATMEMSGTYPEINMSGBOX = 1000; - int KATTRIBUTETYPEADELIEMSG = 16; - int KATTRIBUTETYPEEXTENDBUSINESS = 13; - int KATTRIBUTETYPEFEEDBACKSTATE = 17; - int KATTRIBUTETYPEGROUPHONOR = 2; - int KATTRIBUTETYPEKINGHONOR = 3; - int KATTRIBUTETYPELONGMSG = 8; - int KATTRIBUTETYPEMEMORYSTATEMSGINFO = 18; - int KATTRIBUTETYPEMSG = 0; - int KATTRIBUTETYPEMSGBOXEVENTTYPE = 14; - int KATTRIBUTETYPEPERSONAL = 1; - int KATTRIBUTETYPEPUBLICACCOUNT = 4; - int KATTRIBUTETYPEQQCONNECT = 12; - int KATTRIBUTETYPESENDMSGRSPTRANSSVRINFO = 15; - int KATTRIBUTETYPESHAREDMSGINFO = 5; - int KATTRIBUTETYPETEMPCHATGAMESESSION = 6; - int KATTRIBUTETYPETOROBOTMSG = 9; - int KATTRIBUTETYPEUININFO = 7; - int KATTRIBUTETYPEZPLAN = 11; - int KAUTOREPLYTEXTNONEINDEX = -1; - int KAVRECORDMSG = 19; - int KBUSINESSTYPGUILD = 1; - int KBUSINESSTYPNT = 0; - int KCHATTYPEADELIE = 42; - int KCHATTYPEBUDDYNOTIFY = 5; - int KCHATTYPEC2C = 1; - int KCHATTYPECIRCLE = 113; - int KCHATTYPEDATALINE = 8; - int KCHATTYPEDATALINEMQQ = 134; - int KCHATTYPEDISC = 3; - int KCHATTYPEFAV = 41; - int KCHATTYPEGAMEMESSAGE = 105; - int KCHATTYPEGAMEMESSAGEFOLDER = 116; - int KCHATTYPEGROUP = 2; - int KCHATTYPEGROUPBLESS = 133; - int KCHATTYPEGROUPGUILD = 9; - int KCHATTYPEGROUPHELPER = 7; - int KCHATTYPEGROUPNOTIFY = 6; - int KCHATTYPEGUILD = 4; - int KCHATTYPEGUILDMETA = 16; - int KCHATTYPEMATCHFRIEND = 104; - int KCHATTYPEMATCHFRIENDFOLDER = 109; - int KCHATTYPENEARBY = 106; - int KCHATTYPENEARBYASSISTANT = 107; - int KCHATTYPENEARBYFOLDER = 110; - int KCHATTYPENEARBYHELLOFOLDER = 112; - int KCHATTYPENEARBYINTERACT = 108; - int KCHATTYPEQQNOTIFY = 132; - int KCHATTYPERELATEACCOUNT = 131; - int KCHATTYPESERVICEASSISTANT = 118; - int KCHATTYPESERVICEASSISTANTSUB = 201; - int KCHATTYPESQUAREPUBLIC = 115; - int KCHATTYPESUBSCRIBEFOLDER = 30; - int KCHATTYPETEMPADDRESSBOOK = 111; - int KCHATTYPETEMPBUSSINESSCRM = 102; - int KCHATTYPETEMPC2CFROMGROUP = 100; - int KCHATTYPETEMPC2CFROMUNKNOWN = 99; - int KCHATTYPETEMPFRIENDVERIFY = 101; - int KCHATTYPETEMPNEARBYPRO = 119; - int KCHATTYPETEMPPUBLICACCOUNT = 103; - int KCHATTYPETEMPWPA = 117; - int KCHATTYPEUNKNOWN = 0; - int KCHATTYPEWEIYUN = 40; - int KCOMMONREDENVELOPEMSGTYPEINMSGBOX = 1007; - int KDOWNSOURCETYPEAIOINNER = 1; - int KDOWNSOURCETYPEBIGSCREEN = 2; - int KDOWNSOURCETYPEHISTORY = 3; - int KDOWNSOURCETYPEUNKNOWN = 0; - int KELEMTYPEACTIVITY = 25; - int KELEMTYPEACTIVITYSTATE = 41; - int KELEMTYPEACTIVITYSUBTYPECREATEMOBATEAM = 12; - int KELEMTYPEACTIVITYSUBTYPEDISBANDMOBATEAM = 11; - int KELEMTYPEACTIVITYSUBTYPEFEEDSQUARE = 10001; - int KELEMTYPEACTIVITYSUBTYPEFINISHGAME = 16; - int KELEMTYPEACTIVITYSUBTYPEFINISHMATCHTEAM = 14; - int KELEMTYPEACTIVITYSUBTYPEHOTCHAT = 10000; - int KELEMTYPEACTIVITYSUBTYPEMINIGAME = 18; - int KELEMTYPEACTIVITYSUBTYPEMUSICPLAY = 17; - int KELEMTYPEACTIVITYSUBTYPENEWSMOBA = 9; - int KELEMTYPEACTIVITYSUBTYPENOLIVE = 2; - int KELEMTYPEACTIVITYSUBTYPENOSCREENSHARE = 7; - int KELEMTYPEACTIVITYSUBTYPENOVOICE = 3; - int KELEMTYPEACTIVITYSUBTYPEONLIVE = 1; - int KELEMTYPEACTIVITYSUBTYPEONSCREENSHARE = 6; - int KELEMTYPEACTIVITYSUBTYPEONVOICE = 4; - int KELEMTYPEACTIVITYSUBTYPESTARTMATCHTEAM = 13; - int KELEMTYPEACTIVITYSUBTYPETARTGAME = 15; - int KELEMTYPEACTIVITYSUBTYPEUNKNOWN = 0; - int KELEMTYPEADELIEACTIONBAR = 44; - int KELEMTYPEADELIERECOMMENDEDMSG = 43; - int KELEMTYPEARKSTRUCT = 10; - int KELEMTYPEAVRECORD = 21; - int KELEMTYPECALENDAR = 19; - int KELEMTYPEFACE = 6; - int KELEMTYPEFACEBUBBLE = 27; - int KELEMTYPEFEED = 22; - int KELEMTYPEFILE = 3; - int KELEMTYPEGIPHY = 15; - int KELEMTYPEGRAYTIP = 8; - int KELEMTYPEINLINEKEYBOARD = 17; - int KELEMTYPEINTEXTGIFT = 18; - int KELEMTYPELIVEGIFT = 12; - int KELEMTYPEMARKDOWN = 14; - int KELEMTYPEMARKETFACE = 11; - int KELEMTYPEMULTIFORWARD = 16; - int KELEMTYPEONLINEFILE = 23; - int KELEMTYPEPIC = 2; - int KELEMTYPEPROLOGUE = 46; - int KELEMTYPEPTT = 4; - int KELEMTYPEREPLY = 7; - int KELEMTYPESHARELOCATION = 28; - int KELEMTYPESTRUCTLONGMSG = 13; - int KELEMTYPETASKTOPMSG = 29; - int KELEMTYPETEXT = 1; - int KELEMTYPETOFU = 26; - int KELEMTYPEUNKNOWN = 0; - int KELEMTYPEVIDEO = 5; - int KELEMTYPEWALLET = 9; - int KELEMTYPEYOLOGAMERESULT = 20; - int KENTERAIO = 1; - int KEXITAIO = 2; - int KFEEDBACKBUTTONTYPEDISLIKE = 2; - int KFEEDBACKBUTTONTYPELIKE = 1; - int KFEEDBACKBUTTONTYPEPROMPTCLICK = 5; - int KFEEDBACKBUTTONTYPEREGENERATE = 4; - int KFEEDBACKBUTTONTYPEUNKNOWN = 0; - int KFEEDBACKOPTLIKE = 1; - int KFEEDBACKOPTUNKNOWN = 0; - int KFEEDBACKOPTUNLIKE = 2; - int KFRIENDNEWADDEDMSGTYPEINMSGBOX = 1008; - int KGAMEBOXNEWMSGTYPEINMSGBOX = 3000; - int KGIFTATMEMSGTYPEINMSGBOX = 1005; - int KGROUPFILEATALLMSGTYPEINMSGBOX = 2001; - int KGROUPHOMEWORK = 20000; - int KGROUPHOMEWORKTASK = 20001; - int KGROUPKEYWORDMSGTYPEINMSGBOX = 2006; - int KGROUPMANNOUNCEATALLMSGTYPEINMSGBOX = 2004; - int KGROUPTASKATALLMSGTYPEINMSGBOX = 2003; - int KGROUPUNREADTYPEINMSGBOX = 2007; - int KGUILDCHANNELLIST = 10; - int KHIGHLIGHTWORDINTEMPCHATTYPEINMSGBOX = 1009; - int KHOMEWORKREMINDER = 10000; - int KLIKEORDISLIKESTATEDISLIKE = 2; - int KLIKEORDISLIKESTATELIKE = 1; - int KLIKEORDISLIKESTATENONESELECTED = 0; - int KMARKETFACE = 17; - int KMEMORYSTATEMSGTYPEADELIEWELCOME = 1; - int KMEMORYSTATEMSGTYPEUNKNOWN = 0; - int KMINIPROGRAMNOTICE = 114; - int KMSGSUBTYPEARKGROUPANNOUNCE = 3; - int KMSGSUBTYPEARKGROUPANNOUNCECONFIRMREQUIRED = 4; - int KMSGSUBTYPEARKGROUPGIFTATME = 5; - int KMSGSUBTYPEARKGROUPTASKATALL = 6; - int KMSGSUBTYPEARKMULTIMSG = 7; - int KMSGSUBTYPEARKNORMAL = 0; - int KMSGSUBTYPEARKTENCENTDOCFROMMINIAPP = 1; - int KMSGSUBTYPEARKTENCENTDOCFROMPLUSPANEL = 2; - int KMSGSUBTYPEEMOTICON = 15; - int KMSGSUBTYPEFILEAPP = 11; - int KMSGSUBTYPEFILEAUDIO = 3; - int KMSGSUBTYPEFILEDOC = 4; - int KMSGSUBTYPEFILEEXCEL = 6; - int KMSGSUBTYPEFILEFOLDER = 13; - int KMSGSUBTYPEFILEHTML = 10; - int KMSGSUBTYPEFILEIPA = 14; - int KMSGSUBTYPEFILENORMAL = 0; - int KMSGSUBTYPEFILEPDF = 7; - int KMSGSUBTYPEFILEPIC = 1; - int KMSGSUBTYPEFILEPPT = 5; - int KMSGSUBTYPEFILEPSD = 12; - int KMSGSUBTYPEFILETXT = 8; - int KMSGSUBTYPEFILEVIDEO = 2; - int KMSGSUBTYPEFILEZIP = 9; - int KMSGSUBTYPELINK = 5; - int KMSGSUBTYPEMARKETFACE = 1; - int KMSGSUBTYPEMIXEMOTICON = 7; - int KMSGSUBTYPEMIXFACE = 3; - int KMSGSUBTYPEMIXMARKETFACE = 2; - int KMSGSUBTYPEMIXPIC = 1; - int KMSGSUBTYPEMIXREPLY = 4; - int KMSGSUBTYPEMIXTEXT = 0; - int KMSGSUBTYPETENCENTDOC = 6; - int KMSGTYPEARKSTRUCT = 11; - int KMSGTYPEFACEBUBBLE = 24; - int KMSGTYPEFILE = 3; - int KMSGTYPEGIFT = 14; - int KMSGTYPEGIPHY = 13; - int KMSGTYPEGRAYTIPS = 5; - int KMSGTYPEMIX = 2; - int KMSGTYPEMULTIMSGFORWARD = 8; - int KMSGTYPENULL = 1; - int KMSGTYPEONLINEFILE = 21; - int KMSGTYPEONLINEFOLDER = 27; - int KMSGTYPEPROLOGUE = 29; - int KMSGTYPEPTT = 6; - int KMSGTYPEREPLY = 9; - int KMSGTYPESHARELOCATION = 25; - int KMSGTYPESTRUCT = 4; - int KMSGTYPESTRUCTLONGMSG = 12; - int KMSGTYPETEXTGIFT = 15; - int KMSGTYPEUNKNOWN = 0; - int KMSGTYPEVIDEO = 7; - int KMSGTYPEWALLET = 10; - int KNEEDCONFIRMGROUPMANNOUNCEATALLMSGTYPEINMSGBOX = 2005; - int KNOTPASSTHROUGHEVENTTYPEUPPERBOUNDARY = 9999; - int KPTTFORMATTYPEAMR = 0; - int KPTTFORMATTYPESILK = 1; - int KPTTTRANSLATESTATUSFAIL = 3; - int KPTTTRANSLATESTATUSSUC = 2; - int KPTTTRANSLATESTATUSTRANSLATING = 1; - int KPTTTRANSLATESTATUSUNKNOWN = 0; - int KPTTVIPLEVELTYPENONE = 0; - int KPTTVIPLEVELTYPEQQVIP = 0; - int KPTTVIPLEVELTYPESVIP = 0; - int KPTTVOICECHANGETYPEBEASTMACHINE = 7; - int KPTTVOICECHANGETYPEBOY = 2; - int KPTTVOICECHANGETYPECATCHCOLD = 13; - int KPTTVOICECHANGETYPEECHO = 5; - int KPTTVOICECHANGETYPEFATGUY = 16; - int KPTTVOICECHANGETYPEFLASHING = 9; - int KPTTVOICECHANGETYPEGIRL = 1; - int KPTTVOICECHANGETYPEHORRIBLE = 3; - int KPTTVOICECHANGETYPEKINDERGARTEN = 6; - int KPTTVOICECHANGETYPEMEDAROT = 15; - int KPTTVOICECHANGETYPENONE = 0; - int KPTTVOICECHANGETYPEOPTIMUSPRIME = 8; - int KPTTVOICECHANGETYPEOUTOFDATE = 14; - int KPTTVOICECHANGETYPEPAPI = 11; - int KPTTVOICECHANGETYPEQUICK = 4; - int KPTTVOICECHANGETYPESTUTTER = 10; - int KPTTVOICECHANGETYPETRAPPEDBEAST = 12; - int KPTTVOICETYPEINTERCOM = 1; - int KPTTVOICETYPESOUNDRECORD = 2; - int KPTTVOICETYPEUNKNOW = 0; - int KPTTVOICETYPEVOICECHANGE = 3; - int KPUBLICACCOUNTTIANSHUHIGHLIGHTWORDTYPEINMSGBOX = 1010; - int KREPLYABSELEMTYPEFACE = 2; - int KREPLYABSELEMTYPEPIC = 3; - int KREPLYABSELEMTYPETEXT = 1; - int KREPLYABSELEMTYPEUNKNOWN = 0; - int KREPLYATMEMSGTYPEINMSGBOX = 1002; - int KRMDOWNTYPEORIG = 1; - int KRMDOWNTYPETHUMB = 2; - int KRMDOWNTYPEUNKNOWN = 0; - int KRMFILETHUMBSIZE128 = 128; - int KRMFILETHUMBSIZE320 = 320; - int KRMFILETHUMBSIZE384 = 384; - int KRMFILETHUMBSIZE750 = 750; - int KRMPICAIOTHUMBSIZE = 0; - int KRMPICTHUMBSIZE198 = 198; - int KRMPICTHUMBSIZE720 = 720; - int KRMPICTYPEBMP = 3; - int KRMPICTYPECHECKOTHER = 900; - int KRMPICTYPEGIF = 2; - int KRMPICTYPEJPG = 0; - int KRMPICTYPENEWPICAPNG = 2001; - int KRMPICTYPENEWPICBMP = 1005; - int KRMPICTYPENEWPICGIF = 2000; - int KRMPICTYPENEWPICJPEG = 1000; - int KRMPICTYPENEWPICPNG = 1001; - int KRMPICTYPENEWPICPROGERSSIVJPEG = 1003; - int KRMPICTYPENEWPICSHARPP = 1004; - int KRMPICTYPENEWPICWEBP = 1002; - int KRMPICTYPEPNG = 1; - int KRMPICTYPEUNKOWN = 0; - int KRMTHUMBSIZEZERO = 0; - int KRMTRNASFERSTATUSDOWNLOADING = 3; - int KRMTRNASFERSTATUSFAIL = 5; - int KRMTRNASFERSTATUSINIT = 1; - int KRMTRNASFERSTATUSSUC = 4; - int KRMTRNASFERSTATUSUNKOW = 0; - int KRMTRNASFERSTATUSUPLOADING = 2; - int KRMTRNASFERSTATUSUSERCANCEL = 6; - int KSEEKINGPARTNERFLAGSEEKING = 1; - int KSEEKINGPARTNERFLAGUNKNOWN = 0; - int KSENDSTATUSFAILED = 0; - int KSENDSTATUSSENDING = 1; - int KSENDSTATUSSUCCESS = 2; - int KSENDSTATUSSUCCESSNOSEQ = 3; - int KSENDTYPEDROPPED = 6; - int KSENDTYPELOCAL = 3; - int KSENDTYPEOTHERDEVICE = 2; - int KSENDTYPERECV = 0; - int KSENDTYPESELF = 1; - int KSENDTYPESELFFORWARD = 4; - int KSENDTYPESELFMULTIFORWARD = 5; - int KSESSIONTYPEADDRESSBOOK = 5; - int KSESSIONTYPEC2C = 1; - int KSESSIONTYPEDISC = 3; - int KSESSIONTYPEFAV = 41; - int KSESSIONTYPEGROUP = 2; - int KSESSIONTYPEGROUPBLESS = 52; - int KSESSIONTYPEGUILD = 4; - int KSESSIONTYPEGUILDMETA = 16; - int KSESSIONTYPENEARBYPRO = 54; - int KSESSIONTYPEQQNOTIFY = 51; - int KSESSIONTYPERELATEACCOUNT = 50; - int KSESSIONTYPESERVICEASSISTANT = 19; - int KSESSIONTYPESUBSCRIBEFOLDER = 30; - int KSESSIONTYPETYPEBUDDYNOTIFY = 7; - int KSESSIONTYPETYPEGROUPHELPER = 9; - int KSESSIONTYPETYPEGROUPNOTIFY = 8; - int KSESSIONTYPEUNKNOWN = 0; - int KSESSIONTYPEWEIYUN = 40; - int KSPECIALCAREMSGTYPEINMSGBOX = 1006; - int KSPECIFIEDREDENVELOPEATMEMSGTYPEINMSGBOX = 1004; - int KSPECIFIEDREDENVELOPEATONEMSGTYPEINMSGBOX = 1003; - int KTENCENTDOCTYPEADDON = 110; - int KTENCENTDOCTYPEDOC = 0; - int KTENCENTDOCTYPEDRAWING = 89; - int KTENCENTDOCTYPEDRIVE = 101; - int KTENCENTDOCTYPEFILE = 100; - int KTENCENTDOCTYPEFLOWCHART = 91; - int KTENCENTDOCTYPEFOLDER = 3; - int KTENCENTDOCTYPEFORM = 2; - int KTENCENTDOCTYPEMIND = 90; - int KTENCENTDOCTYPENOTES = 5; - int KTENCENTDOCTYPEPDF = 6; - int KTENCENTDOCTYPEPROGRAM = 7; - int KTENCENTDOCTYPESHEET = 1; - int KTENCENTDOCTYPESLIDE = 4; - int KTENCENTDOCTYPESMARTCANVAS = 8; - int KTENCENTDOCTYPESMARTSHEET = 9; - int KTENCENTDOCTYPESPEECH = 102; - int KTENCENTDOCTYPEUNKNOWN = 10; - int KTOFURECORDMSG = 23; - int KTOPMSGTYPETASK = 1; - int KTOPMSGTYPEUNKNOWN = 0; - int KTRIGGERTYPEAUTO = 1; - int KTRIGGERTYPEMANUAL = 0; - int KUNKNOWN = 0; - int KUNKNOWNTYPEINMSGBOX = 0; - int KUNREADCNTUPTYPEALLDIRECTSESSION = 4; - int KUNREADCNTUPTYPEALLFEEDSINGUILD = 6; - int KUNREADCNTUPTYPEALLGUILD = 3; - int KUNREADCNTUPTYPECATEGORY = 5; - int KUNREADCNTUPTYPECHANNEL = 1; - int KUNREADCNTUPTYPECONTACT = 0; - int KUNREADCNTUPTYPEGUILD = 2; - int KUNREADCNTUPTYPEGUILDGROUP = 7; - int KUNREADSHOWTTYPEGRAYPOINT = 2; - int KUNREADSHOWTYPEREDPOINT = 1; - int KUNREADSHOWTYPESMALLGRAYPOINT = 4; - int KUNREADSHOWTYPESMALLREDPOINT = 3; - int KUNREADSHOWTYPEUNKNOWN = 0; - int KVASGIFTCOINTYPECOIN = 0; - int KVASGIFTCOINTYPEMARKETCOIN = 1; - int KYOLOGAMERESULTMSG = 18; - int PIC_800_RECOMMENDED = 7; - int PIC_AIGC_EMOJI = 14; - int PIC_ALBUM_GIF = 11; - int PIC_COMMERCIAL_ADVERTISING = 9; - int PIC_FIND = 10; - int PIC_HOT = 2; - int PIC_HOT_EMOJI = 13; - int PIC_NORMAL = 0; - int PIC_PK = 3; - int PIC_QQZONE = 5; - int PIC_SELFIE_GIF = 8; - int PIC_SEND_FROM_TAB_SEARCH_BOX = 12; - int PIC_USER = 1; - int PIC_WISDOM_FIGURE = 4; - int REPLYORIGINALMSGSTATEHASRECALL = 1; - int REPLYORIGINALMSGSTATEUNKNOWN = 0; - int SHARELOCATIONELEMSUBTYPENORMAL = 1; - int SHARELOCATIONELEMSUBTYPEUNKNOWN = 0; - int TEXTELEMENTSUBTYPELINK = 1; - int TEXTELEMENTSUBTYPETENCENTDOC = 2; - int TEXTELEMENTSUBTYPEUNKNOWN = 0; -``` \ No newline at end of file diff --git a/docs/develop/NC 1.6.X的计划.md b/docs/develop/NC 1.6.X的计划.md deleted file mode 100644 index 8332b3cc..00000000 --- a/docs/develop/NC 1.6.X的计划.md +++ /dev/null @@ -1,16 +0,0 @@ -# 开发方向 -方向一 NativeCall/Hook: -1. 崩溃检测机制的实现 -2. Api_Caller 的Hook 可以拿到Event/Handler 进一步提升NC 即时的拦截与处理一些事件比如ReCall拦截 -3. Node包装层 进一步分析,拿到脱离自带Listener/Adapter,可以拿到一些更加底层的数据变动 或许包括更多二进制数据 - -方向二 全新的无头启动 Way01 -1. 基于Node启动原理,借助导出符号获取函数地址 再次还原NodeMain - -方向三 发包与收包 -1. 参考 方向一/3 大概可以收包 -2. 发包 (暂时没有计划) - -方向四 版本控制 -1. 根据不同版本进行逻辑控制 -2. 某些参数的自动提取 \ No newline at end of file diff --git a/docs/develop/碎碎的研究记录.md b/docs/develop/碎碎的研究记录.md deleted file mode 100644 index a98db747..00000000 --- a/docs/develop/碎碎的研究记录.md +++ /dev/null @@ -1,8 +0,0 @@ -# Api方向 -## getMsgUniqueId √ 已应用 -getMsgUniqueId 传入时间 产出一个唯一ID 发送消息作为一个参数 - -# Native方向 -## magic_load -## api_caller -## NodeMain diff --git a/script/BootWay.03.ps1 b/script/BootWay.03.ps1 deleted file mode 100644 index d4fb6707..00000000 --- a/script/BootWay.03.ps1 +++ /dev/null @@ -1,45 +0,0 @@ -# Dont Use This Script -# 2024.7.3 -function Get-QQpath { - try { - $key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" - $uninstallString = $key.UninstallString - return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe" - } - catch { - throw "get QQ path error: $_" - } -} -function Select-QQPath { - Add-Type -AssemblyName System.Windows.Forms - [System.Windows.Forms.Application]::EnableVisualStyles() - - $dialogTitle = "Select QQ.exe" - - $filePicker = New-Object System.Windows.Forms.OpenFileDialog - $filePicker.Title = $dialogTitle - $filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*" - $filePicker.FilterIndex = 1 - $null = $filePicker.ShowDialog() - if (-not ($filePicker.FileName)) { - throw "User did not select an .exe file." - } - return $filePicker.FileName -} - -$params = $args -join " " -Try { - $QQpath = Get-QQpath -} -Catch { - $QQpath = Select-QQPath -} - -if (!(Test-Path $QQpath)) { - throw "provided QQ path is invalid: $QQpath" -} - -$Bootfile = Join-Path $PSScriptRoot "napcat.mjs" -$env:ELECTRON_RUN_AS_NODE = 1 -$commandInfo = Get-Command $QQpath -ErrorAction Stop -Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& '$($commandInfo.Path)' --enable-logging }" \ No newline at end of file diff --git a/script/BootWay05.bat b/script/BootWay05.bat deleted file mode 100644 index 95b4299e..00000000 --- a/script/BootWay05.bat +++ /dev/null @@ -1,90 +0,0 @@ -@echo off -REM 检查当前会话是否具有管理员权限 -openfiles >nul 2>&1 -if %errorlevel% neq 0 ( - REM 如果不是管理员,则重新启动脚本以管理员模式运行 - echo 请求管理员权限... - powershell -Command "Start-Process cmd -ArgumentList '/c %~f0 %*' -Verb RunAs" - exit /b -) - -REM 设置当前工作目录 -cd /d %~dp0 - -REM 获取当前目录路径 -set currentPath=%cd% -set currentPath=%currentPath:\=/% - -REM 生成JavaScript代码 -set "jsCode=(async () =^>await import('file:///%currentPath%/napcat.mjs'))();" - -REM 将JavaScript代码保存到文件中 -echo %jsCode% > loadScript.js -echo JavaScript code has been generated and saved to loadScript.js - -REM 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址 -set NAPCAT_PATH=%cd%\loadScript.js - -REM 获取QQ路径 - - -:loop_read -for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do ( - set RetString=%%b - goto :napcat_boot -) - -:napcat_boot -for %%a in (%RetString%) do ( - set "pathWithoutUninstall=%%~dpa" -) - -SET QQPath=%pathWithoutUninstall%QQ.exe - -REM 拿不到QQ路径则退出 -if not exist "%QQpath%" ( - echo provided QQ path is invalid: %QQpath% - pause - exit /b -) - -REM 收集dbghelp.dll路径和HASH信息 -set QQdir=%~dp0 -set oldDllPath=%QQdir%dbghelp.dll -set newDllPath=%currentPath%\dbghelp.dll - -for /f "tokens=*" %%A in ('certutil -hashfile "%oldDllPath%" MD5') do ( - if not defined oldDllHash set oldDllHash=%%A -) -for /f "tokens=*" %%A in ('certutil -hashfile "%newDllPath%" MD5') do ( - if not defined newDllHash set newDllHash=%%A -) - -REM 如果文件一致则跳过 -if "%oldDllHash%" neq "%newDllHash%" ( - tasklist /fi "imagename eq QQ.exe" 2>nul | find /i "QQ.exe" >nul - if %errorlevel% equ 0 ( - REM 文件占用则退出 - echo dbghelp.dll is in use, cannot continue. - ) else ( - REM 文件未占用则尝试覆盖 - copy /y "%newDllPath%" "%oldDllPath%" - if %errorlevel% neq 0 ( - echo Failed to copy dbghelp.dll - pause - exit /b - ) else ( - echo dbghelp.dll has been copied to %QQdir% - ) - ) -) - -REM 带参数启动QQ -REM 判断wt是否存在,存在则通过wt启动,不存在则通过cmd启动 -REM %QQPath% --enable-logging %* -where wt >nul 2>nul -if %errorlevel% equ 0 ( - wt "cmd" /c "%QQPath%" --enable-logging %* -) else ( - %QQPath%" --enable-logging %* -) diff --git a/script/BootWay05.ps1 b/script/BootWay05.ps1 deleted file mode 100644 index 862281ef..00000000 --- a/script/BootWay05.ps1 +++ /dev/null @@ -1,123 +0,0 @@ -# 检查当前会话是否具有管理员权限 -function Test-Administrator { - $user = [Security.Principal.WindowsIdentity]::GetCurrent() - (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) -} - -if (-not (Test-Administrator)) { - # 如果不是管理员,则重新启动脚本以管理员模式运行 - $scriptPath = $myInvocation.MyCommand.Path - if (-not $scriptPath) { - $scriptPath = $PSCommandPath - } - $newProcess = New-Object System.Diagnostics.ProcessStartInfo "powershell"; - $newProcess.Arguments = "-File `"$scriptPath`" $args" - $newProcess.Verb = "runas"; - [System.Diagnostics.Process]::Start($newProcess); - exit -} - -function Get-QQpath { - try { - $key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" - $uninstallString = $key.UninstallString - return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe" - } - catch { - throw "get QQ path error: $_" - } -} -function Select-QQPath { - Add-Type -AssemblyName System.Windows.Forms - [System.Windows.Forms.Application]::EnableVisualStyles() - - $dialogTitle = "Select QQ.exe" - - $filePicker = New-Object System.Windows.Forms.OpenFileDialog - $filePicker.Title = $dialogTitle - $filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*" - $filePicker.FilterIndex = 1 - $null = $filePicker.ShowDialog() - if (-not ($filePicker.FileName)) { - throw "User did not select an .exe file." - } - return $filePicker.FileName -} - -# 设置当前工作目录 -$scriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent -Set-Location $scriptDirectory - -# 获取当前目录路径 -$currentPath = Get-Location - -# 替换\为/ -$currentPath = $currentPath -replace '\\', '/' - -# 生成JavaScript代码 -$jsCode = @" -(async () => { - await import('file:///$currentPath/napcat.mjs'); -})(); -"@ - -# 将JavaScript代码保存到文件中 -$jsFilePath = Join-Path $currentPath "loadScript.js" -$jsCode | Out-File -FilePath $jsFilePath -Encoding UTF8 - -Write-Output "JavaScript code has been generated and saved to $jsFilePath" -# 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址 -$env:NAPCAT_PATH = $jsFilePath - -$params = $args -join " " -Try { - $QQpath = Get-QQpath -} -Catch { - $QQpath = Select-QQPath -} -# 拿不到QQ路径则退出 -if (!(Test-Path $QQpath)) { - Write-Output "provided QQ path is invalid: $QQpath" - Read-Host "Press any key to continue..." - exit -} - -$commandInfo = Get-Command $QQpath -ErrorAction Stop - -# 收集dbghelp.dll路径和HASH信息 -$QQpath = Split-Path $QQpath -$oldDllPath = Join-Path $QQpath "dbghelp.dll" -$oldDllHash = Get-FileHash $oldDllPath -Algorithm MD5 -$newDllPath = Join-Path $currentPath "dbghelp.dll" -$newDllHash = Get-FileHash $newDllPath -Algorithm MD5 -# 如果文件一致则跳过 -if ($oldDllHash.Hash -ne $newDllHash.Hash) { - $processes = Get-Process -Name QQ -ErrorAction SilentlyContinue - if ($processes) { - # 文件占用则退出 - Write-Output "dbghelp.dll is in use by the following processes:" - $processes | ForEach-Object { Write-Output "$($_.Id) $($_.Name) $($_.Path)" } - Write-Output "dbghelp.dll is in use, cannot continue." - Read-Host "Press any key to continue..." - exit - } else { - # 文件未占用则尝试覆盖 - try { - Copy-Item -Path "$newDllPath" -Destination "$oldDllPath" -Force - Write-Output "dbghelp.dll has been copied to $QQpath" - } catch { - Write-Output "Failed to copy dbghelp.dll: $_" - Read-Host "Press any key to continue..." - exit - } - } -} - -# 带参数启动QQ -try { - Start-Process powershell -ArgumentList '-noexit', '-noprofile', "-command &{& chcp 65001;& '$($commandInfo.Path)' --enable-logging $params}" -NoNewWindow -ErrorAction Stop -} catch { - Write-Output "Failed to start process as administrator: $_" - Read-Host "Press any key to continue..." -} \ No newline at end of file diff --git a/script/BootWay05.utf8.bat b/script/BootWay05.utf8.bat deleted file mode 100644 index 2836a38a..00000000 --- a/script/BootWay05.utf8.bat +++ /dev/null @@ -1,93 +0,0 @@ -@echo off -REM 检查当前会话是否具有管理员权限 -openfiles >nul 2>&1 -if %errorlevel% neq 0 ( - REM 如果不是管理员,则重新启动脚本以管理员模式运行 - echo 请求管理员权限... - where wt >nul 2>nul - if %errorlevel% equ 0 ( - powershell -Command "Start-Process cmd -ArgumentList ' /c %~f0 %*' -Verb RunAs" - ) else ( - powershell -Command "Start-Process wt -ArgumentList 'cmd /c %~f0 %*' -Verb RunAs" - ) - - REM wt "cmd" /c "%~f0 %*" - exit /b -) - -REM 设置当前工作目录 -cd /d %~dp0 - -REM 获取当前目录路径 -set currentPath=%cd% -set currentPath=%currentPath:\=/% - -REM 生成JavaScript代码 -set "jsCode=(async () =^>await import('file:///%currentPath%/napcat.mjs'))();" - -REM 将JavaScript代码保存到文件中 -echo %jsCode% > loadScript.js -echo JavaScript code has been generated and saved to loadScript.js - -REM 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址 -set NAPCAT_PATH=%cd%\loadScript.js - -REM 获取QQ路径 - - -:loop_read -for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do ( - set RetString=%%b - goto :napcat_boot -) - -:napcat_boot -for %%a in (%RetString%) do ( - set "pathWithoutUninstall=%%~dpa" -) - -SET QQPath=%pathWithoutUninstall%QQ.exe - -REM 拿不到QQ路径则退出 -if not exist "%QQpath%" ( - echo provided QQ path is invalid: %QQpath% - pause - exit /b -) - -REM 收集dbghelp.dll路径和HASH信息 -set QQdir=%~dp0 -set oldDllPath=%QQdir%dbghelp.dll -set newDllPath=%currentPath%\dbghelp.dll - -for /f "tokens=*" %%A in ('certutil -hashfile "%oldDllPath%" MD5') do ( - if not defined oldDllHash set oldDllHash=%%A -) -for /f "tokens=*" %%A in ('certutil -hashfile "%newDllPath%" MD5') do ( - if not defined newDllHash set newDllHash=%%A -) - -REM 如果文件一致则跳过 -if "%oldDllHash%" neq "%newDllHash%" ( - tasklist /fi "imagename eq QQ.exe" 2>nul | find /i "QQ.exe" >nul - if %errorlevel% equ 0 ( - REM 文件占用则退出 - echo dbghelp.dll is in use, cannot continue. - ) else ( - REM 文件未占用则尝试覆盖 - copy /y "%newDllPath%" "%oldDllPath%" - if %errorlevel% neq 0 ( - echo Failed to copy dbghelp.dll - pause - exit /b - ) else ( - echo dbghelp.dll has been copied to %QQdir% - ) - ) -) - -REM 带参数启动QQ -REM 判断wt是否存在,存在则通过wt启动,不存在则通过cmd启动 -REM %QQPath% --enable-logging %* -chcp 65001 -"%QQPath%" --enable-logging %* diff --git a/script/NapCat.164.bat b/script/NapCat.164.bat deleted file mode 100644 index 679f0373..00000000 --- a/script/NapCat.164.bat +++ /dev/null @@ -1,28 +0,0 @@ -@echo off -chcp 65001 -:: 检查是否有管理员权限 -net session >nul 2>&1 -if %errorlevel% neq 0 ( - echo 请求管理员权限... - powershell -Command "Start-Process '%~f0' -Verb runAs" - exit /b -) -:: 如果有管理员权限,继续执行 -setlocal enabledelayedexpansion -:loop_read -for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do ( - set "RetString=%%b" - goto :napcat_boot -) - -:napcat_boot -for %%a in ("!RetString!") do ( - set "pathWithoutUninstall=%%~dpa" -) - -set "QQPath=!pathWithoutUninstall!QQ.exe" - -echo !QQPath! -"!QQPath!" --enable-logging %* - -pause diff --git a/script/NapCat.Way01.bat b/script/NapCat.Way01.bat deleted file mode 100644 index dd12843d..00000000 --- a/script/NapCat.Way01.bat +++ /dev/null @@ -1,3 +0,0 @@ -REM 全新启动脚本 基于 Hook Native 预计版本1.6.0左右发布 -@echo off -pause \ No newline at end of file diff --git a/script/checkVersion.cjs b/script/checkVersion.cjs deleted file mode 100644 index 6863b9c9..00000000 --- a/script/checkVersion.cjs +++ /dev/null @@ -1,42 +0,0 @@ -const fs = require("fs"); -const process = require("process"); - -console.log("[NapCat] [CheckVersion] 开始检测当前仓库版本..."); -try { - const packageJson = require("../package.json"); - const currentVersion = packageJson.version; - const targetVersion = process.env.VERSION; - - console.log("[NapCat] [CheckVersion] currentVersion:", currentVersion, "targetVersion:", targetVersion); - - // 验证 targetVersion 格式 - if (!targetVersion || typeof targetVersion !== 'string') { - console.error("[NapCat] [CheckVersion] 目标版本格式不正确或未设置!"); - return; - } - - // 写入脚本文件的统一函数 - const writeScriptToFile = (content) => { - fs.writeFileSync("./checkVersion.sh", content, { flag: 'w' }); - console.log("[NapCat] [CheckVersion] checkVersion.sh 文件已更新。"); - }; - - if (currentVersion === targetVersion) { - // 不需要更新版本,写入一个简单的脚本 - const simpleScript = "#!/bin/bash\necho \"CheckVersion Is Done\""; - writeScriptToFile(simpleScript); - } else { - // 更新版本,构建安全的sed命令 - const safeScriptContent = ` - #!/bin/bash - git config --global user.email "bot@test.wumiao.wang" - git config --global user.name "Version" - sed -i "s/\\\"version\\\": \\\"${currentVersion}\\\"/\\\"version\\\": \\\"${targetVersion}\\\"/g" package.json - git add . - git commit -m "chore:version change" - git push -u origin main`; - writeScriptToFile(safeScriptContent); - } -} catch (error) { - console.error("[NapCat] [CheckVersion] 检测过程中发生错误:", error); -} \ No newline at end of file diff --git a/script/copy-core.cjs b/script/copy-core.cjs deleted file mode 100644 index dc294247..00000000 --- a/script/copy-core.cjs +++ /dev/null @@ -1,32 +0,0 @@ -let fs = require('fs'); -let path = require('path'); - -const coreDistDir = path.join(path.resolve(__dirname, '../'), 'src/core/dist/core/src'); -const coreLibDir = path.join(path.resolve(__dirname, '../'), 'src/core.lib/src'); - -function copyDir(currentPath, outputDir) { - fs.readdir(currentPath, { withFileTypes: true }, (err, entries) => { - if (err?.errno === -4058) return; - - entries.forEach(entry => { - const localBasePath = path.join(currentPath, entry.name); - const outputLocalBasePath = path.join(outputDir, entry.name); - - if (entry.isDirectory()) { - // 如果是目录,递归调用 - if (!fs.existsSync(outputLocalBasePath)) { - fs.mkdirSync(outputLocalBasePath, { recursive: true }); - } - copyDir(localBasePath, outputLocalBasePath); - } - else{ - // 如果是文件,直接复制 - fs.copyFile(localBasePath, outputLocalBasePath, (err) => { - if (err) throw err; - }); - } - }); - }); -} - -copyDir(coreDistDir, coreLibDir); diff --git a/script/dbghelp.dll b/script/dbghelp.dll deleted file mode 100644 index f1fbedf5..00000000 Binary files a/script/dbghelp.dll and /dev/null differ diff --git a/script/gen-version.ts b/script/gen-version.ts deleted file mode 100644 index 7ab21a07..00000000 --- a/script/gen-version.ts +++ /dev/null @@ -1,21 +0,0 @@ -import fs from 'fs' -import path from 'path' -import { version } from '../src/onebot11/version' - -const manifestPath = path.join(__dirname, '../package.json') - -function readManifest (): any { - if (fs.existsSync(manifestPath)) { - return JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) - } -} - -function writeManifest (manifest: any) { - fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2)) -} - -const manifest = readManifest() -if (version !== manifest.version) { - manifest.version = version - writeManifest(manifest) -} diff --git a/script/index.js b/script/index.js deleted file mode 100644 index 322fb97d..00000000 --- a/script/index.js +++ /dev/null @@ -1,20 +0,0 @@ -// -------------------- -// 2024.7.3 9.9.12 BootWay.03 其余方法暂不公开(此方案为临时方案 Win平台已验证) - -// 1.与非入侵式不同 现在破坏本体代码 -// 2.重启代码与正常启动代码失效 -// 3.Win需要补丁 -// 4.更新后丢失内容 需要重写此文件 -// 5.安装难度上升与周围基础设施失效 -// -------------------- - -const path = require('path'); -const CurrentPath = path.dirname(__filename) -const hasNapcatParam = process.argv.includes('--enable-logging'); -if (hasNapcatParam) { - (async () => { - await import("file://" + path.join(CurrentPath, './napcat/napcat.mjs')); - })(); -} else { - require('./launcher.node').load('external_index', module); -} \ No newline at end of file diff --git a/script/napcat-9912-utf8.bat b/script/napcat-9912-utf8.bat deleted file mode 100644 index 2fec84db..00000000 --- a/script/napcat-9912-utf8.bat +++ /dev/null @@ -1,18 +0,0 @@ -@echo off -setlocal enabledelayedexpansion -chcp 65001 -:loop_read -for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do ( - set "RetString=%%b" - goto :napcat_boot -) - -:napcat_boot -for %%a in ("!RetString!") do ( - set "pathWithoutUninstall=%%~dpa" -) - -set "QQPath=!pathWithoutUninstall!" -cd /d !QQPath! -echo !QQPath! -QQ.exe --enable-logging %* \ No newline at end of file diff --git a/script/napcat-9912-utf8.ps1 b/script/napcat-9912-utf8.ps1 deleted file mode 100644 index 640dabe3..00000000 --- a/script/napcat-9912-utf8.ps1 +++ /dev/null @@ -1,41 +0,0 @@ -function Get-QQpath { - try { - $key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" - $uninstallString = $key.UninstallString - return [System.IO.Path]::GetDirectoryName($uninstallString) + "\" - } - catch { - throw "get QQ path error: $_" - } -} -function Select-QQPath { - Add-Type -AssemblyName System.Windows.Forms - [System.Windows.Forms.Application]::EnableVisualStyles() - - $dialogTitle = "Select QQ.exe" - - $filePicker = New-Object System.Windows.Forms.OpenFileDialog - $filePicker.Title = $dialogTitle - $filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*" - $filePicker.FilterIndex = 1 - $null = $filePicker.ShowDialog() - if (-not ($filePicker.FileName)) { - throw "User did not select an .exe file." - } - return $filePicker.FileName -} - -$params = $args -join " " -Try { - $QQpath = Get-QQpath -} -Catch { - $QQpath = Select-QQPath -} - -if (!(Test-Path $QQpath)) { - throw "provided QQ path is invalid: $QQpath" -} - -Set-Location -Path $QQpath -Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& ./QQ.exe --enable-logging $params}" diff --git a/script/napcat-9912.bat b/script/napcat-9912.bat deleted file mode 100644 index c45e2303..00000000 --- a/script/napcat-9912.bat +++ /dev/null @@ -1,17 +0,0 @@ -@echo off -setlocal enabledelayedexpansion -:loop_read -for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do ( - set "RetString=%%b" - goto :napcat_boot -) - -:napcat_boot -for %%a in ("!RetString!") do ( - set "pathWithoutUninstall=%%~dpa" -) - -set QQPath=!pathWithoutUninstall! -cd /d !QQPath! -echo !QQPath! -QQ.exe --enable-logging %* \ No newline at end of file diff --git a/script/napcat-9912.ps1 b/script/napcat-9912.ps1 deleted file mode 100644 index b506f512..00000000 --- a/script/napcat-9912.ps1 +++ /dev/null @@ -1,41 +0,0 @@ -function Get-QQpath { - try { - $key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" - $uninstallString = $key.UninstallString - return [System.IO.Path]::GetDirectoryName($uninstallString) + "\" - } - catch { - throw "get QQ path error: $_" - } -} -function Select-QQPath { - Add-Type -AssemblyName System.Windows.Forms - [System.Windows.Forms.Application]::EnableVisualStyles() - - $dialogTitle = "Select QQ.exe" - - $filePicker = New-Object System.Windows.Forms.OpenFileDialog - $filePicker.Title = $dialogTitle - $filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*" - $filePicker.FilterIndex = 1 - $null = $filePicker.ShowDialog() - if (-not ($filePicker.FileName)) { - throw "User did not select an .exe file." - } - return $filePicker.FileName -} - -$params = $args -join " " -Try { - $QQpath = Get-QQpath -} -Catch { - $QQpath = Select-QQPath -} - -if (!(Test-Path $QQpath)) { - throw "provided QQ path is invalid: $QQpath" -} - -Set-Location -Path $QQpath -Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& ./QQ.exe --enable-logging $params}" \ No newline at end of file diff --git a/script/napcat-custom.bat b/script/napcat-custom.bat deleted file mode 100644 index a8e6f5ea..00000000 --- a/script/napcat-custom.bat +++ /dev/null @@ -1,3 +0,0 @@ -chcp 65001 -set ELECTRON_RUN_AS_NODE=1 -"H:\Program Files\QQNT最新版\QQ.exe" %~dp0/napcat.cjs %* diff --git a/script/napcat-gc.ps1 b/script/napcat-gc.ps1 deleted file mode 100644 index 9fea136d..00000000 --- a/script/napcat-gc.ps1 +++ /dev/null @@ -1,15 +0,0 @@ -function Get-QQpath { - try { - $key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" - $uninstallString = $key.UninstallString - return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe" - } - catch { - throw "Error getting UninstallString: $_" - } -} -$params = $args -join " " -$QQpath = Get-QQpath -$Bootfile = Join-Path (Get-Location) "\dist\inject.cjs" -$env:ELECTRON_RUN_AS_NODE = 1 -Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& '$QQpath' --expose-gc $Bootfile $params}" diff --git a/script/napcat-log.ps1 b/script/napcat-log.ps1 deleted file mode 100644 index 90ea28be..00000000 --- a/script/napcat-log.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -function Get-QQpath { - try { - $key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" - $uninstallString = $key.UninstallString - return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe" - } - catch { - return "D:\QQ.exe" - } -} -$params = $args -join " " -$QQpath = Get-QQpath -$Bootfile = Join-Path $PSScriptRoot "napcat.cjs" -$env:ELECTRON_RUN_AS_NODE = 1 -$argumentList = '-noexit', '-noprofile', "-command `"$QQpath`" `"$Bootfile`" $params" -Start-Process powershell -ArgumentList $argumentList -RedirectStandardOutput "log.txt" -RedirectStandardError "error.txt" -powershell Get-Content -Wait -Encoding UTF8 log.txt diff --git a/script/napcat-utf8.bat b/script/napcat-utf8.bat deleted file mode 100644 index 9b15ce8a..00000000 --- a/script/napcat-utf8.bat +++ /dev/null @@ -1,18 +0,0 @@ -@echo off -setlocal enabledelayedexpansion -chcp 65001 -:loop_read -for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do ( - set "RetString=%%b" - goto :napcat_boot -) - -:napcat_boot -for %%a in ("!RetString!") do ( - set "pathWithoutUninstall=%%~dpa" -) - -set "QQPath=!pathWithoutUninstall!QQ.exe" -set ELECTRON_RUN_AS_NODE=1 -echo !QQPath! -"!QQPath!" ./napcat.mjs %* diff --git a/script/napcat-utf8.ps1 b/script/napcat-utf8.ps1 deleted file mode 100644 index 7fc71c3f..00000000 --- a/script/napcat-utf8.ps1 +++ /dev/null @@ -1,43 +0,0 @@ -function Get-QQpath { - try { - $key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" - $uninstallString = $key.UninstallString - return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe" - } - catch { - throw "get QQ path error: $_" - } -} -function Select-QQPath { - Add-Type -AssemblyName System.Windows.Forms - [System.Windows.Forms.Application]::EnableVisualStyles() - - $dialogTitle = "Select QQ.exe" - - $filePicker = New-Object System.Windows.Forms.OpenFileDialog - $filePicker.Title = $dialogTitle - $filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*" - $filePicker.FilterIndex = 1 - $null = $filePicker.ShowDialog() - if (-not ($filePicker.FileName)) { - throw "User did not select an .exe file." - } - return $filePicker.FileName -} - -$params = $args -join " " -Try { - $QQpath = Get-QQpath -} -Catch { - $QQpath = Select-QQPath -} - -if (!(Test-Path $QQpath)) { - throw "provided QQ path is invalid: $QQpath" -} - -$Bootfile = Join-Path $PSScriptRoot "napcat.mjs" -$env:ELECTRON_RUN_AS_NODE = 1 -$commandInfo = Get-Command $QQpath -ErrorAction Stop -Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& '$($commandInfo.Path)' $Bootfile $params}" \ No newline at end of file diff --git a/script/napcat.bat b/script/napcat.bat deleted file mode 100644 index 0b96b596..00000000 --- a/script/napcat.bat +++ /dev/null @@ -1,17 +0,0 @@ -@echo off -setlocal enabledelayedexpansion -:loop_read -for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do ( - set "RetString=%%b" - goto :napcat_boot -) - -:napcat_boot -for %%a in ("!RetString!") do ( - set "pathWithoutUninstall=%%~dpa" -) - -set "QQPath=!pathWithoutUninstall!QQ.exe" -set ELECTRON_RUN_AS_NODE=1 -echo !QQPath! -"!QQPath!" ./napcat.mjs %* diff --git a/script/napcat.ps1 b/script/napcat.ps1 deleted file mode 100644 index e38aca7b..00000000 --- a/script/napcat.ps1 +++ /dev/null @@ -1,43 +0,0 @@ -function Get-QQpath { - try { - $key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" - $uninstallString = $key.UninstallString - return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe" - } - catch { - throw "get QQ path error: $_" - } -} -function Select-QQPath { - Add-Type -AssemblyName System.Windows.Forms - [System.Windows.Forms.Application]::EnableVisualStyles() - - $dialogTitle = "Select QQ.exe" - - $filePicker = New-Object System.Windows.Forms.OpenFileDialog - $filePicker.Title = $dialogTitle - $filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*" - $filePicker.FilterIndex = 1 - $null = $filePicker.ShowDialog() - if (-not ($filePicker.FileName)) { - throw "User did not select an .exe file." - } - return $filePicker.FileName -} - -$params = $args -join " " -Try { - $QQpath = Get-QQpath -} -Catch { - $QQpath = Select-QQPath -} - -if (!(Test-Path $QQpath)) { - throw "provided QQ path is invalid: $QQpath" -} - -$Bootfile = Join-Path $PSScriptRoot "napcat.mjs" -$env:ELECTRON_RUN_AS_NODE = 1 -$commandInfo = Get-Command $QQpath -ErrorAction Stop -Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& '$($commandInfo.Path)' $Bootfile $params}" \ No newline at end of file diff --git a/script/napcat.sh b/script/napcat.sh deleted file mode 100644 index 36198acb..00000000 --- a/script/napcat.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -get_script_dir() { - local script_path="${1:-$0}" - local script_dir - script_path=$(readlink -f "$script_path") - script_dir=$(dirname "$script_path") - - echo "$script_dir" -} - -SCRIPT_DIR=$(get_script_dir) - -export ELECTRON_RUN_AS_NODE=1 - -if ! [ -x /opt/QQ/qq ]; then - echo "Error: /opt/QQ/qq is not executable or does not exist." >&2 - exit 1 -fi - -/opt/QQ/qq "${SCRIPT_DIR}/napcat.mjs" "$@" diff --git a/src/common/server/http.ts b/src/common/server/http.ts deleted file mode 100644 index a507b32c..00000000 --- a/src/common/server/http.ts +++ /dev/null @@ -1,132 +0,0 @@ -import express, { Express, Request, Response } from 'express'; -import cors from 'cors'; -import http from 'http'; -import { log, logDebug, logError } from '../utils/log'; -import { ob11Config } from '@/onebot11/config'; - -type RegisterHandler = (res: Response, payload: any) => Promise - -export abstract class HttpServerBase { - name: string = 'NapCatQQ'; - private readonly expressAPP: Express; - private _server: http.Server | null = null; - - public get server(): http.Server | null { - return this._server; - } - - private set server(value: http.Server | null) { - this._server = value; - } - - constructor() { - this.expressAPP = express(); - this.expressAPP.use(cors()); - this.expressAPP.use(express.urlencoded({ extended: true, limit: '5000mb' })); - this.expressAPP.use((req, res, next) => { - // 兼容处理没有带content-type的请求 - // log("req.headers['content-type']", req.headers['content-type']) - req.headers['content-type'] = 'application/json'; - const originalJson = express.json({ limit: '5000mb' }); - // 调用原始的express.json()处理器 - originalJson(req, res, (err) => { - if (err) { - logError('Error parsing JSON:', err); - return res.status(400).send('Invalid JSON'); - } - next(); - }); - }); - } - - authorize(req: Request, res: Response, next: () => void) { - const serverToken = ob11Config.token; - let clientToken = ''; - const authHeader = req.get('authorization'); - if (authHeader) { - clientToken = authHeader.split('Bearer ').pop() || ''; - //logDebug('receive http header token', clientToken); - } else if (req.query.access_token) { - if (Array.isArray(req.query.access_token)) { - clientToken = req.query.access_token[0].toString(); - } else { - clientToken = req.query.access_token.toString(); - } - //logDebug('receive http url token', clientToken); - } - - if (serverToken && clientToken != serverToken) { - return res.status(403).send(JSON.stringify({ message: 'token verify failed!' })); - } - next(); - } - - start(port: number, host: string) { - try { - this.expressAPP.get('/', (req: Request, res: Response) => { - res.send(`${this.name}已启动`); - }); - this.listen(port, host); - } catch (e: any) { - logError('HTTP服务启动失败', e.toString()); - // httpServerError = "HTTP服务启动失败, " + e.toString() - } - } - - stop() { - // httpServerError = "" - if (this.server) { - this.server.close(); - this.server = null; - } - } - - restart(port: number, host: string) { - this.stop(); - this.start(port, host); - } - - abstract handleFailed(res: Response, payload: any, err: Error): void - - registerRouter(method: 'post' | 'get' | string, url: string, handler: RegisterHandler) { - if (!url.startsWith('/')) { - url = '/' + url; - } - - // @ts-expect-error wait fix - if (!this.expressAPP[method]) { - const err = `${this.name} register router failed,${method} not exist`; - logError(err); - throw err; - } - // @ts-expect-error wait fix - this.expressAPP[method](url, this.authorize, async (req: Request, res: Response) => { - let payload = req.body; - if (method == 'get') { - payload = req.query; - } else if (req.query) { - payload = { ...req.query, ...req.body }; - } - logDebug('收到http请求', url, payload); - try { - res.send(await handler(res, payload)); - } catch (e: any) { - this.handleFailed(res, payload, e); - } - }); - } - - protected listen(port: number, host: string = '0.0.0.0') { - host = host || '0.0.0.0'; - try { - this.server = this.expressAPP.listen(port, host, () => { - const info = `${this.name} started ${host}:${port}`; - log(info); - }).on('error', (err) => { - logError('HTTP服务启动失败', err.toString()); - }); - } catch (e: any) { - logError('HTTP服务启动失败, 请检查监听的ip地址和端口', e.stack.toString()); - } - } -} diff --git a/src/common/server/websocket.ts b/src/common/server/websocket.ts deleted file mode 100644 index fe1c4895..00000000 --- a/src/common/server/websocket.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { WebSocket, WebSocketServer } from 'ws'; -import http from 'http'; -import urlParse from 'url'; -import { IncomingMessage } from 'node:http'; -import { log } from '@/common/utils/log'; - -class WebsocketClientBase { - private wsClient: WebSocket | undefined; - - constructor() { - } - - send(msg: string) { - if (this.wsClient && this.wsClient.readyState == WebSocket.OPEN) { - this.wsClient.send(msg); - } - } - - onMessage(msg: string) { - - } -} - -export class WebsocketServerBase { - private ws: WebSocketServer | null = null; - public token: string = ''; - - constructor() { - } - - start(port: number | http.Server, host: string = '') { - if (port instanceof http.Server) { - try { - const wss = new WebSocketServer({ - noServer: true, - maxPayload: 1024 * 1024 * 1024 - }).on('error', () => { - }); - this.ws = wss; - port.on('upgrade', function upgrade(request, socket, head) { - wss.handleUpgrade(request, socket, head, function done(ws) { - wss.emit('connection', ws, request); - }); - }); - log('ws服务启动成功, 绑定到HTTP服务'); - } catch (e: any) { - throw Error('ws服务启动失败, 可能是绑定的HTTP服务异常' + e.toString()); - } - } else { - try { - this.ws = new WebSocketServer({ - port, - host: '', - maxPayload: 1024 * 1024 * 1024 - }).on('error', () => { - }); - log(`ws服务启动成功, ${host}:${port}`); - } catch (e: any) { - throw Error('ws服务启动失败, 请检查监听的ip和端口' + e.toString()); - } - } - this.ws.on('connection', (wsClient, req) => { - const url: string = req.url!.split('?').shift() || '/'; - this.authorize(wsClient, req); - this.onConnect(wsClient, url, req); - wsClient.on('message', async (msg) => { - this.onMessage(wsClient, url, msg.toString()); - }); - }); - } - - stop() { - if (this.ws) { - this.ws.close((err) => { - if (err) log('ws server close failed!', err); - }); - this.ws = null; - } - } - - restart(port: number) { - this.stop(); - this.start(port); - } - - authorize(wsClient: WebSocket, req: IncomingMessage) { - const url = req.url!.split('?').shift(); - log('ws connect', url); - let clientToken: string = ''; - const authHeader = req.headers['authorization']; - if (authHeader) { - clientToken = authHeader.split('Bearer ').pop() || ''; - log('receive ws header token', clientToken); - } else { - const parsedUrl = urlParse.parse(req.url || '/', true); - const urlToken = parsedUrl.query.access_token; - if (urlToken) { - if (Array.isArray(urlToken)) { - clientToken = urlToken[0]; - } else { - clientToken = urlToken; - } - log('receive ws url token', clientToken); - } - } - if (this.token && clientToken != this.token) { - this.authorizeFailed(wsClient); - return wsClient.close(); - } - } - - authorizeFailed(wsClient: WebSocket) { - - } - - onConnect(wsClient: WebSocket, url: string, req: IncomingMessage) { - - } - - onMessage(wsClient: WebSocket, url: string, msg: string) { - - } - - sendHeart() { - - } -} diff --git a/src/common/utils/ConfigBase.ts b/src/common/utils/ConfigBase.ts deleted file mode 100644 index 62aaf7ea..00000000 --- a/src/common/utils/ConfigBase.ts +++ /dev/null @@ -1,89 +0,0 @@ -import path from 'node:path'; -import fs from 'node:fs'; -import { log, logDebug, logError } from '@/common/utils/log'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { selfInfo } from '@/core/data'; - - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -const configDir = path.resolve(__dirname, 'config'); -fs.mkdirSync(configDir, { recursive: true }); - - -export class ConfigBase { - public name: string = 'default_config'; - private pathName: string | null = null; // 本次读取的文件路径 - constructor() { - } - - protected getKeys(): string[] | null { - // 决定 key 在json配置文件中的顺序 - return null; - } - - getConfigDir() { - const configDir = path.resolve(__dirname, 'config'); - fs.mkdirSync(configDir, { recursive: true }); - return configDir; - } - getConfigPath(pathName: string | null): string { - const suffix = pathName ? `_${pathName}` : ''; - const filename = `${this.name}${suffix}.json`; - return path.join(this.getConfigDir(), filename); - } - read() { - // 尝试加载当前账号配置 - if (this.read_from_file(selfInfo.uin, false)) return this; - // 尝试加载默认配置 - return this.read_from_file('', true); - } - read_from_file(pathName: string, createIfNotExist: boolean) { - const configPath = this.getConfigPath(pathName); - if (!fs.existsSync(configPath)) { - if (!createIfNotExist) return null; - this.pathName = pathName; // 记录有效的设置文件 - try { - fs.writeFileSync(configPath, JSON.stringify(this, this.getKeys(), 2)); - log(`配置文件${configPath}已创建\n如果修改此文件后需要重启 NapCat 生效`); - } - catch (e: any) { - logError(`创建配置文件 ${configPath} 时发生错误:`, e.message); - } - return this; - } - - try { - const data = JSON.parse(fs.readFileSync(configPath, 'utf-8')); - logDebug(`配置文件${configPath}已加载`, data); - Object.assign(this, data); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - this.save(this); // 保存一次,让新版本的字段写入 - return this; - } catch (e: any) { - if (e instanceof SyntaxError) { - logError(`配置文件 ${configPath} 格式错误,请检查配置文件:`, e.message); - } else { - logError(`读取配置文件 ${configPath} 时发生错误:`, e.message); - } - return this; - } - } - - save(config: T, overwrite: boolean = false) { - Object.assign(this, config); - if (overwrite) { - // 用户要求强制写入,则变更当前文件为目标文件 - this.pathName = `${selfInfo.uin}`; - } - const configPath = this.getConfigPath(this.pathName); - try { - fs.writeFileSync(configPath, JSON.stringify(this, this.getKeys(), 2)); - } catch (e: any) { - logError(`保存配置文件 ${configPath} 时发生错误:`, e.message); - } - } -} diff --git a/src/common/utils/EventTask.ts b/src/common/utils/EventTask.ts deleted file mode 100644 index a9e91f34..00000000 --- a/src/common/utils/EventTask.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { NodeIQQNTWrapperSession } from '@/core/wrapper'; -import { randomUUID } from 'crypto'; - -interface Internal_MapKey { - timeout: number, - createtime: number, - func: (...arg: any[]) => any, - checker: ((...args: any[]) => boolean) | undefined, -} - -export class ListenerClassBase { - [key: string]: string; -} - -export interface ListenerIBase { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(listener: any): ListenerClassBase; -} - -export class NTEventWrapper { - - private ListenerMap: { [key: string]: ListenerIBase } | undefined;//ListenerName-Unique -> Listener构造函数 - private WrapperSession: NodeIQQNTWrapperSession | undefined;//WrapperSession - private ListenerManger: Map = new Map(); //ListenerName-Unique -> Listener实例 - private EventTask = new Map>>();//tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func} - constructor() { - - } - createProxyDispatch(ListenerMainName: string) { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const current = this; - return new Proxy({}, { - get(target: any, prop: any, receiver: any) { - // console.log('get', prop, typeof target[prop]); - if (typeof target[prop] === 'undefined') { - // 如果方法不存在,返回一个函数,这个函数调用existentMethod - return (...args: any[]) => { - current.DispatcherListener.apply(current, [ListenerMainName, prop, ...args]).then(); - }; - } - // 如果方法存在,正常返回 - return Reflect.get(target, prop, receiver); - } - }); - } - init({ ListenerMap, WrapperSession }: { ListenerMap: { [key: string]: typeof ListenerClassBase }, WrapperSession: NodeIQQNTWrapperSession }) { - this.ListenerMap = ListenerMap; - this.WrapperSession = WrapperSession; - } - CreatEventFunction any>(eventName: string): T | undefined { - const eventNameArr = eventName.split('/'); - type eventType = { - [key: string]: () => { [key: string]: (...params: Parameters) => Promise> } - } - if (eventNameArr.length > 1) { - const serviceName = 'get' + eventNameArr[0].replace('NodeIKernel', ''); - const eventName = eventNameArr[1]; - //getNodeIKernelGroupListener,GroupService - //console.log('2', eventName); - const services = (this.WrapperSession as unknown as eventType)[serviceName](); - let event = services[eventName]; - //重新绑定this - event = event.bind(services); - if (event) { - return event as T; - } - return undefined; - } - - } - CreatListenerFunction(listenerMainName: string, uniqueCode: string = ''): T { - const ListenerType = this.ListenerMap![listenerMainName]; - let Listener = this.ListenerManger.get(listenerMainName + uniqueCode); - if (!Listener && ListenerType) { - Listener = new ListenerType(this.createProxyDispatch(listenerMainName)); - const ServiceSubName = listenerMainName.match(/^NodeIKernel(.*?)Listener$/)![1]; - const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener'; - const addfunc = this.CreatEventFunction<(listener: T) => number>(Service); - addfunc!(Listener as T); - //console.log(addfunc!(Listener as T)); - this.ListenerManger.set(listenerMainName + uniqueCode, Listener); - } - return Listener as T; - } - //统一回调清理事件 - async DispatcherListener(ListenerMainName: string, ListenerSubName: string, ...args: any[]) { - //console.log("[EventDispatcher]",ListenerMainName, ListenerSubName, ...args); - this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.forEach((task, uuid) => { - //console.log(task.func, uuid, task.createtime, task.timeout); - if (task.createtime + task.timeout < Date.now()) { - this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.delete(uuid); - return; - } - if (task.checker && task.checker(...args)) { - task.func(...args); - } - }); - } - async CallNoListenerEvent Promise | any>(EventName = '', timeout: number = 3000, ...args: Parameters) { - return new Promise>>(async (resolve, reject) => { - const EventFunc = this.CreatEventFunction(EventName); - let complete = false; - const Timeouter = setTimeout(() => { - if (!complete) { - reject(new Error('NTEvent EventName:' + EventName + ' timeout')); - } - }, timeout); - const retData = await EventFunc!(...args); - complete = true; - resolve(retData); - }); - } - async RegisterListen void>(ListenerName = '', waitTimes = 1, timeout = 5000, checker: (...args: Parameters) => boolean) { - return new Promise>((resolve, reject) => { - const ListenerNameList = ListenerName.split('/'); - const ListenerMainName = ListenerNameList[0]; - const ListenerSubName = ListenerNameList[1]; - const id = randomUUID(); - let complete = 0; - let retData: Parameters | undefined = undefined; - const databack = () => { - if (complete == 0) { - reject(new Error(' ListenerName:' + ListenerName + ' timeout')); - } else { - resolve(retData!); - } - }; - const Timeouter = setTimeout(databack, timeout); - const eventCallbak = { - timeout: timeout, - createtime: Date.now(), - checker: checker, - func: (...args: Parameters) => { - complete++; - retData = args; - if (complete >= waitTimes) { - clearTimeout(Timeouter); - databack(); - } - } - }; - if (!this.EventTask.get(ListenerMainName)) { - this.EventTask.set(ListenerMainName, new Map()); - } - if (!(this.EventTask.get(ListenerMainName)?.get(ListenerSubName))) { - this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map()); - } - this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak); - this.CreatListenerFunction(ListenerMainName); - }); - } - async CallNormalEvent Promise, ListenerType extends (...args: any[]) => void> - (EventName = '', ListenerName = '', waitTimes = 1, timeout: number = 3000, checker: (...args: Parameters) => boolean, ...args: Parameters) { - return new Promise<[EventRet: Awaited>, ...Parameters]>(async (resolve, reject) => { - const id = randomUUID(); - let complete = 0; - let retData: Parameters | undefined = undefined; - let retEvent: any = {}; - const databack = () => { - if (complete == 0) { - reject(new Error('Timeout: NTEvent EventName:' + EventName + ' ListenerName:' + ListenerName + ' EventRet:\n' + JSON.stringify(retEvent, null, 4) + '\n')); - } else { - resolve([retEvent as Awaited>, ...retData!]); - } - }; - - - const ListenerNameList = ListenerName.split('/'); - const ListenerMainName = ListenerNameList[0]; - const ListenerSubName = ListenerNameList[1]; - - const Timeouter = setTimeout(databack, timeout); - - const eventCallbak = { - timeout: timeout, - createtime: Date.now(), - checker: checker, - func: (...args: any[]) => { - complete++; - //console.log('func', ...args); - retData = args as Parameters; - if (complete >= waitTimes) { - clearTimeout(Timeouter); - databack(); - } - } - }; - if (!this.EventTask.get(ListenerMainName)) { - this.EventTask.set(ListenerMainName, new Map()); - } - if (!(this.EventTask.get(ListenerMainName)?.get(ListenerSubName))) { - this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map()); - } - this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak); - this.CreatListenerFunction(ListenerMainName); - const EventFunc = this.CreatEventFunction(EventName); - retEvent = await EventFunc!(...(args as any[])); - }); - } -} -export const NTEventDispatch = new NTEventWrapper(); - -// 示例代码 快速创建事件 -// let NTEvent = new NTEventWrapper(); -// let TestEvent = NTEvent.CreatEventFunction<(force: boolean) => Promise>('NodeIKernelProfileLikeService/GetTest'); -// if (TestEvent) { -// TestEvent(true); -// } - -// 示例代码 快速创建监听Listener类 -// let NTEvent = new NTEventWrapper(); -// NTEvent.CreatListenerFunction('NodeIKernelMsgListener', 'core') - - -// 调用接口 -//let NTEvent = new NTEventWrapper(); -//let ret = await NTEvent.CallNormalEvent<(force: boolean) => Promise, (data1: string, data2: number) => void>('NodeIKernelProfileLikeService/GetTest', 'NodeIKernelMsgListener/onAddSendMsg', 1, 3000, true); - -// 注册监听 解除监听 -// NTEventDispatch.RigisterListener('NodeIKernelMsgListener/onAddSendMsg','core',cb); -// NTEventDispatch.UnRigisterListener('NodeIKernelMsgListener/onAddSendMsg','core'); - -// let GetTest = NTEventDispatch.CreatEvent('NodeIKernelProfileLikeService/GetTest','NodeIKernelMsgListener/onAddSendMsg',Mode); -// GetTest('test'); - -// always模式 -// NTEventDispatch.CreatEvent('NodeIKernelProfileLikeService/GetTest','NodeIKernelMsgListener/onAddSendMsg',Mode,(...args:any[])=>{ console.log(args) }); \ No newline at end of file diff --git a/src/common/utils/MessageUnique.ts b/src/common/utils/MessageUnique.ts deleted file mode 100644 index 54fc3571..00000000 --- a/src/common/utils/MessageUnique.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { Peer } from '@/core'; -import crypto, { randomInt, randomUUID } from 'crypto'; -import { logError } from './log'; - -export class LimitedHashTable { - private keyToValue: Map = new Map(); - private valueToKey: Map = new Map(); - private maxSize: number; - - constructor(maxSize: number) { - this.maxSize = maxSize; - } - resize(count: number) { - this.maxSize = count; - } - - set(key: K, value: V): void { - // const isExist = this.keyToValue.get(key); - // if (isExist && isExist === value) { - // return; - // } - this.keyToValue.set(key, value); - this.valueToKey.set(value, key); - while (this.keyToValue.size !== this.valueToKey.size) { - console.log('keyToValue.size !== valueToKey.size Error Atom'); - this.keyToValue.clear(); - this.valueToKey.clear(); - } - // console.log('---------------'); - // console.log(this.keyToValue); - // console.log(this.valueToKey); - // console.log('---------------'); - while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) { - //console.log(this.keyToValue.size > this.maxSize, this.valueToKey.size > this.maxSize); - const oldestKey = this.keyToValue.keys().next().value; - this.valueToKey.delete(this.keyToValue.get(oldestKey)!); - this.keyToValue.delete(oldestKey); - } - } - - getValue(key: K): V | undefined { - return this.keyToValue.get(key); - } - - getKey(value: V): K | undefined { - return this.valueToKey.get(value); - } - - deleteByValue(value: V): void { - const key = this.valueToKey.get(value); - if (key !== undefined) { - this.keyToValue.delete(key); - this.valueToKey.delete(value); - } - } - - deleteByKey(key: K): void { - const value = this.keyToValue.get(key); - if (value !== undefined) { - this.keyToValue.delete(key); - this.valueToKey.delete(value); - } - } - - getKeyList(): K[] { - return Array.from(this.keyToValue.keys()); - } - //获取最近刚写入的几个值 - getHeads(size: number): { key: K; value: V }[] | undefined { - const keyList = this.getKeyList(); - if (keyList.length === 0) { - return undefined; - } - const result: { key: K; value: V }[] = []; - const listSize = Math.min(size, keyList.length); - for (let i = 0; i < listSize; i++) { - const key = keyList[listSize - i]; - result.push({ key, value: this.keyToValue.get(key)! }); - } - return result; - } -} - -class MessageUniqueWrapper { - private msgDataMap: LimitedHashTable; - private msgIdMap: LimitedHashTable; - constructor(maxMap: number = 1000) { - this.msgIdMap = new LimitedHashTable(maxMap); - this.msgDataMap = new LimitedHashTable(maxMap); - } - getRecentMsgIds(Peer: Peer, size: number): string[] { - const heads = this.msgIdMap.getHeads(size); - if (!heads) { - return []; - } - const data = heads.map((t) => MessageUnique.getMsgIdAndPeerByShortId(t.value)); - const ret = data.filter((t) => t?.Peer.chatType === Peer.chatType && t?.Peer.peerUid === Peer.peerUid); - return ret.map((t) => t?.MsgId).filter((t) => t !== undefined); - } - createMsg(peer: Peer, msgId: string): number | undefined { - const key = `${msgId}|${peer.chatType}|${peer.peerUid}`; - const hash = crypto.createHash('md5').update(key).digest(); - //设置第一个bit为0 保证shortId为正数 - hash[0] &= 0x7f; - const shortId = hash.readInt32BE(0); - //减少性能损耗 - // const isExist = this.msgIdMap.getKey(shortId); - // if (isExist && isExist === msgId) { - // return shortId; - // } - this.msgIdMap.set(msgId, shortId); - this.msgDataMap.set(key, shortId); - return shortId; - } - - getMsgIdAndPeerByShortId(shortId: number): { MsgId: string; Peer: Peer } | undefined { - const data = this.msgDataMap.getKey(shortId); - if (data) { - const [msgId, chatTypeStr, peerUid] = data.split('|'); - const peer: Peer = { - chatType: parseInt(chatTypeStr), - peerUid, - guildId: '', - }; - return { MsgId: msgId, Peer: peer }; - } - return undefined; - } - - getShortIdByMsgId(msgId: string): number | undefined { - return this.msgIdMap.getValue(msgId); - } - getPeerByMsgId(msgId: string) { - const shortId = this.msgIdMap.getValue(msgId); - if (!shortId) return undefined; - return this.getMsgIdAndPeerByShortId(shortId); - } - resize(maxSize: number): void { - this.msgIdMap.resize(maxSize); - this.msgDataMap.resize(maxSize); - } -} - -export const MessageUnique: MessageUniqueWrapper = new MessageUniqueWrapper(); \ No newline at end of file diff --git a/src/common/utils/Packet.ts b/src/common/utils/Packet.ts deleted file mode 100644 index 6fcbe87c..00000000 --- a/src/common/utils/Packet.ts +++ /dev/null @@ -1,17 +0,0 @@ -// 方案一 MiniApp发包方案 -// 前置条件: 处于GUI环境 存在MiniApp - -import { NTQQSystemApi } from '@/core'; - -// 前排提示: 开发验证仅Win平台开展 -export class MiniAppUtil { - static async RunMiniAppWithGUI() { - //process.env.ELECTRON_RUN_AS_NODE = undefined;//没用还是得自己用cpp之类的语言写个程序转发参数 - return NTQQSystemApi.BootMiniApp(process.execPath, 'miniapp://open/1007?url=https%3A%2F%2Fm.q.qq.com%2Fa%2Fs%2Fedd0a83d3b8afe233dfa07adaaf8033f%3Fscene%3D1007%26min_refer%3D10001'); - } -} -// 方案二 MiniApp发包方案 替代MiniApp方案 -// 前置条件: 无 -export class MojoMiniAppUtil{ - -} \ No newline at end of file diff --git a/src/common/utils/QQBasicInfo.ts b/src/common/utils/QQBasicInfo.ts deleted file mode 100644 index e69c3827..00000000 --- a/src/common/utils/QQBasicInfo.ts +++ /dev/null @@ -1,57 +0,0 @@ -import path from 'node:path'; -import fs from 'node:fs'; -import { systemPlatform } from '@/common/utils/system'; -import { getDefaultQQVersionConfigInfo, getQQVersionConfigPath } from './helper'; -import AppidTable from '@/core/external/appid.json'; -import { log } from './log'; - -//基础目录获取 -export const QQMainPath = process.execPath; -export const QQPackageInfoPath: string = path.join(path.dirname(QQMainPath), 'resources', 'app', 'package.json'); -export const QQVersionConfigPath: string | undefined = getQQVersionConfigPath(QQMainPath); - -//基础信息获取 无快更则启用默认模板填充 -export const isQuickUpdate: boolean = !!QQVersionConfigPath; -export const QQVersionConfig: QQVersionConfigType = isQuickUpdate ? JSON.parse(fs.readFileSync(QQVersionConfigPath!).toString()) : getDefaultQQVersionConfigInfo(); -export const QQPackageInfo: QQPackageInfoType = JSON.parse(fs.readFileSync(QQPackageInfoPath).toString()); -export const { appid: QQVersionAppid, qua: QQVersionQua } = getAppidV2(); - -//基础函数 -export function getQQBuildStr() { - return isQuickUpdate ? QQVersionConfig.buildId : QQPackageInfo.buildVersion; -} -export function getFullQQVesion() { - return isQuickUpdate ? QQVersionConfig.curVersion : QQPackageInfo.version; -} -export function requireMinNTQQBuild(buildStr: string) { - return parseInt(getQQBuildStr()) >= parseInt(buildStr); -} -//此方法不要直接使用 -export function getQUAInternal() { - return systemPlatform === 'linux' ? `V1_LNX_NQ_${getFullQQVesion()}_${getQQBuildStr()}_GW_B` : `V1_WIN_NQ_${getFullQQVesion()}_${getQQBuildStr()}_GW_B`; -} -export function getAppidV2(): { appid: string, qua: string } { - const appidTbale = AppidTable as unknown as QQAppidTableType; - try { - const data = appidTbale[getFullQQVesion()]; - if (data) { - return data; - } - } - catch (e) { - log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`); - } - // 以下是兜底措施 - log(`[QQ版本兼容性检测] ${getFullQQVesion()} 版本兼容性不佳,可能会导致一些功能无法正常使用`); - return { appid: systemPlatform === 'linux' ? '537237950' : '537237765', qua: getQUAInternal() }; -} -// platform_type: 3, -// app_type: 4, -// app_version: '9.9.12-25765', -// qua: 'V1_WIN_NQ_9.9.12_25765_GW_B', -// appid: '537234702', -// platVer: '10.0.26100', -// clientVer: '9.9.9-25765', -// Linux -// app_version: '3.2.9-25765', -// qua: 'V1_LNX_NQ_3.2.10_25765_GW_B', diff --git a/src/common/utils/audio.ts b/src/common/utils/audio.ts deleted file mode 100644 index 2ac39700..00000000 --- a/src/common/utils/audio.ts +++ /dev/null @@ -1,136 +0,0 @@ -import fs from 'fs'; -import { encode, getDuration, getWavFileInfo, isWav, isSilk } from 'silk-wasm'; -import fsPromise from 'fs/promises'; -import { log, logError } from './log'; -import path from 'node:path'; -import { randomUUID } from 'crypto'; -import { spawn } from 'node:child_process'; -import { getTempDir } from '@/common/utils/file'; - -let TEMP_DIR = './'; -setTimeout(() => { - TEMP_DIR = getTempDir(); -}, 100); -export async function encodeSilk(filePath: string) { - function getFileHeader(filePath: string) { - // 定义要读取的字节数 - const bytesToRead = 7; - try { - const buffer = fs.readFileSync(filePath, { - encoding: null, - flag: 'r', - }); - - const fileHeader = buffer.toString('hex', 0, bytesToRead); - return fileHeader; - } catch (err) { - logError('读取文件错误:', err); - return; - } - } - - async function isWavFile(filePath: string) { - return isWav(fs.readFileSync(filePath)); - } - - async function guessDuration(pttPath: string) { - const pttFileInfo = await fsPromise.stat(pttPath); - let duration = pttFileInfo.size / 1024 / 3; // 3kb/s - duration = Math.floor(duration); - duration = Math.max(1, duration); - log('通过文件大小估算语音的时长:', duration); - return duration; - } - - // function verifyDuration(oriDuration: number, guessDuration: number) { - // // 单位都是秒 - // if (oriDuration - guessDuration > 10) { - // return guessDuration - // } - // oriDuration = Math.max(1, oriDuration) - // return oriDuration - // } - // async function getAudioSampleRate(filePath: string) { - // try { - // const mm = await import('music-metadata'); - // const metadata = await mm.parseFile(filePath); - // log(`${filePath}采样率`, metadata.format.sampleRate); - // return metadata.format.sampleRate; - // } catch (error) { - // log(`${filePath}采样率获取失败`, error.stack); - // // console.error(error); - // } - // } - - try { - const file = await fsPromise.readFile(filePath); - const pttPath = path.join(TEMP_DIR, randomUUID()); - if (!isSilk(file)) { - log(`语音文件${filePath}需要转换成silk`); - const _isWav = isWav(file); - const pcmPath = pttPath + '.pcm'; - let sampleRate = 0; - const convert = () => { - return new Promise((resolve, reject) => { - // todo: 通过配置文件获取ffmpeg路径 - const ffmpegPath = process.env.FFMPEG_PATH || 'ffmpeg'; - const cp = spawn(ffmpegPath, ['-y', '-i', filePath, '-ar', '24000', '-ac', '1', '-f', 's16le', pcmPath]); - cp.on('error', err => { - log('FFmpeg处理转换出错: ', err.message); - return reject(err); - }); - cp.on('exit', (code, signal) => { - const EXIT_CODES = [0, 255]; - if (code == null || EXIT_CODES.includes(code)) { - sampleRate = 24000; - const data = fs.readFileSync(pcmPath); - fs.unlink(pcmPath, (err) => { - }); - return resolve(data); - } - log(`FFmpeg exit: code=${code ?? 'unknown'} sig=${signal ?? 'unknown'}`); - reject(Error('FFmpeg处理转换失败')); - }); - }); - }; - let input: Buffer; - if (!_isWav) { - input = await convert(); - } else { - input = file; - const allowSampleRate = [8000, 12000, 16000, 24000, 32000, 44100, 48000]; - const { fmt } = getWavFileInfo(input); - // log(`wav文件信息`, fmt) - if (!allowSampleRate.includes(fmt.sampleRate)) { - input = await convert(); - } - } - const silk = await encode(input, sampleRate); - fs.writeFileSync(pttPath, silk.data); - log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration); - return { - converted: true, - path: pttPath, - duration: silk.duration / 1000 - }; - } else { - const silk = file; - let duration = 0; - try { - duration = getDuration(silk) / 1000; - } catch (e: any) { - log('获取语音文件时长失败, 使用文件大小推测时长', filePath, e.stack); - duration = await guessDuration(filePath); - } - - return { - converted: false, - path: filePath, - duration, - }; - } - } catch (error: any) { - logError('convert silk failed', error.stack); - return {}; - } -} diff --git a/src/common/utils/cpmodule.ts b/src/common/utils/cpmodule.ts deleted file mode 100644 index ec3c7362..00000000 --- a/src/common/utils/cpmodule.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as os from 'os'; -import path from 'node:path'; -import fs from 'fs'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); -export function getModuleWithArchName(moduleName: string) { - const systemPlatform = os.platform(); - const cpuArch = os.arch(); - return `${moduleName}-${systemPlatform}-${cpuArch}.node`; -} - -export function cpModule(moduleName: string) { - const currentDir = path.resolve(__dirname); - const fileName = `./${getModuleWithArchName(moduleName)}`; - try { - fs.copyFileSync(path.join(currentDir, fileName), path.join(currentDir, `${moduleName}.node`)); - } catch (e) { - console.error(e); - } -} diff --git a/src/common/utils/file.ts b/src/common/utils/file.ts deleted file mode 100644 index fd6a4f37..00000000 --- a/src/common/utils/file.ts +++ /dev/null @@ -1,316 +0,0 @@ -import fs from 'fs'; -import fsPromise, { stat } from 'fs/promises'; -import crypto from 'crypto'; -import util from 'util'; -import path from 'node:path'; -import { log, logError } from './log'; -import * as fileType from 'file-type'; -import { randomUUID } from 'crypto'; -import { napCatCore } from '@/core'; - -export const getNapCatDir = () => { - const p = path.join(napCatCore.dataPath, 'NapCat'); - fs.mkdirSync(p, { recursive: true }); - return p; -}; -export const getTempDir = () => { - const p = path.join(getNapCatDir(), 'temp'); - // 创建临时目录 - if (!fs.existsSync(p)) { - fs.mkdirSync(p, { recursive: true }); - } - return p; -}; - - -export function isGIF(path: string) { - const buffer = Buffer.alloc(4); - const fd = fs.openSync(path, 'r'); - fs.readSync(fd, buffer, 0, 4, 0); - fs.closeSync(fd); - return buffer.toString() === 'GIF8'; -} - -// 定义一个异步函数来检查文件是否存在 -export function checkFileReceived(path: string, timeout: number = 3000): Promise { - return new Promise((resolve, reject) => { - const startTime = Date.now(); - - function check() { - if (fs.existsSync(path)) { - resolve(); - } else if (Date.now() - startTime > timeout) { - reject(new Error(`文件不存在: ${path}`)); - } else { - setTimeout(check, 100); - } - } - - check(); - }); -} -// 定义一个异步函数来检查文件是否存在 -export async function checkFileReceived2(path: string, timeout: number = 3000): Promise { - // 使用 Promise.race 来同时进行文件状态检查和超时计时 - // Promise.race 会返回第一个解决(resolve)或拒绝(reject)的 Promise - await Promise.race([ - checkFile(path), - timeoutPromise(timeout, `文件不存在: ${path}`), - ]); -} - -// 转换超时时间至 Promise -function timeoutPromise(timeout: number, errorMsg: string): Promise { - return new Promise((_, reject) => { - setTimeout(() => { - reject(new Error(errorMsg)); - }, timeout); - }); -} - -// 异步检查文件是否存在 -async function checkFile(path: string): Promise { - try { - await stat(path); - } catch (error: any) { - if (error.code === 'ENOENT') { - // 如果文件不存在,则抛出一个错误 - throw new Error(`文件不存在: ${path}`); - } else { - // 对于 stat 调用的其他错误,重新抛出 - throw error; - } - } - // 如果文件存在,则无需做任何事情,Promise 解决(resolve)自身 -} -export async function file2base64(path: string) { - const readFile = util.promisify(fs.readFile); - const result = { - err: '', - data: '' - }; - try { - // 读取文件内容 - // if (!fs.existsSync(path)){ - // path = path.replace("\\Ori\\", "\\Thumb\\"); - // } - try { - await checkFileReceived(path, 5000); - } catch (e: any) { - result.err = e.toString(); - return result; - } - const data = await readFile(path); - // 转换为Base64编码 - result.data = data.toString('base64'); - } catch (err: any) { - result.err = err.toString(); - } - return result; -} - - -export function calculateFileMD5(filePath: string): Promise { - return new Promise((resolve, reject) => { - // 创建一个流式读取器 - const stream = fs.createReadStream(filePath); - const hash = crypto.createHash('md5'); - - stream.on('data', (data: Buffer) => { - // 当读取到数据时,更新哈希对象的状态 - hash.update(data); - }); - - stream.on('end', () => { - // 文件读取完成,计算哈希 - const md5 = hash.digest('hex'); - resolve(md5); - }); - - stream.on('error', (err: Error) => { - // 处理可能的读取错误 - reject(err); - }); - }); -} - -export interface HttpDownloadOptions { - url: string; - headers?: Record | string; -} - -export async function httpDownload(options: string | HttpDownloadOptions): Promise { - const chunks: Buffer[] = []; - let url: string; - let headers: Record = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36' - }; - if (typeof options === 'string') { - url = options; - const host = new URL(url).hostname; - headers['Host'] = host; - } else { - url = options.url; - if (options.headers) { - if (typeof options.headers === 'string') { - headers = JSON.parse(options.headers); - } else { - headers = options.headers; - } - } - } - const fetchRes = await fetch(url, { headers }).catch((err) => { - if (err.cause) { - throw err.cause; - } - throw err; - }); - if (!fetchRes.ok) throw new Error(`下载文件失败: ${fetchRes.statusText}`); - - const blob = await fetchRes.blob(); - const buffer = await blob.arrayBuffer(); - return Buffer.from(buffer); -} - -type Uri2LocalRes = { - success: boolean, - errMsg: string, - fileName: string, - ext: string, - path: string, - isLocal: boolean -} - -export async function uri2local(UriOrPath: string, fileName: string | null = null): Promise { - const res = { - success: false, - errMsg: '', - fileName: '', - ext: '', - path: '', - isLocal: false - }; - if (!fileName) fileName = randomUUID(); - let filePath = path.join(getTempDir(), fileName);//临时目录 - let url = null; - //区分path和uri - try { - if (fs.existsSync(UriOrPath)) url = new URL('file://' + UriOrPath); - } catch (error: any) { } - try { - url = new URL(UriOrPath); - } catch (error: any) { } - - //验证url - if (!url) { - res.errMsg = `UriOrPath ${UriOrPath} 解析失败,可能${UriOrPath}不存在`; - return res; - } - - if (url.protocol == 'base64:') { - // base64转成文件 - const base64Data = UriOrPath.split('base64://')[1]; - try { - const buffer = Buffer.from(base64Data, 'base64'); - fs.writeFileSync(filePath, buffer); - } catch (e: any) { - res.errMsg = 'base64文件下载失败,' + e.toString(); - return res; - } - } else if (url.protocol == 'http:' || url.protocol == 'https:') { - // 下载文件 - let buffer: Buffer | null = null; - try { - buffer = await httpDownload(UriOrPath); - } catch (e: any) { - res.errMsg = `${url}下载失败,` + e.toString(); - return res; - } - try { - const pathInfo = path.parse(decodeURIComponent(url.pathname)); - if (pathInfo.name) { - fileName = pathInfo.name; - if (pathInfo.ext) { - fileName += pathInfo.ext; - // res.ext = pathInfo.ext - } - } - fileName = fileName.replace(/[/\\:*?"<>|]/g, '_'); - res.fileName = fileName; - filePath = path.join(getTempDir(), randomUUID() + fileName); - fs.writeFileSync(filePath, buffer); - } catch (e: any) { - res.errMsg = `${url}下载失败,` + e.toString(); - return res; - } - } else { - let pathname: string; - if (url.protocol === 'file:') { - // await fs.copyFile(url.pathname, filePath); - pathname = decodeURIComponent(url.pathname); - if (process.platform === 'win32') { - filePath = pathname.slice(1); - } else { - filePath = pathname; - } - } - else { - // 26702执行forword file文件操作 不应该在这里乱来 - // const cache = await dbUtil.getFileCacheByName(uri); - // if (cache) { - // filePath = cache.path; - // } else { - // filePath = uri; - // } - } - res.isLocal = true; - } - // else{ - // res.errMsg = `不支持的file协议,` + url.protocol - // return res - // } - // if (isGIF(filePath) && !res.isLocal) { - // await fs.rename(filePath, filePath + ".gif"); - // filePath += ".gif"; - // } - if (!res.isLocal && !res.ext) { - try { - const ext: string | undefined = (await fileType.fileTypeFromFile(filePath))?.ext; - if (ext) { - log('获取文件类型', ext, filePath); - fs.renameSync(filePath, filePath + `.${ext}`); - filePath += `.${ext}`; - res.fileName += `.${ext}`; - res.ext = ext; - } - } catch (e) { - // log("获取文件类型失败", filePath,e.stack) - } - } - res.success = true; - res.path = filePath; - return res; -} - -export async function copyFolder(sourcePath: string, destPath: string) { - try { - const entries = await fsPromise.readdir(sourcePath, { withFileTypes: true }); - await fsPromise.mkdir(destPath, { recursive: true }); - for (const entry of entries) { - const srcPath = path.join(sourcePath, entry.name); - const dstPath = path.join(destPath, entry.name); - if (entry.isDirectory()) { - await copyFolder(srcPath, dstPath); - } else { - try { - await fsPromise.copyFile(srcPath, dstPath); - } catch (error) { - logError(`无法复制文件 '${srcPath}' 到 '${dstPath}': ${error}`); - // 这里可以决定是否要继续复制其他文件 - } - } - } - } catch (error) { - logError('复制文件夹时出错:', error); - } -} diff --git a/src/common/utils/helper.ts b/src/common/utils/helper.ts deleted file mode 100644 index f311d7a2..00000000 --- a/src/common/utils/helper.ts +++ /dev/null @@ -1,405 +0,0 @@ -import crypto from 'node:crypto'; -import path from 'node:path'; -import fs from 'fs'; -import { log, logDebug } from './log'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import * as fsPromise from 'node:fs/promises'; -import os from 'node:os'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -//下面这个类是用于将uid+msgid合并的类 -export class UUIDConverter { - static encode(highStr: string, lowStr: string): string { - const high = BigInt(highStr); - const low = BigInt(lowStr); - const highHex = high.toString(16).padStart(16, '0'); - const lowHex = low.toString(16).padStart(16, '0'); - const combinedHex = highHex + lowHex; - const uuid = `${combinedHex.substring(0, 8)}-${combinedHex.substring(8, 12)}-${combinedHex.substring(12, 16)}-${combinedHex.substring(16, 20)}-${combinedHex.substring(20)}`; - return uuid; - } - static decode(uuid: string): { high: string, low: string } { - const hex = uuid.replace(/-/g, ''); - const high = BigInt('0x' + hex.substring(0, 16)); - const low = BigInt('0x' + hex.substring(16)); - return { high: high.toString(), low: low.toString() }; - } -} - - -export function sleep(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -export function PromiseTimer(promise: Promise, ms: number): Promise { - const timeoutPromise = new Promise((_, reject) => - setTimeout(() => reject(new Error('PromiseTimer: Operation timed out')), ms) - ); - return Promise.race([promise, timeoutPromise]); -} -export async function runAllWithTimeout(tasks: Promise[], timeout: number): Promise { - const wrappedTasks = tasks.map(task => - PromiseTimer(task, timeout).then( - result => ({ status: 'fulfilled', value: result }), - error => ({ status: 'rejected', reason: error }) - ) - ); - const results = await Promise.all(wrappedTasks); - return results - .filter(result => result.status === 'fulfilled') - .map(result => (result as { status: 'fulfilled'; value: T }).value); -} - -export function getMd5(s: string) { - - const h = crypto.createHash('md5'); - h.update(s); - return h.digest('hex'); -} - -export function isNull(value: any) { - return value === undefined || value === null; -} - -export function isNumeric(str: string) { - return /^\d+$/.test(str); -} - -export function truncateString(obj: any, maxLength = 500) { - if (obj !== null && typeof obj === 'object') { - Object.keys(obj).forEach(key => { - if (typeof obj[key] === 'string') { - // 如果是字符串且超过指定长度,则截断 - if (obj[key].length > maxLength) { - obj[key] = obj[key].substring(0, maxLength) + '...'; - } - } else if (typeof obj[key] === 'object') { - // 如果是对象或数组,则递归调用 - truncateString(obj[key], maxLength); - } - }); - } - return obj; -} -export function simpleDecorator(target: any, context: any) { -} - -// export function CacheClassFunc(ttl: number = 3600 * 1000, customKey: string = '') { -// const cache = new Map(); -// return function CacheClassFuncDecorator(originalMethod: Function, context: ClassMethodDecoratorContext) { -// async function CacheClassFuncDecoratorInternal(this: any, ...args: any[]) { -// const key = `${customKey}${String(context.name)}.(${args.map(arg => JSON.stringify(arg)).join(', ')})`; -// const cachedValue = cache.get(key); -// if (cachedValue && cachedValue.expiry > Date.now()) { -// return cachedValue.value; -// } -// const result = originalMethod.call(this, ...args); -// cache.set(key, { expiry: Date.now() + ttl, value: result }); -// return result; -// } -// return CacheClassFuncDecoratorInternal; -// } -// } -export function CacheClassFuncAsync(ttl: number = 3600 * 1000, customKey: string = '') { - //console.log('CacheClassFuncAsync', ttl, customKey); - function logExecutionTime(target: any, methodName: string, descriptor: PropertyDescriptor) { - //console.log('logExecutionTime', target, methodName, descriptor); - const cache = new Map(); - const originalMethod = descriptor.value; - descriptor.value = async function (...args: any[]) { - const key = `${customKey}${String(methodName)}.(${args.map(arg => JSON.stringify(arg)).join(', ')})`; - cache.forEach((value, key) => { - if (value.expiry < Date.now()) { - cache.delete(key); - } - }); - const cachedValue = cache.get(key); - if (cachedValue && cachedValue.expiry > Date.now()) { - return cachedValue.value; - } - // const start = Date.now(); - const result = await originalMethod.apply(this, args); - // const end = Date.now(); - // console.log(`Method ${methodName} executed in ${end - start} ms.`); - cache.set(key, { expiry: Date.now() + ttl, value: result }); - return result; - }; - } - return logExecutionTime; -} -export function CacheClassFuncAsyncExtend(ttl: number = 3600 * 1000, customKey: string = '', checker: any = (...data: any[]) => { return true; }) { - //console.log('CacheClassFuncAsync', ttl, customKey); - function logExecutionTime(target: any, methodName: string, descriptor: PropertyDescriptor) { - //console.log('logExecutionTime', target, methodName, descriptor); - const cache = new Map(); - const originalMethod = descriptor.value; - descriptor.value = async function (...args: any[]) { - const key = `${customKey}${String(methodName)}.(${args.map(arg => JSON.stringify(arg)).join(', ')})`; - cache.forEach((value, key) => { - if (value.expiry < Date.now()) { - cache.delete(key); - } - }); - const cachedValue = cache.get(key); - if (cachedValue && cachedValue.expiry > Date.now()) { - return cachedValue.value; - } - // const start = Date.now(); - const result = await originalMethod.apply(this, args); - if (!checker(...args, result)) { - return result;//丢弃缓存 - } - // const end = Date.now(); - // console.log(`Method ${methodName} executed in ${end - start} ms.`); - cache.set(key, { expiry: Date.now() + ttl, value: result }); - return result; - }; - } - return logExecutionTime; -} -// export function CacheClassFuncAsync(ttl: number = 3600 * 1000, customKey: string = ''): any { -// const cache = new Map(); - -// // 注意:在JavaScript装饰器中,我们通常不直接处理ClassMethodDecoratorContext这样的类型, -// // 因为装饰器的参数通常是目标类(对于类装饰器)、属性名(对于属性装饰器)等。 -// // 对于方法装饰器,我们关注的是方法本身及其描述符。 -// // 但这里我们维持原逻辑,假设有一个自定义的处理上下文的方式。 - -// return function (originalMethod: Function): any { -// console.log(originalMethod); -// // 由于JavaScript装饰器原生不支持异步直接定义,我们保持async定义以便处理异步方法。 -// async function decoratorWrapper(this: any, ...args: any[]): Promise { -// console.log(...args); -// const key = `${customKey}${originalMethod.name}.(${args.map(arg => JSON.stringify(arg)).join(', ')})`; -// const cachedValue = cache.get(key); -// // 遍历cache 清除expiry内容 -// cache.forEach((value, key) => { -// if (value.expiry < Date.now()) { -// cache.delete(key); -// } -// }); -// if (cachedValue && cachedValue.expiry > Date.now()) { -// return cachedValue.value; -// } - -// // 直接await异步方法的结果 -// const result = await originalMethod.apply(this, args); -// cache.set(key, { expiry: Date.now() + ttl, value: result }); -// return result; -// } - -// // 返回装饰后的方法,保持与原方法相同的名称和描述符(如果需要更精细的控制,可以考虑使用Object.getOwnPropertyDescriptor等) -// return decoratorWrapper; -// }; -// } - -/** - * 函数缓存装饰器,根据方法名、参数、自定义key生成缓存键,在一定时间内返回缓存结果 - * @param ttl 超时时间,单位毫秒 - * @param customKey 自定义缓存键前缀,可为空,防止方法名参数名一致时导致缓存键冲突 - * @returns 处理后缓存或调用原方法的结果 - */ -export function cacheFunc(ttl: number, customKey: string = '') { - const cache = new Map(); - - return function (target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor { - const originalMethod = descriptor.value; - const className = target.constructor.name; // 获取类名 - const methodName = propertyKey; // 获取方法名 - descriptor.value = async function (...args: any[]) { - const cacheKey = `${customKey}${className}.${methodName}:${JSON.stringify(args)}`; - const cached = cache.get(cacheKey); - if (cached && cached.expiry > Date.now()) { - return cached.value; - } else { - const result = await originalMethod.apply(this, args); - cache.set(cacheKey, { value: result, expiry: Date.now() + ttl }); - return result; - } - }; - - return descriptor; - }; -} -export function isValidOldConfig(config: any) { - if (typeof config !== 'object') { - return false; - } - const requiredKeys = [ - 'httpHost', 'httpPort', 'httpPostUrls', 'httpSecret', - 'wsHost', 'wsPort', 'wsReverseUrls', 'enableHttp', - 'enableHttpHeart', 'enableHttpPost', 'enableWs', 'enableWsReverse', - 'messagePostFormat', 'reportSelfMessage', 'enableLocalFile2Url', - 'debug', 'heartInterval', 'token', 'musicSignUrl' - ]; - for (const key of requiredKeys) { - if (!(key in config)) { - return false; - } - } - if (!Array.isArray(config.httpPostUrls) || !Array.isArray(config.wsReverseUrls)) { - return false; - } - if (config.httpPostUrls.some((url: any) => typeof url !== 'string')) { - return false; - } - if (config.wsReverseUrls.some((url: any) => typeof url !== 'string')) { - return false; - } - if (typeof config.httpPort !== 'number' || typeof config.wsPort !== 'number' || typeof config.heartInterval !== 'number') { - return false; - } - if ( - typeof config.enableHttp !== 'boolean' || - typeof config.enableHttpHeart !== 'boolean' || - typeof config.enableHttpPost !== 'boolean' || - typeof config.enableWs !== 'boolean' || - typeof config.enableWsReverse !== 'boolean' || - typeof config.enableLocalFile2Url !== 'boolean' || - typeof config.reportSelfMessage !== 'boolean' - ) { - return false; - } - if (config.messagePostFormat !== 'array' && config.messagePostFormat !== 'string') { - return false; - } - return true; -} -export function migrateConfig(oldConfig: any) { - const newConfig = { - http: { - enable: oldConfig.enableHttp, - host: oldConfig.httpHost, - port: oldConfig.httpPort, - secret: oldConfig.httpSecret, - enableHeart: oldConfig.enableHttpHeart, - enablePost: oldConfig.enableHttpPost, - postUrls: oldConfig.httpPostUrls, - }, - ws: { - enable: oldConfig.enableWs, - host: oldConfig.wsHost, - port: oldConfig.wsPort, - }, - reverseWs: { - enable: oldConfig.enableWsReverse, - urls: oldConfig.wsReverseUrls, - }, - GroupLocalTime: { - Record: false, - RecordList: [] - }, - debug: oldConfig.debug, - heartInterval: oldConfig.heartInterval, - messagePostFormat: oldConfig.messagePostFormat, - enableLocalFile2Url: oldConfig.enableLocalFile2Url, - musicSignUrl: oldConfig.musicSignUrl, - reportSelfMessage: oldConfig.reportSelfMessage, - token: oldConfig.token, - - }; - return newConfig; -} -// 升级旧的配置到新的 -export async function UpdateConfig() { - const configFiles = await fsPromise.readdir(path.join(__dirname, 'config')); - for (const file of configFiles) { - if (file.match(/^onebot11_\d+.json$/)) { - const CurrentConfig = JSON.parse(await fsPromise.readFile(path.join(__dirname, 'config', file), 'utf8')); - if (isValidOldConfig(CurrentConfig)) { - log('正在迁移旧配置到新配置 File:', file); - const NewConfig = migrateConfig(CurrentConfig); - await fsPromise.writeFile(path.join(__dirname, 'config', file), JSON.stringify(NewConfig, null, 2)); - } - } - } -} -export function isEqual(obj1: any, obj2: any) { - if (obj1 === obj2) return true; - if (obj1 == null || obj2 == null) return false; - if (typeof obj1 !== 'object' || typeof obj2 !== 'object') return obj1 === obj2; - - const keys1 = Object.keys(obj1); - const keys2 = Object.keys(obj2); - - if (keys1.length !== keys2.length) return false; - - for (const key of keys1) { - if (!isEqual(obj1[key], obj2[key])) return false; - } - return true; -} -export function getDefaultQQVersionConfigInfo(): QQVersionConfigType { - if (os.platform() === 'linux') { - return { - baseVersion: '3.2.12-26702', - curVersion: '3.2.12-26702', - prevVersion: '', - onErrorVersions: [], - buildId: '26702' - }; - } - return { - baseVersion: '9.9.15-26702', - curVersion: '9.9.15-26702', - prevVersion: '', - onErrorVersions: [], - buildId: '26702' - }; -} -export async function promisePipeline(promises: Promise[], callback: (result: any) => boolean): Promise { - let callbackCalled = false; - for (const promise of promises) { - if (callbackCalled) break; - try { - const result = await promise; - if (!callbackCalled) { - callbackCalled = callback(result); - } - } catch (error) { - console.error('Error in promise pipeline:', error); - } - } -} - -export function getQQVersionConfigPath(exePath: string = ''): string | undefined { - let configVersionInfoPath; - if (os.platform() !== 'linux') { - configVersionInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'versions', 'config.json'); - } else { - const userPath = os.homedir(); - const appDataPath = path.resolve(userPath, './.config/QQ'); - configVersionInfoPath = path.resolve(appDataPath, './versions/config.json'); - } - if (typeof configVersionInfoPath !== 'string') { - return undefined; - } - if (!fs.existsSync(configVersionInfoPath)) { - return undefined; - } - return configVersionInfoPath; -} -export async function deleteOldFiles(directoryPath: string, daysThreshold: number) { - try { - const files = await fsPromise.readdir(directoryPath); - - for (const file of files) { - const filePath = path.join(directoryPath, file); - const stats = await fsPromise.stat(filePath); - const lastModifiedTime = stats.mtimeMs; - const currentTime = Date.now(); - const timeDifference = currentTime - lastModifiedTime; - const daysDifference = timeDifference / (1000 * 60 * 60 * 24); - - if (daysDifference > daysThreshold) { - await fsPromise.unlink(filePath); // Delete the file - //console.log(`Deleted: ${filePath}`); - } - } - } catch (error) { - //console.error('Error deleting files:', error); - } -} diff --git a/src/common/utils/log.ts b/src/common/utils/log.ts deleted file mode 100644 index 73e61033..00000000 --- a/src/common/utils/log.ts +++ /dev/null @@ -1,138 +0,0 @@ -import log4js, { Configuration } from 'log4js'; -import { truncateString } from '@/common/utils/helper'; -import path from 'node:path'; -import { SelfInfo } from '@/core'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import chalk from 'chalk'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -export enum LogLevel { - DEBUG = 'debug', - INFO = 'info', - WARN = 'warn', - ERROR = 'error', - FATAL = 'fatal', -} - -const logDir = path.join(path.resolve(__dirname), 'logs'); - -function getFormattedTimestamp() { - const now = new Date(); - const year = now.getFullYear(); - const month = (now.getMonth() + 1).toString().padStart(2, '0'); - const day = now.getDate().toString().padStart(2, '0'); - const hours = now.getHours().toString().padStart(2, '0'); - const minutes = now.getMinutes().toString().padStart(2, '0'); - const seconds = now.getSeconds().toString().padStart(2, '0'); - const milliseconds = now.getMilliseconds().toString().padStart(3, '0'); - return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}.${milliseconds}`; -} - -const filename = `${getFormattedTimestamp()}.log`; -const logPath = path.join(logDir, filename); - -const logConfig: Configuration = { - appenders: { - FileAppender: { // 输出到文件的appender - type: 'file', - filename: logPath, // 指定日志文件的位置和文件名 - maxLogSize: 10485760, // 日志文件的最大大小(单位:字节),这里设置为10MB - layout: { - type: 'pattern', - pattern: '%d{yyyy-MM-dd hh:mm:ss} [%p] %X{userInfo} | %m' - } - }, - ConsoleAppender: { // 输出到控制台的appender - type: 'console', - layout: { - type: 'pattern', - pattern: `%d{yyyy-MM-dd hh:mm:ss} [%[%p%]] ${chalk.magenta('%X{userInfo}')} | %m` - } - } - }, - categories: { - default: { appenders: ['FileAppender', 'ConsoleAppender'], level: 'debug' }, // 默认情况下同时输出到文件和控制台 - file: { appenders: ['FileAppender'], level: 'debug' }, - console: { appenders: ['ConsoleAppender'], level: 'debug' } - } -}; - -log4js.configure(logConfig); -const loggerConsole = log4js.getLogger('console'); -const loggerFile = log4js.getLogger('file'); -const loggerDefault = log4js.getLogger('default'); - -export function setLogLevel(fileLogLevel: LogLevel, consoleLogLevel: LogLevel) { - logConfig.categories.file.level = fileLogLevel; - logConfig.categories.console.level = consoleLogLevel; - log4js.configure(logConfig); -} - -export function setLogSelfInfo(selfInfo: SelfInfo) { - const userInfo = `${selfInfo.nick}(${selfInfo.uin})`; - loggerConsole.addContext('userInfo', userInfo); - loggerFile.addContext('userInfo', userInfo); - loggerDefault.addContext('userInfo', userInfo); -} -setLogSelfInfo({ nick: '', uin: '', uid: '' }); - -let fileLogEnabled = true; -let consoleLogEnabled = true; -export function enableFileLog(enable: boolean) { - fileLogEnabled = enable; -} -export function enableConsoleLog(enable: boolean) { - consoleLogEnabled = enable; -} - -function formatMsg(msg: any[]) { - let logMsg = ''; - for (const msgItem of msg) { - if (msgItem instanceof Error) { // 判断是否是错误 - logMsg += msgItem.stack + ' '; - continue; - } else if (typeof msgItem === 'object') { // 判断是否是对象 - const obj = JSON.parse(JSON.stringify(msgItem, null, 2)); - logMsg += JSON.stringify(truncateString(obj)) + ' '; - continue; - } - logMsg += msgItem + ' '; - } - return logMsg; -} - -// eslint-disable-next-line no-control-regex -const colorEscape = /\x1B[@-_][0-?]*[ -/]*[@-~]/g; - -function _log(level: LogLevel, ...args: any[]) { - if (consoleLogEnabled) { - loggerConsole[level](formatMsg(args)); - } - if (fileLogEnabled) { - loggerFile[level](formatMsg(args).replace(colorEscape, '')); - } -} - -export function log(...args: any[]) { - // info 等级 - _log(LogLevel.INFO, ...args); -} - -export function logDebug(...args: any[]) { - _log(LogLevel.DEBUG, ...args); -} - -export function logError(...args: any[]) { - _log(LogLevel.ERROR, ...args); -} - -export function logWarn(...args: any[]) { - _log(LogLevel.WARN, ...args); -} - -export function logFatal(...args: any[]) { - _log(LogLevel.FATAL, ...args); -} \ No newline at end of file diff --git a/src/common/utils/qqlevel.ts b/src/common/utils/qqlevel.ts deleted file mode 100644 index 7e957ddb..00000000 --- a/src/common/utils/qqlevel.ts +++ /dev/null @@ -1,7 +0,0 @@ -// QQ等级换算 -import { QQLevel } from '@/core/entities'; - -export function calcQQLevel(level: QQLevel) { - const { crownNum, sunNum, moonNum, starNum } = level; - return crownNum * 64 + sunNum * 16 + moonNum * 4 + starNum; -} diff --git a/src/common/utils/reboot.ts b/src/common/utils/reboot.ts deleted file mode 100644 index 5e9a7754..00000000 --- a/src/common/utils/reboot.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { resolve } from 'node:path'; -import { spawn } from 'node:child_process'; -import { pid, ppid, exit } from 'node:process'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; - - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -export async function rebootWithQuickLogin(uin: string) { - const batScript = resolve(__dirname, './napcat.bat'); - const batUtf8Script = resolve(__dirname, './napcat-utf8.bat'); - const bashScript = resolve(__dirname, './napcat.sh'); - if (process.platform === 'win32') { - const subProcess = spawn(`start ${batUtf8Script} -q ${uin}`, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' }); - subProcess.unref(); - // 子父进程一起送走 有点效果 - spawn('cmd /c taskkill /t /f /pid ' + pid.toString(), { detached: true, shell: true, stdio: 'ignore' }); - spawn('cmd /c taskkill /t /f /pid ' + ppid.toString(), { detached: true, shell: true, stdio: 'ignore' }); - } else if (process.platform === 'linux') { - const subProcess = spawn(`${bashScript} -q ${uin}`, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' }); - //还没兼容 - subProcess.unref(); - exit(0); - } - //exit(0); -} -export async function rebootWithNormolLogin() { - const batScript = resolve(__dirname, './napcat.bat'); - const batUtf8Script = resolve(__dirname, './napcat-utf8.bat'); - const bashScript = resolve(__dirname, './napcat.sh'); - if (process.platform === 'win32') { - const subProcess = spawn(`start ${batUtf8Script} `, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' }); - subProcess.unref(); - // 子父进程一起送走 有点效果 - spawn('cmd /c taskkill /t /f /pid ' + pid.toString(), { detached: true, shell: true, stdio: 'ignore' }); - spawn('cmd /c taskkill /t /f /pid ' + ppid.toString(), { detached: true, shell: true, stdio: 'ignore' }); - } else if (process.platform === 'linux') { - const subProcess = spawn(`${bashScript}`, { detached: true, windowsHide: false, env: process.env, shell: true }); - subProcess.unref(); - exit(0); - } -} \ No newline at end of file diff --git a/src/common/utils/request.ts b/src/common/utils/request.ts deleted file mode 100644 index b2653d38..00000000 --- a/src/common/utils/request.ts +++ /dev/null @@ -1,193 +0,0 @@ -import https from 'node:https'; -import http from 'node:http'; -import { readFileSync } from 'node:fs'; -import { NTQQUserApi } from '@/core'; -export class RequestUtil { - // 适用于获取服务器下发cookies时获取,仅GET - static async HttpsGetCookies(url: string): Promise<{ [key: string]: string }> { - const client = url.startsWith('https') ? https : http; - return new Promise((resolve, reject) => { - const req = client.get(url, (res) => { - let cookies: { [key: string]: string } = {}; - const handleRedirect = (res: http.IncomingMessage) => { - //console.log(res.headers.location); - if (res.statusCode === 301 || res.statusCode === 302) { - if (res.headers.location) { - const redirectUrl = new URL(res.headers.location, url); - RequestUtil.HttpsGetCookies(redirectUrl.href).then((redirectCookies) => { - // 合并重定向过程中的cookies - cookies = { ...cookies, ...redirectCookies }; - resolve(cookies); - }).catch((err) => { - reject(err); - }); - } else { - resolve(cookies); - } - } else { - resolve(cookies); - } - }; - res.on('data', () => { }); // Necessary to consume the stream - res.on('end', () => { - handleRedirect(res); - }); - if (res.headers['set-cookie']) { - //console.log(res.headers['set-cookie']); - res.headers['set-cookie'].forEach((cookie) => { - const parts = cookie.split(';')[0].split('='); - const key = parts[0]; - const value = parts[1]; - if (key && value && key.length > 0 && value.length > 0) { - cookies[key] = value; - } - }); - } - }); - req.on('error', (error: any) => { - reject(error); - }); - }); - } - - - - // 请求和回复都是JSON data传原始内容 自动编码json - static async HttpGetJson(url: string, method: string = 'GET', data?: any, headers: { [key: string]: string } = {}, isJsonRet: boolean = true, isArgJson: boolean = true): Promise { - const option = new URL(url); - const protocol = url.startsWith('https://') ? https : http; - const options = { - hostname: option.hostname, - port: option.port, - path: option.href, - method: method, - headers: headers - }; - // headers: { - // 'Content-Type': 'application/json', - // 'Content-Length': Buffer.byteLength(postData), - // }, - return new Promise((resolve, reject) => { - const req = protocol.request(options, (res: any) => { - let responseBody = ''; - res.on('data', (chunk: string | Buffer) => { - responseBody += chunk.toString(); - }); - - res.on('end', () => { - try { - if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { - if (isJsonRet) { - const responseJson = JSON.parse(responseBody); - resolve(responseJson as T); - } else { - resolve(responseBody as T); - } - } else { - reject(new Error(`Unexpected status code: ${res.statusCode}`)); - } - } catch (parseError) { - reject(parseError); - } - }); - }); - - req.on('error', (error: any) => { - reject(error); - }); - if (method === 'POST' || method === 'PUT' || method === 'PATCH') { - if (isArgJson) { - req.write(JSON.stringify(data)); - } else { - req.write(data); - } - - } - req.end(); - }); - } - - // 请求返回都是原始内容 - static async HttpGetText(url: string, method: string = 'GET', data?: any, headers: { [key: string]: string } = {}) { - return this.HttpGetJson(url, method, data, headers, false, false); - } - - static async createFormData(boundary: string, filePath: string): Promise { - let type = 'image/png'; - if (filePath.endsWith('.jpg')) { - type = 'image/jpeg'; - } - const formDataParts = [ - `------${boundary}\r\n`, - `Content-Disposition: form-data; name="share_image"; filename="${filePath}"\r\n`, - 'Content-Type: ' + type + '\r\n\r\n' - ]; - - const fileContent = readFileSync(filePath); - const footer = `\r\n------${boundary}--`; - return Buffer.concat([ - Buffer.from(formDataParts.join(''), 'utf8'), - fileContent, - Buffer.from(footer, 'utf8') - ]); - } - - static async uploadImageForOpenPlatform(filePath: string): Promise { - return new Promise(async (resolve, reject) => { - type retType = { retcode: number, result?: { url: string } }; - try { - const cookies = Object.entries(await NTQQUserApi.getCookies('connect.qq.com')).map(([key, value]) => `${key}=${value}`).join('; '); - const options = { - hostname: 'cgi.connect.qq.com', - port: 443, - path: '/qqconnectopen/upload_share_image', - method: 'POST', - headers: { - 'Referer': 'https://cgi.connect.qq.com', - 'Cookie': cookies, - 'Accept': '*/*', - 'Connection': 'keep-alive', - 'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' - } - }; - const req = https.request(options, async (res) => { - let responseBody = ''; - - res.on('data', (chunk: string | Buffer) => { - responseBody += chunk.toString(); - }); - - res.on('end', () => { - try { - if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { - const responseJson = JSON.parse(responseBody) as retType; - resolve(responseJson.result!.url!); - } else { - reject(new Error(`Unexpected status code: ${res.statusCode}`)); - } - } catch (parseError) { - reject(parseError); - } - - }); - - }); - - req.on('error', (error) => { - reject(error); - console.error('Error during upload:', error); - }); - - const body = await RequestUtil.createFormData('WebKitFormBoundary7MA4YWxkTrZu0gW', filePath); - // req.setHeader('Content-Length', Buffer.byteLength(body)); - // console.log(`Prepared data size: ${Buffer.byteLength(body)} bytes`); - req.write(body); - req.end(); - return; - } catch (error) { - reject(error); - } - return undefined; - }); - } -} diff --git a/src/common/utils/system.ts b/src/common/utils/system.ts deleted file mode 100644 index 18b476c8..00000000 --- a/src/common/utils/system.ts +++ /dev/null @@ -1,74 +0,0 @@ -import os from 'node:os'; -import path from 'node:path'; -import { networkInterfaces } from 'os'; -import { randomUUID } from 'crypto'; - -// 缓解Win7设备兼容性问题 -let osName: string; -// 设备ID -let machineId: Promise; - -try { - osName = os.hostname(); -} catch (e) { - osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4); -} - -const invalidMacAddresses = new Set([ - '00:00:00:00:00:00', - 'ff:ff:ff:ff:ff:ff', - 'ac:de:48:00:11:22' -]); - -function validateMacAddress(candidate: string): boolean { - // eslint-disable-next-line no-useless-escape - const tempCandidate = candidate.replace(/\-/g, ':').toLowerCase(); - return !invalidMacAddresses.has(tempCandidate); -} - -export async function getMachineId(): Promise { - if (!machineId) { - machineId = (async () => { - const id = await getMacMachineId(); - return id || randomUUID(); // fallback, generate a UUID - })(); - } - - return machineId; -} - -export function getMac(): string { - const ifaces = networkInterfaces(); - for (const name in ifaces) { - const networkInterface = ifaces[name]; - if (networkInterface) { - for (const { mac } of networkInterface) { - if (validateMacAddress(mac)) { - return mac; - } - } - } - } - - throw new Error('Unable to retrieve mac address (unexpected format)'); -} - -async function getMacMachineId(): Promise { - try { - const crypto = await import('crypto'); - const macAddress = getMac(); - return crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex'); - } catch (err) { - return undefined; - } -} - -const homeDir = os.homedir(); - - -export const systemPlatform = os.platform(); -export const cpuArch = os.arch(); -export const systemVersion = os.release(); -export const hostname = osName; -export const downloadsPath = path.join(homeDir, 'Downloads'); -export const systemName = os.type(); \ No newline at end of file diff --git a/src/common/utils/type.ts b/src/common/utils/type.ts deleted file mode 100644 index 7e62606c..00000000 --- a/src/common/utils/type.ts +++ /dev/null @@ -1,17 +0,0 @@ -//QQVersionType -type QQPackageInfoType = { - version: string; - buildVersion: string; - platform: string; - eleArch: string; -} -type QQVersionConfigType = { - baseVersion: string; - curVersion: string; - prevVersion: string; - onErrorVersions: Array; - buildId: string; -} -type QQAppidTableType = { - [key: string]: { appid: string, qua: string }; -} \ No newline at end of file diff --git a/src/common/utils/version.ts b/src/common/utils/version.ts deleted file mode 100644 index 01371936..00000000 --- a/src/common/utils/version.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { logDebug } from './log'; -import { RequestUtil } from './request'; -export async function checkVersion(): Promise { - return new Promise(async (resolve, reject) => { - const MirrorList = - [ - 'https://jsd.cdn.zzko.cn/gh/NapNeko/NapCatQQ@main/package.json', - 'https://fastly.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json', - 'https://gcore.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json', - 'https://cdn.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json' - ]; - let version = undefined; - for (const url of MirrorList) { - try { - version = (await RequestUtil.HttpGetJson<{ version: string }>(url)).version; - } catch (e) { - logDebug('检测更新异常',e); - } - if (version) { - resolve(version); - } - } - reject('get verison error!'); - }); -} diff --git a/src/common/utils/video.ts b/src/common/utils/video.ts deleted file mode 100644 index b459d382..00000000 --- a/src/common/utils/video.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { log } from './log'; -import ffmpeg, { FfprobeStream } from 'fluent-ffmpeg'; -import fs from 'fs'; - -const defaultVideoThumbB64 = '/9j/4AAQSkZJRgABAQAAAQABAAD//gAXR2VuZXJhdGVkIGJ5IFNuaXBhc3Rl/9sAhAAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47AQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAF/APADAREAAhEBAxEB/8QBogAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoLEAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+foBAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKCxEAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDiAayNxwagBwNAC5oAM0xBmgBM0ANJoAjY0AQsaBkTGgCM0DEpAFAC0AFMBaACgAoEJTASgQlACUwCgQ4UAOFADhQA4UAOFADxQIkBqDQUGgBwagBQaBC5pgGaAELUAMLUARs1AETGgBhNAxhoASkAUALQIKYxaBBQAUwEoAQ0CEoASmAUAOoEKKAHCgBwoAeKAHigQ7NZmoZpgLmgBd1Ahd1ABupgNLUAMLUAMY0AMJoAYaAENACUCCgAoAWgAoAWgBKYCUAJQISgApgLQAooEOFACigB4oAeKBDxQAVmaiZpgGaAFzQAbqAE3UAIWpgNJoAYTQIaaAEoAQ0CEoASgBaACgBaACmAUAJQAlAgoAKYC0AKKBCigB4FADgKBDwKAHigBuazNRM0DEzTAM0AJmgAzQAhNAhpNACGmA2gQlACUCEoAKACgBaAFpgFACUAJQAUCCmAUALQIcBQA4CgB4FADgKBDhQA4UAMzWZqNzTGJQAZoATNABmgBKAEoEIaYCUCEoASgQlABQAtABQAtMBKACgAoEFABimAYoEKBQA4CgB4FADwKBDgKAFFADhQBCazNhKAEpgFACUAFACUAFAhDTAbQISgAoEJQAUALQAtMAoAKADFABigQYoAMUALimIUCgBwFAh4FADgKAHUALQAtAENZmwlACUwEoAKAEoAKACgQlMBpoEJQAUCCgBcUAFABTAXFAC4oAMUAGKBBigAxQIKYCigQ8UAOFADhQAtAC0ALQBDWZqJQMSgBKYBQAlABQISgBKYCGgQlAC0CCgBcUAFABTAUCkA7FMAxQAYoEJQAUCCmAooEOFADxQA4UAFAC0ALQBDWZqJQAlACUxhQAlABQIKAEoASmISgBcUCCgBaACgBcUAKBQAuKYC0CEoAQ0AJQISmAooEPFADhQA4UALQAtAC0AQ1maiUAFACUAJTAKAEoAKAEoAMUxBigAxQIWgAoAKAFAoAWgBaYBQIQ0ANNACUCCmIUUAOFADxQA4UALQAtABQBFWZqFACUAFACYpgFACUAFACUAFAgxTEFABQAUALQAooAWgAoAKYDTQIaaAEpiCgQ4UAOFAh4oGOFAC0ALSAKYEdZmglABQAUDDFACUwEoASgAoAKBBQIKYBQAUALQAtAC0AJQAhpgNJoENJoATNMQCgQ8UCHigB4oAWgYtABQAUAMrM0CgAoAKADFACUxiUAJQAlAgoAKYgoAKACgYtAC0AFAhDTAQmgBhNAhpNACZpiFBoEPFAEi0CHigB1ABQAUDEoAbWZoFABQAtABTAQ0ANNAxDQAlAhaAEpiCgAoGFAC0AFABmgBCaYhpNADCaBDSaBBmgABpiJFNAEimgB4NADqAFzQAlACE0AJWZoFAC0AFAC0wEIoAaaAG0AJQAUCCgApjCgAoAKADNABmgBpNMQ0mgBpNAhhNAgzQAoNADwaAHqaAJAaBDgaYC5oATNACZoAWszQKACgBaBDqYCGgBpoAYaBiUCCgBKYBQMKACgAoAM0AITQIaTQA0mmA0mgQ3NAhKAHCgBwNADwaAHg0AOBpiFzQAZoATNAD6zNAoAKAFoEOpgBoAaaAGGmAw0AJmgAzQMM0AGaADNABmgBM0AITQIaTQAhNMQw0AJQIKAFFADhQA4GgBwNADs0xC5oAM0CDNAEtZmoUCCgBaAHUwCgBppgRtQAw0ANzQAZoAM0AGaADNABmgBKAEoAQ0ANNMQhoEJQAlMBaQDgaAFBoAcDTAdmgQuaADNAgzQBPWZqFAgoAWgBaYC0CGmmBG1AyM0ANJoATNACZoAXNABmgAzQAUAJQAhoAQ0xDTQISmAUALQAUgHA0AKDTAdmgQuaBBQAtAFiszQKACgBaAFFMAoEIaYEbUDI2oAYaAEoASgAzQAuaACgAoAKAENMQ00AJTEFAhKACgAoAXNACg0AOBoAWgQtAC0AWazNAoAKACgBaYBQIQ0AMNMYw0AMIoAbQAlMAoAKACgAzSAKYhKAENACUxBQIKACgBKACgBaAHCgQ4UALQAUAWqzNAoAKACgApgFACGgQ00xjTQAwigBCKAG4pgJQAlABQAUCCgBKACgBKYgoEFABQISgAoAWgBRQA4UALQAUCLdZmoUAFABQAlMAoASgBDQA00wENACYoATFMBpFADSKAEoEJQAUAFABQAlMQtAgoASgQUAJQAUAKKAHCgBaBBQBbrM1CgAoAKACmAUAJQAlADaYBQAlACYpgIRQA0igBpFAhtABQAUAFMAoEFABQIKAEoASgQUALQAooAWgQUAW81mbC0CCgApgFACUAIaAEpgJQAUAFABQAhFMBpFADSKAGkUCExQAYoAMUAGKADFMQYoAMUCExSATFABQIKYBQAtABQIt5qDYM0ALmgQtIApgIaAENADaACmAlAC0ALQAUwGkUANIoAaRQAmKBBigAxQAYoAMUAGKBBigBMUAJigQmKAExTAKBC0AFAFnNQaig0AKDQAtAgoASgBDQAlMBKACgAFADhQAtMBCKAGkUAIRQAmKADFABigQmKADFACYoAXFABigQmKAExQAmKBCYpgJigAoAnzUGgZoAcDQAuaBC0AJQAhoASmAlABQAtADhQAtMAoATFACEUAJigAxQAYoATFAhMUAFABQAuKADFABigBpWgBCKBCYpgJigB+ag0DNADgaBDgaAFzQITNACUAJTAKACgBRQAopgOoAWgBKAEoAKACgAoASgBpoEJQAooAWgBaBhigBMUCEIoAQigBMUAJSLCgBQaBDgaQC5oEFACUwCgBKACmAtADhQA4UALQAUAJQAUAJQAUAJQAhoENoAWgBRQAooGLQAUAGKAGkUAIRQIZSKEoGKKBDhQAUCCgAoAKBBQAUwFoGKKAHCgBaACgAoASgAoASgBCaAEoEJmgAoAUGgBQaAHZoGFABQAUANoAjpDEoAWgBaAFoEFACUALQAUCCmAUAOFAxRQAtAC0AJQAUAJQAmaBDSaAEzQAmaYBmgBQaAHA0gFzQAuaBhmgAzQAlAEdIYUALQAtAgoAKAEoEFAC0AFMAoAUUDFFAC0ALQAUAJQAhoENNACE0wEoATNABmgBc0ALmgBc0gDNAC5oATNABmgBKRQlACigB1AgoASgQlABTAWgBKACgBaBi0ALQAZoAM0AFACGgQ00wENACUAJQAUCFzQMM0ALmgAzQAZoAM0AGaQC0igoAUUALQIWgBDQISmAUAFACUAFABQAuaBi5oAM0AGaBBmgBKAEpgIaAG0AJQAUCFoAM0DDNAC5oATNABmgAzQBJUlBQAooAWgQtACGmIaaACgAoASgBKACgBc0DCgQUAGaADNABTASgBDQAlACUAFAgoAKBhQAUAFABQAlAE1SUFAxRQIWgQtMBDQIQ0AJQAlAhKBiUAFABmgBc0AGaADNABTAKACgBKAEoASgQlABQAUAFAC0AFACUAFAE1SaBQAUCHCgQtMBKBCUAJQISgBDQA00DEzQAuaADNMBc0AGaADNABQAUAJQAlABQISgAoAKACgBaACgBKAEoAnqTQSgBRQIcKBC0xCUAJQISgBKAENADDQAmaYwzQAuaADNAC0AFABQAUAFAhKACgBKACgAoAWgAoELQAlAxKAJqk0EoAWgQooELTEFADaBCUABoENNMY00ANNAwzQAZoAXNAC0AFAC0CFoASgAoASgBKACgAoAWgQtABQAUANNAyWpNAoAKBCimIWgQUCEoASmIQ0ANNADTQMaaAEoGLmgAzQAtADhQIWgBaACgQhoASgYlACUALQIWgBaACgBKAENAyWpNBKYBQIcKBC0CEoEJTAKBCUANNADDQMQ0ANoGFAC5oAUGgBwNAhRQIWgBaAENACGgBtAwoAKAFzQIXNABmgAoAQ0DJKRoJQAtAhRQSLQIKYCUCCgBDQA00AMNAxpoGNoAM0AGaAFBoAcDQIcKBDqACgBDQAhoAQ0DEoAKADNAC5oEGaBhmgAoAkpGgUCCgQooELQIKYhKACgBKAGmgBpoGMNAxDQAlAwzQIUUAOFAhwoAcKBC0AJQAhoGNNACUAFABQAZoAXNABQAUAS0ixKACgQoNAhaYgoEFACUABoAaaAGmgYw0DENAxtABQAooEOFADhQIcKAFoASgBDQAhoGJQAUAFACUALQIKBi0CJDSLEoATNAhc0CHZpiCgQUAJQIKBjTQAhoGNNAxpoATFABigBQKAHCgBwoAWgAoAKACgBKAEoASgAoASgBaAAUAOoEONIoaTQAZoAUGmIUGgQtAgzQISgAoAQ0DGmgYlAxKACgAxQAtACigBRQAtAxaACgAoATFABigBCKAG0CEoAWgBRTAUUAf//Z'; - -export const defaultVideoThumb = Buffer.from(defaultVideoThumbB64, 'base64'); - -export async function getVideoInfo(filePath: string) { - const size = fs.statSync(filePath).size; - return new Promise<{ - width: number, - height: number, - time: number, - format: string, - size: number, - filePath: string - }>((resolve, reject) => { - const ffmpegPath = process.env.FFMPEG_PATH; - ffmpegPath && ffmpeg.setFfmpegPath(ffmpegPath); - ffmpeg(filePath).ffprobe((err: any, metadata: ffmpeg.FfprobeData) => { - if (err) { - reject(err); - } else { - const videoStream = metadata.streams.find((s: FfprobeStream) => s.codec_type === 'video'); - if (videoStream) { - log(`视频尺寸: ${videoStream.width}x${videoStream.height}`); - } else { - return reject('未找到视频流信息。'); - } - resolve({ - width: videoStream.width!, height: videoStream.height!, - time: parseInt(videoStream.duration!), - format: metadata.format.format_name!, - size, - filePath - }); - } - }); - }); -} -export function checkFfmpeg(newPath: string | null = null): Promise { - return new Promise((resolve, reject) => { - log('开始检查ffmpeg', newPath); - if (newPath) { - ffmpeg.setFfmpegPath(newPath); - } - try { - ffmpeg.getAvailableFormats((err: any, formats: any) => { - if (err) { - log('ffmpeg is not installed or not found in PATH:', err); - resolve(false); - } else { - log('ffmpeg is installed.'); - resolve(true); - } - }); - } catch (e) { - resolve(false); - } - }); -} diff --git a/src/core/.eslintrc.cjs b/src/core/.eslintrc.cjs deleted file mode 100644 index 3212fad6..00000000 --- a/src/core/.eslintrc.cjs +++ /dev/null @@ -1,67 +0,0 @@ -module.exports = { - 'root': true, - 'env': { - 'es2021': true, - 'node': true - }, - 'extends': [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended' - ], - 'overrides': [ - { - 'env': { - 'node': true - }, - 'files': [ - '.eslintrc.{js,cjs}' - ], - 'parserOptions': { - 'sourceType': 'script' - } - } - ], - 'parser': '@typescript-eslint/parser', - 'parserOptions': { - 'ecmaVersion': 'latest', - 'sourceType': 'module' - }, - 'plugins': [ - '@typescript-eslint', - 'import' - ], - 'settings': { - 'import/parsers': { - '@typescript-eslint/parser': ['.ts'] - }, - 'import/resolver': { - 'typescript': { - 'alwaysTryTypes': true - } - } - }, - 'rules': { - 'indent': [ - 'error', - 2 - ], - 'linebreak-style': [ - 'error', - 'unix' - ], - 'quotes': [ - 'error', - 'single' - ], - 'semi': [ - 'error', - 'always' - ], - 'no-unused-vars': 'off', - 'no-async-promise-executor': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-var-requires': 'off', - 'object-curly-spacing': ['error', 'always'], - } -}; diff --git a/src/core/.gitignore b/src/core/.gitignore deleted file mode 100644 index bc178a54..00000000 --- a/src/core/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.idea/ -node_modules/ -dist/ -lib/ -package-lock.json diff --git a/src/core/README.md b/src/core/README.md deleted file mode 100644 index b6b779bb..00000000 --- a/src/core/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @napneko/core - -此仓库目前只用于隐藏源码,目前无法进行单独打包,只是作为 NapCatQQ 的 git submodule 引用。 \ No newline at end of file diff --git a/src/core/build.cjs b/src/core/build.cjs deleted file mode 100644 index 0090b28a..00000000 --- a/src/core/build.cjs +++ /dev/null @@ -1,51 +0,0 @@ -const swc = require("@swc/core"); -const glob = require('glob'); -const fs = require('fs-extra'); - -const files = glob.sync('src/**/*.ts'); - -function transfrom(file) { - return swc - .transformFile(file, { - // Some options cannot be specified in .swcrc - sourceMaps: false, - // Input files are treated as module by default. - // isModule: false, - module: { - type: 'commonjs' - }, - - // All options below can be configured via .swcrc - jsc: { - parser: { - syntax: "typescript", - decorators: true, - }, - transform: { - "legacyDecorator": true, - "decoratorMetadata": true - }, - target: 'es2017' - }, - // "keepClassNames": true, - // "loose": true - }) - .then((output) => { - // console.log(output.code); // transformed code - return { - file, - output - } - }); -} - -(async () => { - const result = await Promise.all(files.map((file) => { - return transfrom(file) - })); - - await Promise.all(result.map((item) => { - return fs.outputFile(item.file.replace('src', 'dist').replace('.ts', '.js'), item.output.code) - })); - //console.timeEnd('swc build'); -})() diff --git a/src/core/package.json b/src/core/package.json deleted file mode 100644 index f4220b92..00000000 --- a/src/core/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "@napneko/core", - "version": "1.0.0", - "description": "", - "type": "module", - "main": "./lib/index.js", - "files": [ - "lib" - ], - "scripts": { - "lint": "eslint --fix ./src/**/*.ts", - "build": "npx tsc --target es2022 --experimentalDecorators && node ./scripts/obfuscator.cjs" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/NapNeko/core.git" - }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/NapNeko/core/issues" - }, - "homepage": "https://github.com/NapNeko/core#readme", - "devDependencies": { - "@babel/core": "^7.24.7", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-decorators": "^7.24.7", - "@babel/preset-typescript": "^7.24.7", - "@swc/core": "^1.6.1", - "@types/node": "^20.12.7", - "@typescript-eslint/eslint-plugin": "^6.21.0", - "eslint": "^8.57.0", - "eslint-config-standard-with-typescript": "^43.0.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-n": "^16.6.2", - "eslint-plugin-promise": "^6.1.1", - "typescript": "^5.4.5", - "vite": "^5.2.8", - "vite-plugin-babel": "^1.2.0", - "vite-plugin-dts": "^3.8.1" - }, - "dependencies": { - "@log4js-node/log4js-api": "^1.0.2" - } -} diff --git a/src/core/pub-package.json b/src/core/pub-package.json deleted file mode 100644 index d7b4b825..00000000 --- a/src/core/pub-package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@napneko/core", - "version": "1.0.0", - "description": "", - "type": "module", - "main": "./index.js", - "files": [ - "lib" - ], - "scripts": { - "lint": "eslint --fix ./src/**/*.ts", - "build:dev": "vite build --mode development", - "build:prod": "vite build --mode production", - "build": "npm run build:dev" - }, - "author": "NapNeko", - "license": "MIT", - "bugs": { - "url": "https://github.com/NapNeko/NapCatQQ/issues" - }, - "homepage": "https://github.com/NapNeko/NapCatQQ#readme" -} diff --git a/src/core/scripts/obfuscator.cjs b/src/core/scripts/obfuscator.cjs deleted file mode 100644 index a4c12582..00000000 --- a/src/core/scripts/obfuscator.cjs +++ /dev/null @@ -1,45 +0,0 @@ -let fs = require('fs'); -let path = require('path'); -let JavaScriptObfuscator = require('javascript-obfuscator'); - -const dirPath = path.join(__dirname, '../dist/core'); -const outputPath = dirPath; - -if (!fs.existsSync(outputPath)) { - fs.mkdirSync(outputPath, {recursive: true}); -} - -function obfuscateDir(currentPath, outputDir) { - fs.readdir(currentPath, {withFileTypes: true}, (err, entries) => { - if (err) throw err; - - entries.forEach(entry => { - const localBasePath = path.join(currentPath, entry.name); - const outputLocalBasePath = path.join(outputDir, entry.name); - - if (entry.isDirectory()) { - // 如果是目录,递归调用 - if (!fs.existsSync(outputLocalBasePath)) { - fs.mkdirSync(outputLocalBasePath, {recursive: true}); - } - obfuscateDir(localBasePath, outputLocalBasePath); - } else if (entry.isFile() && path.extname(entry.name) === '.js') { - // 如果是文件且为 .js,进行混淆 - fs.readFile(localBasePath, (err, content)=>{ - // console.log('read file', localBasePath); - const obfuscated = JavaScriptObfuscator.obfuscate(content.toString(), { - compact: true, - controlFlowFlattening: true - }); - // console.log('obfuscate file', localBasePath); - fs.writeFile(outputLocalBasePath, obfuscated.getObfuscatedCode(), ()=>{ - // console.log(`[NapCat] [Obfuscator] ${localBasePath} => ${outputLocalBasePath}`); - }); - }); - } - }); - }); -} - -// 开始混淆 -obfuscateDir(dirPath, outputPath); diff --git a/src/core/src/adapters/NodeIDependsAdapter.ts b/src/core/src/adapters/NodeIDependsAdapter.ts deleted file mode 100644 index 7f77a83c..00000000 --- a/src/core/src/adapters/NodeIDependsAdapter.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { log } from "@/common/utils/log"; - -interface IDependsAdapter { - onMSFStatusChange(arg1: number, arg2: number): void; - - onMSFSsoError(args: unknown): void; - - getGroupCode(args: unknown): void; -} - -export interface NodeIDependsAdapter extends IDependsAdapter { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(adapter: IDependsAdapter): NodeIDependsAdapter; -} - -export class DependsAdapter implements IDependsAdapter { - onMSFStatusChange(arg1: number, arg2: number) { - // console.log(arg1, arg2); - // if (arg1 == 2 && arg2 == 2) { - // log("NapCat丢失网络连接,请检查网络") - // } - } - - onMSFSsoError(args: unknown) { - } - - getGroupCode(args: unknown) { - } -} diff --git a/src/core/src/adapters/NodeIDispatcherAdapter.ts b/src/core/src/adapters/NodeIDispatcherAdapter.ts deleted file mode 100644 index 20557687..00000000 --- a/src/core/src/adapters/NodeIDispatcherAdapter.ts +++ /dev/null @@ -1,23 +0,0 @@ -interface IDispatcherAdapter { - dispatchRequest(arg: unknown): void; - - dispatchCall(arg: unknown): void; - - dispatchCallWithJson(arg: unknown): void; -} - -export interface NodeIDispatcherAdapter extends IDispatcherAdapter { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(adapter: IDispatcherAdapter): NodeIDispatcherAdapter; -} - -export class DispatcherAdapter implements IDispatcherAdapter { - dispatchRequest(arg: unknown) { - } - - dispatchCall(arg: unknown) { - } - - dispatchCallWithJson(arg: unknown) { - } -} diff --git a/src/core/src/adapters/NodeIGlobalAdapter.ts b/src/core/src/adapters/NodeIGlobalAdapter.ts deleted file mode 100644 index 29cb906a..00000000 --- a/src/core/src/adapters/NodeIGlobalAdapter.ts +++ /dev/null @@ -1,48 +0,0 @@ -interface IGlobalAdapter { - onLog(...args: unknown[]): void; - - onGetSrvCalTime(...args: unknown[]): void; - - onShowErrUITips(...args: unknown[]): void; - - fixPicImgType(...args: unknown[]): void; - - getAppSetting(...args: unknown[]): void; - - onInstallFinished(...args: unknown[]): void; - - onUpdateGeneralFlag(...args: unknown[]): void; - - onGetOfflineMsg(...args: unknown[]): void; -} - -export interface NodeIGlobalAdapter extends IGlobalAdapter { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(adapter: IGlobalAdapter): NodeIGlobalAdapter; -} - -export class GlobalAdapter implements IGlobalAdapter { - onLog(...args: unknown[]) { - } - - onGetSrvCalTime(...args: unknown[]) { - } - - onShowErrUITips(...args: unknown[]) { - } - - fixPicImgType(...args: unknown[]) { - } - - getAppSetting(...args: unknown[]) { - } - - onInstallFinished(...args: unknown[]) { - } - - onUpdateGeneralFlag(...args: unknown[]) { - } - - onGetOfflineMsg(...args: unknown[]) { - } -} diff --git a/src/core/src/adapters/index.ts b/src/core/src/adapters/index.ts deleted file mode 100644 index 2db6d288..00000000 --- a/src/core/src/adapters/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './NodeIDependsAdapter'; -export * from './NodeIDispatcherAdapter'; -export * from './NodeIGlobalAdapter'; diff --git a/src/core/src/apis/collection.ts b/src/core/src/apis/collection.ts deleted file mode 100644 index bcaf8795..00000000 --- a/src/core/src/apis/collection.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { napCatCore } from ".."; - -export class NTQQCollectionApi { - static async createCollection(authorUin: string, authorUid: string, authorName: string, brief: string, rawData: string) { - let param = { - commInfo: { - bid: 1, - category: 2, - author: { - type: 1, - numId: authorUin, - strId: authorName, - groupId: '0', - groupName: '', - uid: authorUid - }, - customGroupId: '0', - createTime: Date.now().toString(), - sequence: Date.now().toString() - }, - richMediaSummary: { - originalUri: '', - publisher: '', - richMediaVersion: 0, - subTitle: '', - title: '', - brief: brief, - picList: [], - contentType: 1 - }, - richMediaContent: { - rawData: rawData, - bizDataList: [], - picList: [], - fileList: [] - }, - need_share_url: false - }; - return napCatCore.session.getCollectionService().createNewCollectionItem(param); - } - static async getAllCollection(category: number = 0, count: number = 50) { - let param = { - category: category, - groupId: -1, - forceSync: true, - forceFromDb: false, - timeStamp: "0", - count: count, - searchDown: true - }; - return napCatCore.session.getCollectionService().getCollectionItemList(param); - } -} diff --git a/src/core/src/apis/file.ts b/src/core/src/apis/file.ts deleted file mode 100644 index 4564d4da..00000000 --- a/src/core/src/apis/file.ts +++ /dev/null @@ -1,341 +0,0 @@ -import { - CacheFileListItem, - CacheFileType, - ChatCacheListItemBasic, - ChatType, - ElementType, IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT, Peer, PicElement, RawMessage -} from '@/core/entities'; -import path from 'path'; -import fs from 'fs'; -import fsPromises from 'fs/promises'; -import { log, logDebug, logError } from '@/common/utils/log'; -import { GeneralCallResult, napCatCore, OnRichMediaDownloadCompleteParams } from '@/core'; -import { calculateFileMD5 } from '@/common/utils/file'; -import * as fileType from 'file-type'; -import imageSize from 'image-size'; -import { ISizeCalculationResult } from 'image-size/dist/types/interface'; -import { sessionConfig } from '@/core/sessionConfig'; -import { rkeyManager } from '../utils/rkey'; -import { NTEventDispatch } from '@/common/utils/EventTask'; -import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService'; -import { selfInfo } from '../data'; - - -export class NTQQFileApi { - static async getFileType(filePath: string) { - return fileType.fileTypeFromFile(filePath); - } - - static async copyFile(filePath: string, destPath: string) { - await napCatCore.util.copyFile(filePath, destPath); - } - - static async getFileSize(filePath: string): Promise { - return await napCatCore.util.getFileSize(filePath); - } - static async getVideoUrl(peer: Peer, msgId: string, elementId: string) { - return (await napCatCore.session.getRichMediaService().getVideoPlayUrlV2(peer, msgId, elementId, 0, { downSourceType: 1, triggerType: 1 })).urlResult.domainUrl; - } - // 上传文件到QQ的文件夹 - static async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) { - // napCatCore.wrapper.util. - const fileMd5 = await calculateFileMD5(filePath); - let ext: string = (await NTQQFileApi.getFileType(filePath))?.ext as string || ''; - if (ext) { - ext = '.' + ext; - } - let fileName = `${path.basename(filePath)}`; - if (fileName.indexOf('.') === -1) { - fileName += ext; - } - const mediaPath = napCatCore.session.getMsgService().getRichMediaFilePathForGuild({ - md5HexStr: fileMd5, - fileName: fileName, - elementType: elementType, - elementSubType, - thumbSize: 0, - needCreate: true, - downloadType: 1, - file_uuid: '' - }); - await NTQQFileApi.copyFile(filePath, mediaPath!); - const fileSize = await NTQQFileApi.getFileSize(filePath); - return { - md5: fileMd5, - fileName, - path: mediaPath, - fileSize, - ext - }; - } - static async downloadMediaByUuid() { - //napCatCore.session.getRichMediaService().downloadFileForFileUuid(); - } - static async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) { - //logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force); - // 用于下载收到的消息中的图片等 - if (sourcePath && fs.existsSync(sourcePath)) { - if (force) { - try { - await fsPromises.unlink(sourcePath); - } catch (e) { - // - } - } else { - return sourcePath; - } - } - let data = await NTEventDispatch.CallNormalEvent< - ( - params: { - fileModelId: string, - downloadSourceType: number, - triggerType: number, - msgId: string, - chatType: ChatType, - peerUid: string, - elementId: string, - thumbSize: number, - downloadType: number, - filePath: string - }) => Promise, - (fileTransNotifyInfo: OnRichMediaDownloadCompleteParams) => void - >( - 'NodeIKernelMsgService/downloadRichMedia', - 'NodeIKernelMsgListener/onRichMediaDownloadComplete', - 1, - timeout, - (arg: OnRichMediaDownloadCompleteParams) => { - if (arg.msgId === msgId) { - return true; - } - return false; - }, - { - fileModelId: '0', - downloadSourceType: 0, - triggerType: 1, - msgId: msgId, - chatType: chatType, - peerUid: peerUid, - elementId: elementId, - thumbSize: 0, - downloadType: 1, - filePath: thumbPath - } - ); - let filePath = data[1].filePath; - if (filePath.startsWith('\\')) { - // log('filePath start with \\'); - const downloadPath = sessionConfig.defaultFileDownloadPath; - //logDebug('downloadPath', downloadPath); - filePath = path.join(downloadPath, filePath); - // 下载路径是下载文件夹的相对路径 - } - return filePath; - } - - static async getImageSize(filePath: string): Promise { - return new Promise((resolve, reject) => { - imageSize(filePath, (err, dimensions) => { - if (err) { - reject(err); - } else { - resolve(dimensions); - } - }); - }); - } - static async addFileCache(peer: Peer, msgId: string, msgSeq: string, senderUid: string, elemId: string, elemType: string, fileSize: string, fileName: string) { - let GroupData; - let BuddyData; - if (peer.chatType === ChatType.group) { - GroupData = - [{ - groupCode: peer.peerUid, - isConf: false, - hasModifyConfGroupFace: true, - hasModifyConfGroupName: true, - groupName: "NapCat.Cached", - remark: "NapCat.Cached" - }]; - } else if (peer.chatType === ChatType.friend) { - BuddyData = [{ - category_name: 'NapCat.Cached', - peerUid: peer.peerUid, - peerUin: peer.peerUid, - remark: 'NapCat.Cached' - }]; - } else { - return undefined; - } - - return napCatCore.session.getSearchService().addSearchHistory({ - type: 4, - contactList: [], - id: -1, - groupInfos: [], - msgs: [], - fileInfos: [ - { - chatType: peer.chatType, - buddyChatInfo: BuddyData || [], - discussChatInfo: [], - groupChatInfo: GroupData || [], - dataLineChatInfo: [], - tmpChatInfo: [], - msgId: msgId, - msgSeq: msgSeq, - msgTime: Math.floor(Date.now() / 1000).toString(), - senderUid: senderUid, - senderNick: 'NapCat.Cached', - senderRemark: 'NapCat.Cached', - senderCard: 'NapCat.Cached', - elemId: elemId, - elemType: elemType, - fileSize: fileSize, - filePath: '', - fileName: fileName, - hits: [{ - start: 12, - end: 14 - }] - } - ] - }); - } - static async searchfile(keys: string[]) { - type EventType = NodeIKernelSearchService['searchFileWithKeywords']; - interface OnListener { - searchId: string, - hasMore: boolean, - resultItems: { - chatType: ChatType, - buddyChatInfo: any[], - discussChatInfo: any[], - groupChatInfo: - { - groupCode: string, - isConf: boolean, - hasModifyConfGroupFace: boolean, - hasModifyConfGroupName: boolean, - groupName: string, - remark: string - }[] - , - dataLineChatInfo: any[], - tmpChatInfo: any[], - msgId: string, - msgSeq: string, - msgTime: string, - senderUid: string, - senderNick: string, - senderRemark: string, - senderCard: string, - elemId: string, - elemType: number, - fileSize: string, - filePath: string, - fileName: string, - hits: - { - start: number, - end: number - }[] - }[] - }; - const Event = await NTEventDispatch.CreatEventFunction('NodeIKernelSearchService/searchFileWithKeywords'); - let id = ''; - const Listener = NTEventDispatch.RegisterListen<(params: OnListener) => void>('NodeIKernelSearchListener/onSearchFileKeywordsResult', 1, 20000, (params) => { - if (id !== '' && params.searchId == id) { - return true - } - return false; - }); - id = await Event!(keys, 12); - let [ret] = (await Listener); - return ret; - } - static async getImageUrl(element: PicElement) { - if (!element) { - return ''; - } - const url: string = element.originImageUrl!; // 没有域名 - const md5HexStr = element.md5HexStr; - const fileMd5 = element.md5HexStr; - const fileUuid = element.fileUuid; - - if (url) { - let UrlParse = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接 - let imageAppid = UrlParse.searchParams.get('appid'); - let isNewPic = imageAppid && ['1406', '1407'].includes(imageAppid); - if (isNewPic) { - let UrlRkey = UrlParse.searchParams.get('rkey'); - if (UrlRkey) { - return IMAGE_HTTP_HOST_NT + url; - } - const rkeyData = await rkeyManager.getRkey(); - UrlRkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey; - return IMAGE_HTTP_HOST_NT + url + `${UrlRkey}`; - } else { - // 老的图片url,不需要rkey - return IMAGE_HTTP_HOST + url; - } - } else if (fileMd5 || md5HexStr) { - // 没有url,需要自己拼接 - return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 || md5HexStr)!.toUpperCase()}/0`; - } - logDebug('图片url获取失败', element); - return ''; - } -} - -export class NTQQFileCacheApi { - static async setCacheSilentScan(isSilent: boolean = true) { - return ''; - } - - static getCacheSessionPathList() { - return ''; - } - - static clearCache(cacheKeys: Array = ['tmp', 'hotUpdate']) { - // 参数未验证 - return napCatCore.session.getStorageCleanService().clearCacheDataByKeys(cacheKeys); - } - - static addCacheScannedPaths(pathMap: object = {}) { - return napCatCore.session.getStorageCleanService().addCacheScanedPaths(pathMap); - } - - static scanCache(): Promise { - // 需要注册Listener onFinishScan - return napCatCore.session.getStorageCleanService().scanCache(); - } - - static getHotUpdateCachePath() { - // 未实现 - return ''; - } - - static getDesktopTmpPath() { - // 未实现 - return ''; - } - - static getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) { - return napCatCore.session.getStorageCleanService().getChatCacheInfo(type, pageSize, 1, pageIndex); - } - - static getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) { - const _lastRecord = lastRecord ? lastRecord : { fileType: fileType }; - //需要五个参数 - //return napCatCore.session.getStorageCleanService().getFileCacheInfo(); - } - - static async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) { - return napCatCore.session.getStorageCleanService().clearChatCacheInfo(chats, fileKeys); - } -} diff --git a/src/core/src/apis/friend.ts b/src/core/src/apis/friend.ts deleted file mode 100644 index d9f853fe..00000000 --- a/src/core/src/apis/friend.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { FriendRequest, FriendV2, SimpleInfo, User } from '@/core/entities'; -import { BuddyListReqType, napCatCore, NodeIKernelBuddyListener, NodeIKernelProfileService, OnBuddyChangeParams } from '@/core'; -import { NTEventDispatch } from '@/common/utils/EventTask'; -import { LimitedHashTable } from '@/common/utils/MessageUnique'; -import { CacheClassFuncAsyncExtend } from '@/common/utils/helper'; -export class NTQQFriendApi { - static async getBuddyV2(refresh = false): Promise { - let uids: string[] = []; - const buddyService = napCatCore.session.getBuddyService(); - const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL); - uids.push(...buddyListV2.data.flatMap(item => item.buddyUids)); - const data = await NTEventDispatch.CallNoListenerEvent( - 'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids - ); - return Array.from(data.values()); - } - @CacheClassFuncAsyncExtend(3600 * 1000, 'getBuddyIdMap', () => true) - static async getBuddyIdMapCache(refresh = false): Promise> { - return await NTQQFriendApi.getBuddyIdMap(refresh); - } - static async getBuddyIdMap(refresh = false): Promise> { - let uids: string[] = []; - let retMap: LimitedHashTable = new LimitedHashTable(5000); - const buddyService = napCatCore.session.getBuddyService(); - const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL); - uids.push(...buddyListV2.data.flatMap(item => item.buddyUids)); - const data = await NTEventDispatch.CallNoListenerEvent( - 'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids - ); - data.forEach((value, key) => { - retMap.set(value.uin!, value.uid!); - }); - //console.log('getBuddyIdMap', retMap.getValue); - return retMap; - } - static async getBuddyV2ExWithCate(refresh = false) { - let uids: string[] = []; - let categoryMap: Map = new Map(); - const buddyService = napCatCore.session.getBuddyService(); - const buddyListV2 = refresh ? (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data : (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data; - uids.push( - ...buddyListV2.flatMap(item => { - item.buddyUids.forEach(uid => { - categoryMap.set(uid, { categoryId: item.categoryId, categroyName: item.categroyName }); - }); - return item.buddyUids - })); - const data = await NTEventDispatch.CallNoListenerEvent( - 'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids - ); - return Array.from(data).map(([key, value]) => { - const category = categoryMap.get(key); - return category ? { ...value, categoryId: category.categoryId, categroyName: category.categroyName } : value; - }); - } - static async isBuddy(uid: string) { - return napCatCore.session.getBuddyService().isBuddy(uid); - } - /** - * @deprecated - * @param forced - * @returns - */ - static async getFriends(forced = false): Promise { - let [_retData, _BuddyArg] = await NTEventDispatch.CallNormalEvent - <(force: boolean) => Promise, (arg: OnBuddyChangeParams) => void> - ( - 'NodeIKernelBuddyService/getBuddyList', - 'NodeIKernelBuddyListener/onBuddyListChange', - 1, - 5000, - () => true, - forced - ); - const friends: User[] = []; - for (const categoryItem of _BuddyArg) { - for (const friend of categoryItem.buddyList) { - friends.push(friend); - } - } - return friends; - } - - static async handleFriendRequest(flag: string, accept: boolean) { - let data = flag.split('|'); - if (data.length < 2) { - return; - } - let friendUid = data[0]; - let reqTime = data[1]; - napCatCore.session.getBuddyService()?.approvalFriendRequest({ - friendUid: friendUid, - reqTime: reqTime, - accept - }); - } -} diff --git a/src/core/src/apis/group.ts b/src/core/src/apis/group.ts deleted file mode 100644 index 1ccf1e99..00000000 --- a/src/core/src/apis/group.ts +++ /dev/null @@ -1,327 +0,0 @@ -import { GroupMember, GroupRequestOperateTypes, GroupMemberRole, GroupNotify, Group, MemberExtSourceType, GroupNotifyTypes, ChatType, Peer, GroupListUpdateType } from '../entities'; -import { GeneralCallResult, NTQQUserApi, NodeIKernelGroupListener, NodeIKernelGroupService, napCatCore } from '@/core'; -import { NTEventDispatch } from '@/common/utils/EventTask'; -import { log } from '@/common/utils/log'; -import { groupMembers } from '../data'; -import { CacheClassFuncAsyncExtend, runAllWithTimeout } from '@/common/utils/helper'; -export class NTQQGroupApi { - static async setGroupAvatar(gc: string, filePath: string) { - return napCatCore.session.getGroupService().setHeader(gc, filePath); - } - static async getGroups(forced = false) { - type ListenerType = NodeIKernelGroupListener['onGroupListUpdate']; - let [_retData, _updateType, groupList] = await NTEventDispatch.CallNormalEvent - <(force: boolean) => Promise, ListenerType> - ( - 'NodeIKernelGroupService/getGroupList', - 'NodeIKernelGroupListener/onGroupListUpdate', - 1, - 5000, - (updateType) => true, - forced - ); - return groupList; - } - - @CacheClassFuncAsyncExtend(3600 * 1000, "LastestSendTime", () => true) - static async getGroupMemberLastestSendTimeCache(GroupCode: string) { - return NTQQGroupApi.getGroupMemberLastestSendTime(GroupCode); - } - /** - * 通过QQ自带数据库获取群成员最后发言时间(仅返回有效数据 且消耗延迟大 需要进行缓存) - * @param GroupCode 群号 - * @returns Map key: uin value: sendTime - * @example - * let ret = await NTQQGroupApi.getGroupMemberLastestSendTime('123456'); - * for (let [uin, sendTime] of ret) { - * console.log(uin, sendTime); - * } - */ - static async getGroupMemberLastestSendTime(GroupCode: string) { - async function getdata(uid: string) { - let NTRet = await NTQQGroupApi.getLastestMsgByUids(GroupCode, [uid]); - if (NTRet.result != 0 && NTRet.msgList.length < 1) { - return undefined; - } - return { sendUin: NTRet.msgList[0].senderUin, sendTime: NTRet.msgList[0].msgTime } - } - let currentGroupMembers = groupMembers.get(GroupCode); - let PromiseData: Promise<({ - sendUin: string; - sendTime: string; - } | undefined)>[] = []; - let ret: Map = new Map(); - if (!currentGroupMembers) { - return ret; - } - for (let member of currentGroupMembers.values()) { - PromiseData.push(getdata(member.uid).catch(() => undefined)); - } - let allRet = await runAllWithTimeout(PromiseData, 2500); - for (let PromiseDo of allRet) { - if (PromiseDo) { - ret.set(PromiseDo.sendUin, PromiseDo.sendTime); - } - } - return ret; - } - static async getLastestMsgByUids(GroupCode: string, uids: string[]) { - let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', { - chatInfo: { - peerUid: GroupCode, - chatType: ChatType.group, - }, - filterMsgType: [], - filterSendersUid: uids, - filterMsgToTime: '0', - filterMsgFromTime: '0', - isReverseOrder: false, - isIncludeCurrent: true, - pageLimit: 1, - }); - return ret; - } - static async getGroupMemberAll(GroupCode: string, forced = false) { - return napCatCore.session.getGroupService().getAllMemberList(GroupCode, forced); - } - static async getLastestMsg(GroupCode: string, uins: string[]) { - let uids: Array = []; - for (let uin of uins) { - let uid = await NTQQUserApi.getUidByUin(uin) - if (uid) { - uids.push(uid); - } - } - let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', { - chatInfo: { - peerUid: GroupCode, - chatType: ChatType.group, - }, - filterMsgType: [], - filterSendersUid: uids, - filterMsgToTime: '0', - filterMsgFromTime: '0', - isReverseOrder: false, - isIncludeCurrent: true, - pageLimit: 1, - }); - return ret; - } - static async getGroupRecommendContactArkJson(GroupCode: string) { - return napCatCore.session.getGroupService().getGroupRecommendContactArkJson(GroupCode); - } - static async CreatGroupFileFolder(groupCode: string, folderName: string) { - return napCatCore.session.getRichMediaService().createGroupFolder(groupCode, folderName); - } - static async DelGroupFile(groupCode: string, files: string[]) { - return napCatCore.session.getRichMediaService().deleteGroupFile(groupCode, [102], files); - } - static async DelGroupFileFolder(groupCode: string, folderId: string) { - return napCatCore.session.getRichMediaService().deleteGroupFolder(groupCode, folderId); - } - static async addGroupEssence(GroupCode: string, msgId: string) { - // 代码没测过 - // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom - let MsgData = await napCatCore.session.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false); - let param = { - groupCode: GroupCode, - msgRandom: parseInt(MsgData.msgList[0].msgRandom), - msgSeq: parseInt(MsgData.msgList[0].msgSeq) - }; - // GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数 - return napCatCore.session.getGroupService().addGroupEssence(param); - } - static async removeGroupEssence(GroupCode: string, msgId: string) { - // 代码没测过 - // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom - let MsgData = await napCatCore.session.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false); - let param = { - groupCode: GroupCode, - msgRandom: parseInt(MsgData.msgList[0].msgRandom), - msgSeq: parseInt(MsgData.msgList[0].msgSeq) - }; - // GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数 - return napCatCore.session.getGroupService().removeGroupEssence(param); - } - static async getSingleScreenNotifies(num: number) { - let [_retData, _doubt, _seq, notifies] = await NTEventDispatch.CallNormalEvent - <(arg1: boolean, arg2: string, arg3: number) => Promise, (doubt: boolean, seq: string, notifies: GroupNotify[]) => void> - ( - 'NodeIKernelGroupService/getSingleScreenNotifies', - 'NodeIKernelGroupListener/onGroupSingleScreenNotifies', - 1, - 5000, - () => true, - false, - '', - num - ); - return notifies; - } - static async getGroupMemberV2(GroupCode: string, uid: string, forced = false) { - type ListenerType = NodeIKernelGroupListener['onMemberInfoChange']; - type EventType = NodeIKernelGroupService['getMemberInfo']; - // NTEventDispatch.CreatListenerFunction('NodeIKernelGroupListener/onGroupMemberInfoUpdate', - //return napCatCore.session.getGroupService().getMemberInfo(GroupCode, [uid], forced); - const [ret, _groupCode, _changeType, _members] = await NTEventDispatch.CallNormalEvent - - ( - 'NodeIKernelGroupService/getMemberInfo', - 'NodeIKernelGroupListener/onMemberInfoChange', - 1, - 5000, - (groupCode: string, changeType: number, members: Map) => { - return groupCode == GroupCode && members.has(uid); - }, - GroupCode, [uid], forced - ); - return _members.get(uid); - } - static async getGroupMembers(groupQQ: string, num = 3000): Promise> { - const groupService = napCatCore.session.getGroupService(); - const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow'); - const result = await groupService.getNextMemberList(sceneId!, undefined, num); - if (result.errCode !== 0) { - throw ('获取群成员列表出错,' + result.errMsg); - } - - //logDebug(`获取群(${groupQQ})成员列表结果:`, `finish: ${result.result.finish}`); //, Array.from(result.result.infos.values())); - return result.result.infos; - /* - console.log(sceneId); - const result = await napCatCore.getGroupService().getNextMemberList(sceneId, num); - console.log(result); - - return result; - */ - } - - static async getGroupNotifies() { - // 获取管理员变更 - // 加群通知,退出通知,需要管理员权限 - - } - static async GetGroupFileCount(Gids: Array) { - return napCatCore.session.getRichMediaService().batchGetGroupFileCount(Gids); - } - static async getGroupIgnoreNotifies() { - } - static async getArkJsonGroupShare(GroupCode: string) { - let ret = await NTEventDispatch.CallNoListenerEvent - <(GroupId: string) => Promise>( - 'NodeIKernelGroupService/getGroupRecommendContactArkJson', - 5000, - GroupCode - ); - return ret.arkJson; - } - //需要异常处理 - static async uploadGroupBulletinPic(GroupCode: string, imageurl: string) { - const _Pskey = (await NTQQUserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!; - return napCatCore.session.getGroupService().uploadGroupBulletinPic(GroupCode, _Pskey, imageurl); - } - static async handleGroupRequest(flag: string, operateType: GroupRequestOperateTypes, reason?: string) { - let flagitem = flag.split('|'); - let groupCode = flagitem[0]; - let seq = flagitem[1]; - let type = parseInt(flagitem[2]); - - return napCatCore.session.getGroupService().operateSysNotify( - false, - { - 'operateType': operateType, // 2 拒绝 - 'targetMsg': { - 'seq': seq, // 通知序列号 - 'type': type, - 'groupCode': groupCode, - 'postscript': reason || ' ' // 仅传空值可能导致处理失败,故默认给个空格 - } - }); - } - - static async quitGroup(groupQQ: string) { - return napCatCore.session.getGroupService().quitGroup(groupQQ); - } - - static async kickMember(groupQQ: string, kickUids: string[], refuseForever: boolean = false, kickReason: string = '') { - return napCatCore.session.getGroupService().kickMember(groupQQ, kickUids, refuseForever, kickReason); - } - - static async banMember(groupQQ: string, memList: Array<{ uid: string, timeStamp: number }>) { - // timeStamp为秒数, 0为解除禁言 - return napCatCore.session.getGroupService().setMemberShutUp(groupQQ, memList); - } - - static async banGroup(groupQQ: string, shutUp: boolean) { - return napCatCore.session.getGroupService().setGroupShutUp(groupQQ, shutUp); - } - - static async setMemberCard(groupQQ: string, memberUid: string, cardName: string) { - return napCatCore.session.getGroupService().modifyMemberCardName(groupQQ, memberUid, cardName); - } - - static async setMemberRole(groupQQ: string, memberUid: string, role: GroupMemberRole) { - return napCatCore.session.getGroupService().modifyMemberRole(groupQQ, memberUid, role); - } - - static async setGroupName(groupQQ: string, groupName: string) { - return napCatCore.session.getGroupService().modifyGroupName(groupQQ, groupName, false); - } - - // 头衔不可用 - static async setGroupTitle(groupQQ: string, uid: string, title: string) { - - } - - static async publishGroupBulletin(groupQQ: string, content: string, picInfo: { id: string, width: number, height: number } | undefined = undefined, pinned: number = 0, confirmRequired: number = 0,) { - const _Pskey = (await NTQQUserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com'); - //text是content内容url编码 - let data = { - text: encodeURI(content), - picInfo: picInfo, - oldFeedsId: '', - pinned: pinned, - confirmRequired: confirmRequired - }; - return napCatCore.session.getGroupService().publishGroupBulletin(groupQQ, _Pskey!, data); - } - static async getGroupRemainAtTimes(GroupCode: string) { - napCatCore.session.getGroupService().getGroupRemainAtTimes(GroupCode); - } - static async getMemberExtInfo(groupCode: string, uin: string) { - // 仅NTQQ 9.9.11 24568测试 容易炸开谨慎使用 - return napCatCore.session.getGroupService().getMemberExtInfo( - { - groupCode: groupCode, - sourceType: MemberExtSourceType.TITLETYPE, - beginUin: '0', - dataTime: '0', - uinList: [uin], - uinNum: '', - seq: '', - groupType: '', - richCardNameVer: '', - memberExtFilter: { - memberLevelInfoUin: 1, - memberLevelInfoPoint: 1, - memberLevelInfoActiveDay: 1, - memberLevelInfoLevel: 1, - memberLevelInfoName: 1, - levelName: 1, - dataTime: 1, - userShowFlag: 1, - sysShowFlag: 1, - timeToUpdate: 1, - nickName: 1, - specialTitle: 1, - levelNameNew: 1, - userShowFlagNew: 1, - msgNeedField: 1, - cmdUinFlagExt3Grocery: 1, - memberIcon: 1, - memberInfoSeq: 1 - } - } - ); - } -} \ No newline at end of file diff --git a/src/core/src/apis/index.ts b/src/core/src/apis/index.ts deleted file mode 100644 index 4c0619e3..00000000 --- a/src/core/src/apis/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './file'; -export * from './friend'; -export * from './group'; -export * from './msg'; -export * from './user'; -export * from './webapi'; -export * from './sign'; -export * from './system'; \ No newline at end of file diff --git a/src/core/src/apis/msg.ts b/src/core/src/apis/msg.ts deleted file mode 100644 index 53c9ba88..00000000 --- a/src/core/src/apis/msg.ts +++ /dev/null @@ -1,317 +0,0 @@ -import { GetFileListParam, Peer, RawMessage, SendMessageElement, SendMsgElementConstructor } from '@/core/entities'; -import { friends, groups, selfInfo } from '@/core/data'; -import { log, logWarn } from '@/common/utils/log'; -import { sleep } from '@/common/utils/helper'; -import { napCatCore, NTQQUserApi } from '@/core'; -import { onGroupFileInfoUpdateParamType } from '@/core/listeners'; -import { GeneralCallResult } from '@/core/services/common'; -import { MessageUnique } from '../../../common/utils/MessageUnique'; -import { NTEventDispatch } from '@/common/utils/EventTask'; -import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo'; - -async function LoadMessageIdList(Peer: Peer, msgId: string) { - let msgList = await NTQQMsgApi.getMsgHistory(Peer, msgId, 50); - for (let j = 0; j < msgList.msgList.length; j++) { - let shortId = MessageUnique.createMsg(Peer, msgList.msgList[j].msgId); - } -} -async function loadMessageUnique() { - if (groups.size > 100) { - logWarn('[性能检测] 群数量大于100,可能会导致性能问题'); - } - let predict = (groups.size + friends.size / 2) / 5; - predict = predict < 20 ? 20 : predict; - predict = predict > 50 ? 50 : predict; - //let waitpromise: Array> = []; - predict = Math.floor(predict * 50); - MessageUnique.resize(predict); - let RecentContact = await NTQQUserApi.getRecentContactListSnapShot(predict); - let LoadMessageIdDo: Array> = new Array>(); - if (RecentContact?.info?.changedList && RecentContact?.info?.changedList?.length > 0) { - for (let i = 0; i < RecentContact.info.changedList.length; i++) { - let Peer: Peer = { chatType: RecentContact.info.changedList[i].chatType, peerUid: RecentContact.info.changedList[i].peerUid, guildId: '' }; - LoadMessageIdDo.push(LoadMessageIdList(Peer, RecentContact.info.changedList[i].msgId)); - } - } - await Promise.all(LoadMessageIdDo).then(() => { - log(`[消息序列] 加载 ${predict} 条历史消息记录完成`); - }); -} - -setTimeout(() => { - napCatCore.onLoginSuccess(async () => { - await sleep(100); - // NTQQMsgApi.CheckSendMode().then().catch(); - loadMessageUnique().then().catch(); - //下面的代码还没摸清 不要使用 - //let data = await napCatCore.session.getMsgService().sendSsoCmdReqByContend("LightAppSvc.mini_app_growguard.ReportExecute","1124343"); - //console.log(data); - }); -}, 100); -//歇菜LocalMsg压根不写Db -// setTimeout(async () => { -// let ele: MessageElement = { extBufForUI: '0x', ...SendMsgElementConstructor.text('测试消息') }; -// let MsgId = await NTQQMsgApi.getMsgUniqueEx(); -// let peer = { chatType: 2, peerUid: '', guildId: '' }; -// console.log(await napCatCore.session.getTestPerformanceService().insertMsg( -// { -// peer: peer, -// msgTime: Math.floor(Date.now() / 1000).toString(), -// msgId: MsgId, -// msgSeq: '56564', -// batchNums: 1, -// timesPerBatch: 1, -// numPerTime: 1 -// }, [ele] -// )); -// console.log(await NTQQMsgApi.multiForwardMsg(peer, peer, [MsgId])); -// }, 25000) - -export class NTQQMsgApi { - static async FetchLongMsg(peer: Peer, msgId: string) { - return napCatCore.session.getMsgService().fetchLongMsg(peer, msgId); - } - static async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) { - //console.log(peer, msgSeq, emojiId, emojiType, count); - //注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa - return napCatCore.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, "", false, 20) - } - // static napCatCore: NapCatCore | null = null; - // enum BaseEmojiType { - // NORMAL_EMOJI, - // SUPER_EMOJI, - // RANDOM_SUPER_EMOJI, - // CHAIN_SUPER_EMOJI, - // EMOJI_EMOJI - // } - static async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) { - // nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览 - // nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid - // 其实以官方文档为准是最好的,https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType - emojiId = emojiId.toString(); - return napCatCore.session.getMsgService().setMsgEmojiLikes(peer, msgSeq, emojiId, emojiId.length > 3 ? '2' : '1', set); - } - static async getMultiMsg(peer: Peer, rootMsgId: string, parentMsgId: string): Promise { - return napCatCore.session.getMsgService().getMultiMsg(peer, rootMsgId, parentMsgId); - } - static async ForwardMsg(peer: Peer, msgIds: string[]) { - return napCatCore.session.getMsgService().forwardMsg(msgIds, peer, [peer], new Map()); - } - static async getLastestMsgByUids(peer: Peer, count: number = 20, isReverseOrder: boolean = false) { - let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', { - chatInfo: peer, - filterMsgType: [], - filterSendersUid: [], - filterMsgToTime: '0', - filterMsgFromTime: '0', - isReverseOrder: isReverseOrder,//此参数有点离谱 注意不是本次查询的排序 而是全部消历史信息的排序 默认false 从新消息拉取到旧消息 - isIncludeCurrent: true, - pageLimit: count, - }); - return ret; - } - static async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) { - if (!peer) throw new Error('peer is not allowed'); - if (!msgIds) throw new Error('msgIds is not allowed'); - //Mlikiowa: 参数不合规会导致NC异常崩溃 原因是TX未对进入参数判断 对应Android标记@NotNull AndroidJADX分析可得 - return await napCatCore.session.getMsgService().getMsgsByMsgId(peer, msgIds); - } - static async getSingleMsg(peer: Peer, seq: string) { - return await napCatCore.session.getMsgService().getSingleMsg(peer, seq); - } - static async fetchFavEmojiList(num: number) { - return napCatCore.session.getMsgService().fetchFavEmojiList("", num, true, true) - } - static async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) { - let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, { - chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa - filterMsgType: [], - filterSendersUid: [], - filterMsgToTime: '0', - filterMsgFromTime: '0', - isReverseOrder: false, - isIncludeCurrent: true, - pageLimit: 1, - }); - return ret; - } - static async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) { - return await napCatCore.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z); - } - static async setMsgRead(peer: Peer) { - return napCatCore.session.getMsgService().setMsgRead(peer); - } - static async getGroupFileList(GroupCode: string, params: GetFileListParam) { - let data = await NTEventDispatch.CallNormalEvent< - (GroupCode: string, params: GetFileListParam) => Promise, - (groupFileListResult: onGroupFileInfoUpdateParamType) => void - >( - 'NodeIKernelRichMediaService/getGroupFileList', - 'NodeIKernelMsgListener/onGroupFileInfoUpdate', - 1, - 5000, - (groupFileListResult: onGroupFileInfoUpdateParamType) => { - //Developer Mlikiowa Todo: 此处有问题 无法判断是否成功 - return true; - }, - GroupCode, - params - ); - return data[1].item; - } - static async getMsgHistory(peer: Peer, msgId: string, count: number, isReverseOrder: boolean = false) { - // 消息时间从旧到新 - return napCatCore.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, isReverseOrder); - } - static async recallMsg(peer: Peer, msgIds: string[]) { - await napCatCore.session.getMsgService().recallMsg({ - chatType: peer.chatType, - peerUid: peer.peerUid - }, msgIds); - } - static async sendMsgV2(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) { - function generateMsgId() { - const timestamp = Math.floor(Date.now() / 1000); - const random = Math.floor(Math.random() * Math.pow(2, 32)); - const buffer = Buffer.alloc(8); - buffer.writeUInt32BE(timestamp, 0); - buffer.writeUInt32BE(random, 4); - const msgId = BigInt("0x" + buffer.toString('hex')).toString(); - return msgId; - } - // 此处有采用Hack方法 利用数据返回正确得到对应消息 - // 与之前 Peer队列 MsgSeq队列 真正的MsgId并发不同 - // 谨慎采用 目前测试暂无问题 Developer.Mlikiowa - let msgId: string; - try { - msgId = await NTQQMsgApi.getMsgUnique(peer.chatType, await NTQQMsgApi.getServerTime()); - } catch (error) { - //if (!napCatCore.session.getMsgService()['generateMsgUniqueId']) - //兜底识别策略V2 - msgId = generateMsgId().toString(); - } - let data = await NTEventDispatch.CallNormalEvent< - (msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map) => Promise, - (msgList: RawMessage[]) => void - >( - 'NodeIKernelMsgService/sendMsg', - 'NodeIKernelMsgListener/onMsgInfoListUpdate', - 1, - timeout, - (msgRecords: RawMessage[]) => { - for (let msgRecord of msgRecords) { - if (msgRecord.msgId === msgId && msgRecord.sendStatus === 2) { - return true; - } - } - return false; - }, - msgId, - peer, - msgElements, - new Map() - ); - let retMsg = data[1].find(msgRecord => { - if (msgRecord.msgId === msgId) { - return true; - } - }); - return retMsg; - } - static sendMsgEx(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) { - //return NTQQMsgApi.sendMsgV1(peer, msgElements, waitComplete, timeout); - } - static async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) { - //唉? !我有个想法 - let msgId = await NTQQMsgApi.getMsgUnique(peer.chatType, await NTQQMsgApi.getServerTime()); - peer.guildId = msgId; - let data = await NTEventDispatch.CallNormalEvent< - (msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map) => Promise, - (msgList: RawMessage[]) => void - >( - 'NodeIKernelMsgService/sendMsg', - 'NodeIKernelMsgListener/onMsgInfoListUpdate', - 1, - timeout, - (msgRecords: RawMessage[]) => { - for (let msgRecord of msgRecords) { - if (msgRecord.guildId === msgId && msgRecord.sendStatus === 2) { - return true; - } - } - return false; - }, - "0", - peer, - msgElements, - new Map() - ); - let retMsg = data[1].find(msgRecord => { - if (msgRecord.guildId === msgId) { - return true; - } - }); - return retMsg; - } - static async getMsgUnique(chatType: number, time: string) { - if (requireMinNTQQBuild('26702')) { - return napCatCore.session.getMsgService().generateMsgUniqueId(chatType, time); - } - return napCatCore.session.getMsgService().getMsgUniqueId(time); - } - static async getServerTime() { - return napCatCore.session.getMSFService().getServerTime(); - } - static async getServerTimeV2() { - return NTEventDispatch.CallNoListenerEvent<() => string>('NodeIKernelMsgService/getServerTime', 5000); - } - static async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) { - return napCatCore.session.getMsgService().forwardMsg(msgIds, srcPeer, [destPeer], new Map()); - } - static async multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]): Promise { - const msgInfos = msgIds.map(id => { - return { msgId: id, senderShowName: selfInfo.nick }; - }); - let data = await NTEventDispatch.CallNormalEvent< - (msgInfo: typeof msgInfos, srcPeer: Peer, destPeer: Peer, comment: Array, attr: Map,) => Promise, - (msgList: RawMessage[]) => void - >( - 'NodeIKernelMsgService/multiForwardMsgWithComment', - 'NodeIKernelMsgListener/onMsgInfoListUpdate', - 1, - 5000, - (msgRecords: RawMessage[]) => { - for (let msgRecord of msgRecords) { - if (msgRecord.peerUid == destPeer.peerUid && msgRecord.senderUid == selfInfo.uid) { - return true; - } - } - return false; - }, - msgInfos, - srcPeer, - destPeer, - [], - new Map() - ); - for (let msg of data[1]) { - const arkElement = msg.elements.find(ele => ele.arkElement); - if (!arkElement) { - continue; - } - const forwardData: any = JSON.parse(arkElement.arkElement.bytesData); - if (forwardData.app != 'com.tencent.multimsg') { - continue; - } - if (msg.peerUid == destPeer.peerUid && msg.senderUid == selfInfo.uid) { - return msg; - } - } - throw new Error('转发消息超时'); - } - static async markallMsgAsRead() { - return napCatCore.session.getMsgService().setAllC2CAndGroupMsgRead(); - } -} diff --git a/src/core/src/apis/sign.ts b/src/core/src/apis/sign.ts deleted file mode 100644 index 8da3ab8e..00000000 --- a/src/core/src/apis/sign.ts +++ /dev/null @@ -1,308 +0,0 @@ -import { logDebug } from '@/common/utils/log'; -import { NTQQUserApi } from './user'; -import { selfInfo } from '../data'; -import { RequestUtil } from '@/common/utils/request'; -import { WebApi } from './webapi'; -import { checkFileReceived, checkFileReceived2, uri2local } from '@/common/utils/file'; -import fs from 'node:fs' -import { sleep } from '@/common/utils/helper'; -export interface IdMusicSignPostData { - type: 'qq' | '163', - id: string | number, -} - -export interface CustomMusicSignPostData { - type: 'custom', - url: string, - audio: string, - title: string, - image?: string, - singer?: string -} -// let t = await napCatCore.session.getGroupService().shareDigest({ -// appId: "100497308", -// appType: 1, -// msgStyle: 0, -// recvUin: "726067488", -// sendType: 1, -// clientInfo: { -// platform: 1 -// }, -// richMsg: { -// usingArk: true, -// title: "Bot测试title", -// summary: "Bot测试summary", -// url: "https://www.bilibili.com", -// pictureUrl: "https://y.qq.com/music/photo_new/T002R300x300M0000035DC6W4ZpSqf_1.jpg?max_age=2592000", -// brief: "Bot测试brief", -// } -// }); -// { -// errCode: 0, -// errMsg: '', -// rsp: { -// sendType: 1, -// recvUin: '726067488', -// recvOpenId: '', -// errCode: 901501, -// errMsg: 'imagent service_error:150_OIDB_NO_PRIV', -// extInfo: { -// wording: '消息下发失败(错误码:901501)', -// jumpResult: 0, -// jumpUrl: '', -// level: 0, -// subLevel: 0, -// developMsg: 'imagent error' -// } -// } -// } - -// export class MusicSign { -// private readonly url: string; - -// constructor(url: string) { -// this.url = url; -// } - -// sign(postData: CustomMusicSignPostData | IdMusicSignPostData): Promise { -// return new Promise((resolve, reject) => { -// fetch(this.url, { -// method: 'POST', // 指定请求方法为 POST -// headers: { -// 'Content-Type': 'application/json' // 设置请求头,指明发送的数据类型为 JSON -// }, -// body: JSON.stringify(postData) // 将 JavaScript 对象转换为 JSON 字符串作为请求体 -// }) -// .then(response => { -// if (!response.ok) { -// reject(response.statusText); // 请求失败,返回错误信息 -// } -// return response.json(); // 解析 JSON 格式的响应体 -// }) -// .then(data => { -// logDebug('音乐消息生成成功', data); -// resolve(data); -// }) -// .catch(error => { -// reject(error); -// }); -// }); -// } -// } -export interface MiniAppLuaJsonType { - prompt: string, - title: string, - preview: string, - jumpUrl: string, - tag: string, - tagIcon: string, - source: string, - sourcelogo: string, -} -export async function SignMiniApp(CardData: MiniAppLuaJsonType) { - // { - // "app": "com.tencent.miniapp.lua", - // "bizsrc": "tianxuan.imgJumpArk", - // "view": "miniapp", - // "prompt": "hi! 这里有我的日常故事,只想讲给你听", - // "config": { - // "type": "normal", - // "forward": 1, - // "autosize": 0 - // }, - // "meta": { - // "miniapp": { - // "title": "hi! 这里有我的日常故事,只想讲给你听", - // "preview": "https:\/\/tianquan.gtimg.cn\/qqAIAgent\/item\/7\/square.png", - // "jumpUrl": "https:\/\/club.vip.qq.com\/transfer?open_kuikly_info=%7B%22version%22%3A%20%221%22%2C%22src_type%22%3A%20%22web%22%2C%22kr_turbo_display%22%3A%20%221%22%2C%22page_name%22%3A%20%22vas_ai_persona_moments%22%2C%22bundle_name%22%3A%20%22vas_ai_persona_moments%22%7D&page_name=vas_ai_persona_moments&enteranceId=share&robot_uin=3889008584", - // "tag": "QQ智能体", - // "tagIcon": "https:\/\/tianquan.gtimg.cn\/shoal\/qqAIAgent\/3e9d70c9-d98c-45b8-80b4-79d82971b514.png", - // "source": "QQ智能体", - // "sourcelogo": "https:\/\/tianquan.gtimg.cn\/shoal\/qqAIAgent\/3e9d70c9-d98c-45b8-80b4-79d82971b514.png" - // } - // } - // } - - // token : function(url,skey){ - // var str = skey || cookie('skey') || cookie('rv2') || '', - // hash = 5381; - // if(url){ - // var hostname = uri(url).hostname; - // if(hostname.indexOf('qun.qq.com') > -1 || (hostname.indexOf('qzone.qq.com') > -1 && hostname.indexOf('qun.qzone.qq.com') === -1)){ - // str = cookie('p_skey') || str; - // } - // } - // for(var i = 0, len = str.length; i < len; ++i){ - // hash += (hash << 5) + str.charAt(i).charCodeAt(); - // } - // return hash & 0x7fffffff; - // }, - // - - // function signToken(skey: string) { - // let hash = 5381; - // for (let i = 0, len = skey.length; i < len; ++i) { - // hash += (hash << 5) + skey.charCodeAt(i); - // } - // return hash & 0x7fffffff; - // } - let signCard = { - "app": "com.tencent.miniapp.lua", - "bizsrc": "tianxuan.imgJumpArk", - "view": "miniapp", - "prompt": CardData.prompt, - "config": { - "type": "normal", - "forward": 1, - "autosize": 0 - }, - "meta": { - "miniapp": { - "title": CardData.title, - "preview": (CardData.preview as string).replace(/\\/g, "\\/\\/"), - "jumpUrl": (CardData.jumpUrl as string).replace(/\\/g, "\\/\\/"), - "tag": CardData.tag, - "tagIcon": (CardData.tagIcon as string).replace(/\\/g, "\\/\\/"), - "source": CardData.source, - "sourcelogo": (CardData.sourcelogo as string).replace(/\\/g, "\\/\\/") - } - } - }; - // let signCard = { - // "app": "com.tencent.eventshare.lua", - // "prompt": "Bot Test", - // "bizsrc": "tianxuan.business", - // "meta": { - // "eventshare": { - // "button1URL": "https://www.bilibili.com", - // "button1disable": false, - // "button1title": "点我前往", - // "button2URL": "", - // "button2disable": false, - // "button2title": "", - // "buttonNum": 1, - // "jumpURL": "https://www.bilibili.com", - // "preview": "https://tianquan.gtimg.cn/shoal/card/9930bc4e-4a92-4da3-814f-8094a2421d9c.png", - // "tag": "QQ集卡", - // "tagIcon": "https://tianquan.gtimg.cn/shoal/card/c034854b-102d-40be-a545-5ca90a7c49c9.png", - // "title": "Bot Test" - // } - // }, - // "config": { - // "autosize": 0, - // "collect": 0, - // "ctime": 1716568575, - // "forward": 1, - // "height": 336, - // "reply": 0, - // "round": 1, - // "type": "normal", - // "width": 263 - // }, - // "view": "eventshare", - // "ver": "0.0.0.1" - // }; - let data = (await NTQQUserApi.getQzoneCookies()); - const Bkn = WebApi.genBkn(data.p_skey); - - const CookieValue = 'p_skey=' + data.p_skey + '; skey=' + data.skey + '; p_uin=o' + selfInfo.uin + '; uin=o' + selfInfo.uin; - - let signurl = "https://h5.qzone.qq.com/v2/vip/tx/trpc/ark-share/GenNewSignedArk?g_tk=" + Bkn + "&ark=" + encodeURIComponent(JSON.stringify(signCard)); - let signed_ark = ""; - try { - let retData = await RequestUtil.HttpGetJson<{ code: number, data: { signed_ark: string } }>(signurl, 'GET', undefined, { Cookie: CookieValue }); - //logDebug('MiniApp JSON 消息生成成功', retData); - signed_ark = retData.data.signed_ark; - } catch (error) { - logDebug('MiniApp JSON 消息生成失败', error); - } - return signed_ark; -} -export async function SignMusicInternal(songname: string, singer: string, cover: string, songmid: string, songmusic: string) { - //curl -X POST 'https://mqq.reader.qq.com/api/mqq/share/card?accessToken&_csrfToken&source=c0003' -H 'Content-Type: application/json' -H 'Cookie: uin=o10086' -d '{"app":"com.tencent.qqreader.share","config":{"ctime":1718634110,"forward":1,"token":"9a63343c32d5a16bcde653eb97faa25d","type":"normal"},"extra":{"app_type":1,"appid":100497308,"msg_seq":14386738075403815000.0,"uin":1733139081},"meta":{"music":{"action":"","android_pkg_name":"","app_type":1,"appid":100497308,"ctime":1718634110,"desc":"周杰伦","jumpUrl":"https://i.y.qq.com/v8/playsong.html?songmid=0039MnYb0qxYhV&type=0","musicUrl":"http://ws.stream.qqmusic.qq.com/http://isure6.stream.qqmusic.qq.com/M800002202B43Cq4V4.mp3?fromtag=810033622&guid=br_xzg&trace=23fe7bcbe2336bbf&uin=553&vkey=CF0F5CE8B0FA16F3001F8A88D877A217EB5E4F00BDCEF1021EB6C48969CA33C6303987AEECE9CC840122DD2F917A59D6130D8A8CA4577C87","preview":"https://y.qq.com/music/photo_new/T002R800x800M000000MkMni19ClKG.jpg","cover":"https://y.qq.com/music/photo_new/T002R800x800M000000MkMni19ClKG.jpg","sourceMsgId":"0","source_icon":"https://p.qpic.cn/qqconnect/0/app_100497308_1626060999/100?max-age=2592000&t=0","source_url":"","tag":"QQ音乐","title":"晴天","uin":10086}},"prompt":"[分享]晴天","ver":"0.0.0.1","view":"music"}' - let signurl = 'https://mqq.reader.qq.com/api/mqq/share/card?accessToken&_csrfToken&source=c0003'; - //let = "https://y.qq.com/music/photo_new/T002R800x800M000000MkMni19ClKG.jpg"; - let signCard = { - app: "com.tencent.qqreader.share", - config: { - ctime: 1718634110, - forward: 1, - token: "9a63343c32d5a16bcde653eb97faa25d", - type: "normal" - }, - extra: { - app_type: 1, - appid: 100497308, - msg_seq: 14386738075403815000.0, - uin: 1733139081 - }, - meta: { - music: - { - action: "", - android_pkg_name: "", - app_type: 1, - appid: 100497308, - ctime: 1718634110, - desc: singer, - jumpUrl: "https://i.y.qq.com/v8/playsong.html?songmid=" + songmid + "&type=0", - musicUrl: songmusic, - preview: cover, - cover: cover, - sourceMsgId: "0", - source_icon: "https://p.qpic.cn/qqconnect/0/app_100497308_1626060999/100?max-age=2592000&t=0", - source_url: "", - tag: "QQ音乐", - title: songname, - uin: 10086 - } - }, - prompt: "[分享]" + songname, - ver: "0.0.0.1", - view: "music" - } - //console.log(JSON.stringify(signCard, null, 2)); - let data = await RequestUtil.HttpGetJson<{ code: number, data: { arkResult: string } }> - (signurl, 'POST', signCard, { 'Cookie': 'uin=o10086', 'Content-Type': 'application/json' }); - return data; -} -//注意处理错误 -export async function CreateMusicThridWay0(id: string = '', mid: string = '') { - if (mid == '') { - let MusicInfo = await RequestUtil.HttpGetJson - <{ songinfo?: { data?: { track_info: { mid: string } } } }> - ( - 'https://u.y.qq.com/cgi-bin/musicu.fcg?format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0&data={"comm":{"ct":24,"cv":0},"songinfo":{"method":"get_song_detail_yqq","param":{"song_type":0,"song_mid":"","song_id":' + id + '},"module":"music.pf_song_detail_svr"}}', - 'GET', - undefined - ); - mid = MusicInfo.songinfo?.data?.track_info.mid!; - } - //第三方接口 存在速率限制 现在勉强用 - let MusicReal = await RequestUtil.HttpGetJson - <{ code: number, data?: { name: string, singer: string, url: string, cover: string } }> - ('https://api.leafone.cn/api/qqmusic?id=' + mid + '&type=8', 'GET', undefined); - //console.log(MusicReal); - return { ...MusicReal.data, mid: mid }; -} -export async function CreateMusicThridWay1(id: string = '', mid: string = '') { - -} -//转换外域名为 https://qq.ugcimg.cn/v1/cpqcbu4b8870i61bde6k7cbmjgejq8mr3in82qir4qi7ielffv5slv8ck8g42novtmev26i233ujtuab6tvu2l2sjgtupfr389191v00s1j5oh5325j5eqi40774jv1i/khovifoh7jrqd6eahoiv7koh8o -//https://cgi.connect.qq.com/qqconnectopen/openapi/change_image_url?url=https://th.bing.com/th?id=OSK.b8ed36f1fb1889de6dc84fd81c187773&w=46&h=46&c=11&rs=1&qlt=80&o=6&dpr=2&pid=SANGAM - -//外域名不行得走qgroup中转 -//https://proxy.gtimg.cn/tx_tls_gate=y.qq.com/music/photo_new/T002R800x800M000000y5gq7449K9I.jpg - -//可外域名 -//https://pic.ugcimg.cn/500955bdd6657ecc8e82e02d2df06800/jpg1 - -//QQ音乐gtimg接口 -//https://y.gtimg.cn/music/photo_new/T002R800x800M000000y5gq7449K9I.jpg?max_age=2592000 - -//还有一处公告上传可以上传高质量图片 持久为qq域名 -export async function SignMusicWrapper(id: string = '') { - let MusicInfo = await CreateMusicThridWay0(id)!; - let MusicCard = await SignMusicInternal(MusicInfo.name!, MusicInfo.singer!, MusicInfo.cover!, MusicInfo.mid!, "https://ws.stream.qqmusic.qq.com/" + MusicInfo.url!); - return MusicCard; -} \ No newline at end of file diff --git a/src/core/src/apis/system.ts b/src/core/src/apis/system.ts deleted file mode 100644 index 52d3f997..00000000 --- a/src/core/src/apis/system.ts +++ /dev/null @@ -1,35 +0,0 @@ - - -import { NTEventDispatch } from '@/common/utils/EventTask'; -import { GeneralCallResult, NTQQFileApi, NTQQUserApi, napCatCore } from '@/core'; -export class NTQQSystemApi { - static async hasOtherRunningQQProcess() { - return napCatCore.util.hasOtherRunningQQProcess(); - } - static async ORCImage(filePath: string) { - return napCatCore.session.getNodeMiscService().wantWinScreenOCR(filePath); - } - static async translateEnWordToZn(words: string[]) { - return napCatCore.session.getRichMediaService().translateEnWordToZn(words); - } - //调用会超时 没灯用 (好像是通知listener的) onLineDev - static async getOnlineDev() { - return napCatCore.session.getMsgService().getOnLineDev(); - } - //1-2-162b9b42-65b9-4405-a8ed-2e256ec8aa50 - static async getArkJsonCollection(cid: string) { - let ret = await NTEventDispatch.CallNoListenerEvent - <(cid: string) => Promise>( - 'NodeIKernelCollectionService/collectionArkShare', - 5000, - '1717662698058' - ); - return ret; - } - static async BootMiniApp(appfile: string, params: string) { - await napCatCore.session.getNodeMiscService().setMiniAppVersion('2.16.4'); - let c = await napCatCore.session.getNodeMiscService().getMiniAppPath(); - - return napCatCore.session.getNodeMiscService().startNewMiniApp(appfile, params); - } -} \ No newline at end of file diff --git a/src/core/src/apis/user.ts b/src/core/src/apis/user.ts deleted file mode 100644 index 0446c108..00000000 --- a/src/core/src/apis/user.ts +++ /dev/null @@ -1,357 +0,0 @@ -import { ModifyProfileParams, SelfInfo, User, UserDetailInfoByUin, UserDetailInfoByUinV2 } from '@/core/entities'; -import { friends, groupMembers, selfInfo } from '@/core/data'; -import { CacheClassFuncAsync, CacheClassFuncAsyncExtend } from '@/common/utils/helper'; -import { napCatCore, NTQQFriendApi } from '@/core'; -import { NodeIKernelProfileListener, ProfileListener } from '@/core/listeners'; -import { RequestUtil } from '@/common/utils/request'; -import { logWarn } from '@/common/utils/log'; -import { NTEventDispatch } from '@/common/utils/EventTask'; -import { NodeIKernelProfileService, ProfileBizType, UserDetailSource } from '@/core/services'; -import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo'; - -export class NTQQUserApi { - static async getProfileLike(uid: string) { - return napCatCore.session.getProfileLikeService().getBuddyProfileLike({ - friendUids: [ - uid - ], - basic: 1, - vote: 1, - favorite: 0, - userProfile: 1, - type: 2, - start: 0, - limit: 20 - }); - } - static async setLongNick(longNick: string) { - return napCatCore.session.getProfileService().setLongNick(longNick); - } - static async setSelfOnlineStatus(status: number, extStatus: number, batteryStatus: number) { - return napCatCore.session.getMsgService().setStatus({ status: status, extStatus: extStatus, batteryStatus: batteryStatus }); - } - static async getBuddyRecommendContactArkJson(uin: string, sencenID = '') { - return napCatCore.session.getBuddyService().getBuddyRecommendContactArkJson(uin, sencenID); - } - static async like(uid: string, count = 1): Promise<{ result: number, errMsg: string, succCounts: number }> { - return napCatCore.session.getProfileLikeService().setBuddyProfileLike({ - friendUid: uid, - sourceId: 71, - doLikeCount: count, - doLikeTollCount: 0 - }); - } - - static async setQQAvatar(filePath: string) { - type setQQAvatarRet = { result: number, errMsg: string }; - const ret = await napCatCore.session.getProfileService().setHeader(filePath) as setQQAvatarRet; - return { result: ret?.result, errMsg: ret?.errMsg }; - } - static async setGroupAvatar(gc: string, filePath: string) { - return napCatCore.session.getGroupService().setHeader(gc, filePath); - } - - static async fetchUserDetailInfos(uids: string[]) { - //26702 以上使用新接口 .Dev Mlikiowa - type EventService = NodeIKernelProfileService['fetchUserDetailInfo']; - type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged']; - let retData: User[] = []; - let [_retData, _retListener] = await NTEventDispatch.CallNormalEvent - - ( - 'NodeIKernelProfileService/fetchUserDetailInfo', - 'NodeIKernelProfileListener/onUserDetailInfoChanged', - uids.length, - 5000, - (profile) => { - if (uids.includes(profile.uid)) { - let RetUser: User = { - ...profile.simpleInfo.coreInfo, - ...profile.simpleInfo.status, - ...profile.simpleInfo.vasInfo, - ...profile.commonExt, - ...profile.simpleInfo.baseInfo, - qqLevel: profile.commonExt.qqLevel, - pendantId: "" - }; - retData.push(RetUser); - return true; - } - return false; - }, - "BuddyProfileStore", - uids, - UserDetailSource.KSERVER, - [ - ProfileBizType.KALL - ] - ); - - return retData; - } - static async fetchUserDetailInfo(uid: string) { - type EventService = NodeIKernelProfileService['fetchUserDetailInfo']; - type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged']; - let [_retData, profile] = await NTEventDispatch.CallNormalEvent - - ( - 'NodeIKernelProfileService/fetchUserDetailInfo', - 'NodeIKernelProfileListener/onUserDetailInfoChanged', - 1, - 5000, - (profile) => { - if (profile.uid === uid) { - return true; - } - return false; - }, - "BuddyProfileStore", - [ - uid - ], - UserDetailSource.KSERVER, - [ - ProfileBizType.KALL - ] - ); - let RetUser: User = { - ...profile.simpleInfo.coreInfo, - ...profile.simpleInfo.status, - ...profile.simpleInfo.vasInfo, - ...profile.commonExt, - ...profile.simpleInfo.baseInfo, - qqLevel: profile.commonExt.qqLevel, - pendantId: "" - }; - return RetUser; - } - static async getUserDetailInfo(uid: string) { - if (requireMinNTQQBuild('26702')) { - return this.fetchUserDetailInfo(uid); - } - return this.getUserDetailInfoOld(uid); - } - static async getUserDetailInfoOld(uid: string) { - type EventService = NodeIKernelProfileService['getUserDetailInfoWithBizInfo']; - type EventListener = NodeIKernelProfileListener['onProfileDetailInfoChanged']; - let [_retData, profile] = await NTEventDispatch.CallNormalEvent - - ( - 'NodeIKernelProfileService/getUserDetailInfoWithBizInfo', - 'NodeIKernelProfileListener/onProfileDetailInfoChanged', - 2, - 5000, - (profile: User) => { - if (profile.uid === uid) { - return true; - } - return false; - }, - uid, - [0] - ); - return profile; - } - static async modifySelfProfile(param: ModifyProfileParams) { - return napCatCore.session.getProfileService().modifyDesktopMiniProfile(param); - } - //需要异常处理 - @CacheClassFuncAsync(1800 * 1000) - static async getCookies(domain: string) { - const ClientKeyData = await NTQQUserApi.forceFetchClientKey(); - const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + selfInfo.uin + '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + selfInfo.uin + '%2Finfocenter&keyindex=19%27' - let cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl); - return cookies; - } - @CacheClassFuncAsync(1800 * 1000) - static async getPSkey(domainList: string[]) { - return await napCatCore.session.getTipOffService().getPskey(domainList, true); - } - static async getRobotUinRange(): Promise> { - const robotUinRanges = await napCatCore.session.getRobotService().getRobotUinRange({ - justFetchMsgConfig: '1', - type: 1, - version: 0, - aioKeywordVersion: 0 - }); - // console.log(robotUinRanges?.response?.robotUinRanges); - return robotUinRanges?.response?.robotUinRanges; - } - //需要异常处理 - @CacheClassFuncAsync(1800 * 1000) - static async getQzoneCookies() { - const ClientKeyData = await NTQQUserApi.forceFetchClientKey(); - const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + selfInfo.uin + '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2Fuser.qzone.qq.com%2F' + selfInfo.uin + '%2Finfocenter&keyindex=19%27' - let cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl); - return cookies; - } - //需要异常处理 - @CacheClassFuncAsync(1800 * 1000) - static async getSkey(): Promise { - const ClientKeyData = await NTQQUserApi.forceFetchClientKey(); - if (ClientKeyData.result !== 0) { - throw new Error('getClientKey Error'); - } - const clientKey = ClientKeyData.clientKey; - const keyIndex = ClientKeyData.keyIndex; - const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + selfInfo.uin + '&clientkey=' + clientKey + '&u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=19%27'; - let cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl); - const skey = cookies['skey']; - if (!skey) { - throw new Error('getSkey Skey is Empty'); - } - return skey; - } - @CacheClassFuncAsyncExtend(3600 * 1000, 'Uin2Uid', (Uin: string, Uid: string | undefined) => { - if (Uid && Uid.indexOf('u_') != -1) { - return true - } - logWarn("uin转换到uid时异常", Uin, Uid); - return false; - }) - static async getUidByUin(Uin: string) { - //此代码仅临时使用,后期会被废弃 - if (requireMinNTQQBuild('26702')) { - return await NTQQUserApi.getUidByUinV2(Uin); - } - return await NTQQUserApi.getUidByUinV1(Uin); - } - @CacheClassFuncAsyncExtend(3600 * 1000, 'Uid2Uin', (Uid: string | undefined, Uin: number | undefined) => { - if (Uin && Uin != 0 && !isNaN(Uin)) { - return true - } - logWarn("uid转换到uin时异常", Uid, Uin); - return false; - }) - static async getUinByUid(Uid: string) { - //此代码仅临时使用,后期会被废弃 - if (requireMinNTQQBuild('26702')) { - return await NTQQUserApi.getUinByUidV2(Uid); - } - return await NTQQUserApi.getUinByUidV1(Uid); - } - - //后期改成流水线处理 - static async getUidByUinV2(Uin: string) { - let uid = (await napCatCore.session.getProfileService().getUidByUin('FriendsServiceImpl', [Uin])).get(Uin); - if (uid) return uid; - uid = (await napCatCore.session.getGroupService().getUidByUins([Uin])).uids.get(Uin); - if (uid) return uid; - uid = (await napCatCore.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin); - if (uid) return uid; - console.log((await NTQQFriendApi.getBuddyIdMapCache(true))); - uid = (await NTQQFriendApi.getBuddyIdMapCache(true)).getValue(Uin);//从Buddy缓存获取Uid - if (uid) return uid; - uid = (await NTQQFriendApi.getBuddyIdMap(true)).getValue(Uin); - if (uid) return uid; - let unveifyUid = (await NTQQUserApi.getUserDetailInfoByUinV2(Uin)).detail.uid;//从QQ Native 特殊转换 - if (unveifyUid.indexOf("*") == -1) uid = unveifyUid; - //if (uid) return uid; - return uid; - } - //后期改成流水线处理 - static async getUinByUidV2(Uid: string) { - let uin = (await napCatCore.session.getProfileService().getUinByUid('FriendsServiceImpl', [Uid])).get(Uid); - if (uin) return uin; - uin = (await napCatCore.session.getGroupService().getUinByUids([Uid])).uins.get(Uid); - if (uin) return uin; - uin = (await napCatCore.session.getUixConvertService().getUin([Uid])).uinInfo.get(Uid); - if (uin) return uin; - uin = (await NTQQFriendApi.getBuddyIdMapCache(true)).getKey(Uid);//从Buddy缓存获取Uin - if (uin) return uin; - uin = (await NTQQFriendApi.getBuddyIdMap(true)).getKey(Uid); - if (uin) return uin; - uin = (await NTQQUserApi.getUserDetailInfo(Uid)).uin; //从QQ Native 转换 - return uin; - } - - static async getUidByUinV1(Uin: string) { - // 通用转换开始尝试 - let uid = (await napCatCore.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin); - // Uid 好友转 - if (!uid) { - Array.from(friends.values()).forEach((t) => { - if (t.uin == Uin) { - uid = t.uid; - } - }); - } - //Uid 群友列表转 - if (!uid) { - for (let groupMembersList of groupMembers.values()) { - for (let GroupMember of groupMembersList.values()) { - if (GroupMember.uin == Uin) { - uid = GroupMember.uid; - } - } - } - } - if (!uid) { - let unveifyUid = (await NTQQUserApi.getUserDetailInfoByUin(Uin)).info.uid;//从QQ Native 特殊转换 方法三 - if (unveifyUid.indexOf("*") == -1) { - uid = unveifyUid; - } - } - return uid; - } - static async getUinByUidV1(Uid: string) { - let ret = await NTEventDispatch.CallNoListenerEvent - <(Uin: string[]) => Promise<{ uinInfo: Map }>>( - 'NodeIKernelUixConvertService/getUin', - 5000, - [Uid] - ); - let uin = ret.uinInfo.get(Uid); - if (!uin) { - //从Buddy缓存获取Uin - Array.from(friends.values()).forEach((t) => { - if (t.uid == Uid) { - uin = t.uin; - } - }) - } - if (!uin) { - uin = (await NTQQUserApi.getUserDetailInfo(Uid)).uin; //从QQ Native 转换 - } - - // if (!uin) { - // uin = (await NTQQFriendApi.getFriends(false)).find((t) => { t.uid == Uid })?.uin; //从QQ Native 缓存转换 - // } - // if (!uin) { - // uin = (await NTQQFriendApi.getFriends(true)).find((t) => { t.uid == Uid })?.uin; //从QQ Native 非缓存转换 - // } - return uin; - } - static async getRecentContactListSnapShot(count: number) { - return await napCatCore.session.getRecentContactService().getRecentContactListSnapShot(count); - } - static async getRecentContactListSyncLimit(count: number) { - return await napCatCore.session.getRecentContactService().getRecentContactListSyncLimit(count); - } - static async getRecentContactListSync() { - return await napCatCore.session.getRecentContactService().getRecentContactListSync(); - } - static async getRecentContactList() { - return await napCatCore.session.getRecentContactService().getRecentContactList(); - } - static async getUserDetailInfoByUinV2(Uin: string) { - return await NTEventDispatch.CallNoListenerEvent - <(Uin: string) => Promise>( - 'NodeIKernelProfileService/getUserDetailInfoByUin', - 5000, - Uin - ); - } - static async getUserDetailInfoByUin(Uin: string) { - return NTEventDispatch.CallNoListenerEvent - <(Uin: string) => Promise>( - 'NodeIKernelProfileService/getUserDetailInfoByUin', - 5000, - Uin - ); - } - @CacheClassFuncAsync(3600 * 1000, 'ClientKey') - static async forceFetchClientKey() { - return await napCatCore.session.getTicketService().forceFetchClientKey(''); - } -} diff --git a/src/core/src/apis/webapi.ts b/src/core/src/apis/webapi.ts deleted file mode 100644 index 0b859ae0..00000000 --- a/src/core/src/apis/webapi.ts +++ /dev/null @@ -1,367 +0,0 @@ -import { selfInfo } from '@/core/data'; -import { log, logDebug } from '@/common/utils/log'; -import { NTQQUserApi } from './user'; -import { RequestUtil } from '@/common/utils/request'; -import { CacheClassFuncAsync } from '@/common/utils/helper'; -export enum WebHonorType { - ALL = 'all', - TALKACTIVE = 'talkative', - PERFROMER = 'performer', - LEGEND = 'legend', - STORONGE_NEWBI = 'strong_newbie', - EMOTION = 'emotion' -} -export interface WebApiGroupMember { - uin: number - role: number - g: number - join_time: number - last_speak_time: number - lv: { - point: number - level: number - } - card: string - tags: string - flag: number - nick: string - qage: number - rm: number -} -interface WebApiGroupMemberRet { - ec: number - errcode: number - em: string - cache: number - adm_num: number - levelname: any - mems: WebApiGroupMember[] - count: number - svr_time: number - max_count: number - search_count: number - extmode: number -} -export interface WebApiGroupNoticeFeed { - u: number//发送者 - fid: string//fid - pubt: number//时间 - msg: { - text: string - text_face: string - title: string, - pics?: { - id: string, - w: string, - h: string - }[] - } - type: number - fn: number - cn: number - vn: number - settings: { - is_show_edit_card: number - remind_ts: number - tip_window_type: number - confirm_required: number - } - read_num: number - is_read: number - is_all_confirm: number -} -export interface WebApiGroupNoticeRet { - ec: number - em: string - ltsm: number - srv_code: number - read_only: number - role: number - feeds: WebApiGroupNoticeFeed[] - group: { - group_id: number - class_ext: number - } - sta: number, - gln: number - tst: number, - ui: any - server_time: number - svrt: number - ad: number -} -interface GroupEssenceMsg { - group_code: string - msg_seq: number - msg_random: number - sender_uin: string - sender_nick: string - sender_time: number - add_digest_uin: string - add_digest_nick: string - add_digest_time: number - msg_content: any[] - can_be_removed: true -} -export interface GroupEssenceMsgRet { - retcode: number - retmsg: string - data: { - msg_list: GroupEssenceMsg[] - is_end: boolean - group_role: number - config_page_url: string - } -} -export class WebApi { - static async shareDigest(groupCode: string, msgSeq: string, msgRandom: string, targetGroupCode: string) { - const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = WebApi.genBkn(CookiesObject.skey); - let ret: any = undefined; - const data = 'group_code=' + groupCode + '&msg_seq=' + msgSeq + '&msg_random=' + msgRandom + '&target_group_code=' + targetGroupCode; - const url = 'https://qun.qq.com/cgi-bin/group_digest/share_digest?bkn=' + Bkn + "&" + data; - //console.log(url); - try { - ret = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': CookieValue }); - return ret; - } catch (e) { - return undefined; - } - return undefined; - } - @CacheClassFuncAsync(3600 * 1000, 'webapi_get_group_members') - static async getGroupEssenceMsg(GroupCode: string, page_start: string) { - const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = WebApi.genBkn(CookiesObject.skey); - const url = 'https://qun.qq.com/cgi-bin/group_digest/digest_list?bkn=' + Bkn + '&group_code=' + GroupCode + '&page_start=' + page_start + '&page_limit=20'; - let ret; - try { - ret = await RequestUtil.HttpGetJson(url, 'GET', '', { 'Cookie': CookieValue }); - } catch { - return undefined; - } - //console.log(url, CookieValue); - if (ret.retcode !== 0) { - return undefined; - } - return ret; - } - @CacheClassFuncAsync(3600 * 1000, 'webapi_get_group_members') - static async getGroupMembers(GroupCode: string, cached: boolean = true): Promise { - //logDebug('webapi 获取群成员', GroupCode); - let MemberData: Array = new Array(); - try { - const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = WebApi.genBkn(CookiesObject.skey); - const retList: Promise[] = []; - const fastRet = await RequestUtil.HttpGetJson('https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?st=0&end=40&sort=1&gc=' + GroupCode + '&bkn=' + Bkn, 'POST', '', { 'Cookie': CookieValue }); - if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) { - return []; - } else { - for (const key in fastRet.mems) { - MemberData.push(fastRet.mems[key]); - } - } - //初始化获取PageNum - const PageNum = Math.ceil(fastRet.count / 40); - //遍历批量请求 - for (let i = 2; i <= PageNum; i++) { - const ret: Promise = RequestUtil.HttpGetJson('https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?st=' + (i - 1) * 40 + '&end=' + i * 40 + '&sort=1&gc=' + GroupCode + '&bkn=' + Bkn, 'POST', '', { 'Cookie': CookieValue }); - retList.push(ret); - } - //批量等待 - for (let i = 1; i <= PageNum; i++) { - const ret = await (retList[i]); - if (!ret?.count || ret?.errcode !== 0 || !ret?.mems) { - continue; - } - for (const key in ret.mems) { - MemberData.push(ret.mems[key]); - } - } - } catch { - return MemberData; - } - return MemberData; - } - // public static async addGroupDigest(groupCode: string, msgSeq: string) { - // const url = `https://qun.qq.com/cgi-bin/group_digest/cancel_digest?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&msg_seq=${msgSeq}&msg_random=444021292`; - // const res = await this.request(url); - // return await res.json(); - // } - - // public async getGroupDigest(groupCode: string) { - // const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&page_start=0&page_limit=20`; - // const res = await this.request(url); - // return await res.json(); - // } - static async setGroupNotice(GroupCode: string, Content: string = '') { - //https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?bkn=${bkn} - //qid=${群号}&bkn=${bkn}&text=${内容}&pinned=0&type=1&settings={"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1} - - const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = WebApi.genBkn(CookiesObject.skey); - let ret: any = undefined; - const data = 'qid=' + GroupCode + '&bkn=' + Bkn + '&text=' + Content + '&pinned=0&type=1&settings={"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}'; - const url = 'https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?bkn=' + Bkn; - try { - ret = await RequestUtil.HttpGetJson(url, 'GET', '', { 'Cookie': CookieValue }); - return ret; - } catch (e) { - return undefined; - } - return undefined; - } - static async getGrouptNotice(GroupCode: string): Promise { - const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = WebApi.genBkn(CookiesObject.skey); - let ret: WebApiGroupNoticeRet | undefined = undefined; - //console.log(CookieValue); - const url = 'https://web.qun.qq.com/cgi-bin/announce/get_t_list?bkn=' + Bkn + '&qid=' + GroupCode + '&ft=23&ni=1&n=1&i=1&log_read=1&platform=1&s=-1&n=20'; - try { - ret = await RequestUtil.HttpGetJson(url, 'GET', '', { 'Cookie': CookieValue }); - if (ret?.ec !== 0) { - return undefined; - } - return ret; - } catch (e) { - return undefined; - } - return undefined; - } - static genBkn(sKey: string) { - sKey = sKey || ''; - let hash = 5381; - - for (let i = 0; i < sKey.length; i++) { - const code = sKey.charCodeAt(i); - hash = hash + (hash << 5) + code; - } - - return (hash & 0x7FFFFFFF).toString(); - } - - @CacheClassFuncAsync(3600 * 1000, 'GroupHonorInfo') - static async getGroupHonorInfo(groupCode: string, getType: WebHonorType) { - const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = WebApi.genBkn(CookiesObject.skey); - async function getDataInternal(Internal_groupCode: string, Internal_type: number) { - let url = 'https://qun.qq.com/interactive/honorlist?gc=' + Internal_groupCode + '&type=' + Internal_type.toString(); - let res = ''; - let resJson; - try { - res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': CookieValue }); - const match = res.match(/window\.__INITIAL_STATE__=(.*?);/); - if (match) { - resJson = JSON.parse(match[1].trim()); - } - if (Internal_type === 1) { - return resJson?.talkativeList; - } else { - return resJson?.actorList; - } - } catch (e) { - logDebug('获取当前群荣耀失败', url, e); - } - return undefined; - } - - let HonorInfo: any = { group_id: groupCode }; - - if (getType === WebHonorType.TALKACTIVE || getType === WebHonorType.ALL) { - try { - let RetInternal = await getDataInternal(groupCode, 1); - if (!RetInternal) { - throw new Error('获取龙王信息失败'); - } - HonorInfo.current_talkative = { - user_id: RetInternal[0]?.uin, - avatar: RetInternal[0]?.avatar, - nickname: RetInternal[0]?.name, - day_count: 0, - description: RetInternal[0]?.desc - } - HonorInfo.talkative_list = []; - for (const talkative_ele of RetInternal) { - HonorInfo.talkative_list.push({ - user_id: talkative_ele?.uin, - avatar: talkative_ele?.avatar, - description: talkative_ele?.desc, - day_count: 0, - nickname: talkative_ele?.name - }); - } - } catch (e) { - logDebug(e); - } - } - if (getType === WebHonorType.PERFROMER || getType === WebHonorType.ALL) { - try { - let RetInternal = await getDataInternal(groupCode, 2); - if (!RetInternal) { - throw new Error('获取群聊之火失败'); - } - HonorInfo.performer_list = []; - for (const performer_ele of RetInternal) { - HonorInfo.performer_list.push({ - user_id: performer_ele?.uin, - nickname: performer_ele?.name, - avatar: performer_ele?.avatar, - description: performer_ele?.desc - }); - } - } catch (e) { - logDebug(e); - } - } - if (getType === WebHonorType.PERFROMER || getType === WebHonorType.ALL) { - try { - let RetInternal = await getDataInternal(groupCode, 3); - if (!RetInternal) { - throw new Error('获取群聊炽焰失败'); - } - HonorInfo.legend_list = []; - for (const legend_ele of RetInternal) { - HonorInfo.legend_list.push({ - user_id: legend_ele?.uin, - nickname: legend_ele?.name, - avatar: legend_ele?.avatar, - desc: legend_ele?.description - }); - } - } catch (e) { - logDebug('获取群聊炽焰失败', e); - } - } - if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) { - try { - let RetInternal = await getDataInternal(groupCode, 6); - if (!RetInternal) { - throw new Error('获取快乐源泉失败'); - } - HonorInfo.emotion_list = []; - for (const emotion_ele of RetInternal) { - HonorInfo.emotion_list.push({ - user_id: emotion_ele?.uin, - nickname: emotion_ele?.name, - avatar: emotion_ele?.avatar, - desc: emotion_ele?.description - }); - } - } catch (e) { - logDebug('获取快乐源泉失败', e); - } - } - //冒尖小春笋好像已经被tx扬了 - if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) { - HonorInfo.strong_newbie_list = []; - } - return HonorInfo; - } -} diff --git a/src/core/src/core.ts b/src/core/src/core.ts deleted file mode 100644 index 76af9759..00000000 --- a/src/core/src/core.ts +++ /dev/null @@ -1,484 +0,0 @@ -import QQWrapper, { NodeIQQNTWrapperEngine, NodeIQQNTWrapperSession, NodeQQNTWrapperUtil } from '@/core/wrapper'; -import { DeviceList } from '@/onebot11/main'; -import { - NodeIKernelLoginService, - NodeIKernelBuddyService, - QuickLoginResult, passwordLoginArgType -} from '@/core/services'; -import { - BuddyListener, - GroupListener, - LoginListener, MsgListener, - ProfileListener, SessionListener -} from '@/core/listeners'; -import { DependsAdapter, DispatcherAdapter, GlobalAdapter, NodeIGlobalAdapter } from '@/core/adapters'; -import path from 'node:path'; -import os from 'node:os'; -import fs from 'node:fs'; -import { getFullQQVesion, QQVersionAppid, QQVersionQua, requireMinNTQQBuild } from '@/common/utils/QQBasicInfo'; -import { hostname, systemVersion } from '@/common/utils/system'; -import { genSessionConfig } from '@/core/sessionConfig'; -import { sleep } from '@/common/utils/helper'; -import crypto from 'node:crypto'; -import { groupMembers, groups, selfInfo, stat } from '@/core/data'; -import { GroupMember, RawMessage } from '@/core/entities'; -import { NTEventDispatch } from '@/common/utils/EventTask'; -import { - enableConsoleLog, - enableFileLog, - log, - logDebug, - logError, - setLogLevel, - setLogSelfInfo -} from '@/common/utils/log'; -import { napCatConfig } from '@/core/utils/config'; -import { NTQQFriendApi } from './apis'; - -export interface OnLoginSuccess { - (uin: string, uid: string): void | Promise; -} - - -export class NapCatCore { - public readonly session: NodeIQQNTWrapperSession; - public readonly util: NodeQQNTWrapperUtil; - public readonly engine: NodeIQQNTWrapperEngine; - private readonly loginListener: LoginListener; - - private loginService: NodeIKernelLoginService; - private onLoginSuccessFuncList: OnLoginSuccess[] = []; - - private proxyHandler = { - get(target: any, prop: any, receiver: any) { - // console.log('get', prop, typeof target[prop]); - if (typeof target[prop] === 'undefined') { - // 如果方法不存在,返回一个函数,这个函数调用existentMethod - return (...args: unknown[]) => { - logDebug(`${target.constructor.name} has no method ${prop}`); - }; - } - // 如果方法存在,正常返回 - return Reflect.get(target, prop, receiver); - } - }; - - constructor() { - this.engine = new QQWrapper.NodeIQQNTWrapperEngine(); - this.util = new QQWrapper.NodeQQNTWrapperUtil(); - this.loginService = new QQWrapper.NodeIKernelLoginService(); - this.session = new QQWrapper.NodeIQQNTWrapperSession(); - this.loginListener = new LoginListener(); - this.loginListener.onUserLoggedIn = (userid: string) => { - logError('当前账号(' + userid + ')已登录,无法重复登录'); - }; - this.initConfig(); - this.loginListener.onQRCodeLoginSucceed = (arg) => { - this.initSession(arg.uin, arg.uid).then((r) => { - selfInfo.uin = arg.uin; - selfInfo.uid = arg.uid; - napCatConfig.read(); - setLogLevel(napCatConfig.fileLogLevel, napCatConfig.consoleLogLevel); - enableFileLog(napCatConfig.fileLog); - enableConsoleLog(napCatConfig.consoleLog); - setLogSelfInfo(selfInfo); - const dataPath = path.resolve(this.dataPath, './NapCat/data'); - fs.mkdirSync(dataPath, { recursive: true }); - logDebug('本账号数据/缓存目录:', dataPath); - this.initDataListener(); - this.onLoginSuccessFuncList.map(cb => { - new Promise((resolve, reject) => { - const result = cb(arg.uin, arg.uid); - if (result instanceof Promise) { - result.then(resolve).catch(reject); - } - }).then(); - }); - }).catch((e) => { - logError('initSession failed', e); - throw new Error(`启动失败: ${JSON.stringify(e)}`); - }); - }; - // todo: 登录失败处理 - this.loginListener.onQRCodeSessionFailed = (errType: number, errCode: number, errMsg: string) => { - logError('登录失败(onQRCodeSessionFailed)', errMsg); - if (errType == 1 && errCode == 3) { - // 二维码过期刷新 - } - this.loginService.getQRCodePicture(); - }; - this.loginListener.onLoginFailed = (args) => { - logError('登录失败(onLoginFailed)', args); - }; - - this.loginListener = new Proxy(this.loginListener, this.proxyHandler); - // 初始化流程:initConfig, login, initSession, loginSuccess | initDataListener - this.loginService.addKernelLoginListener(new QQWrapper.NodeIKernelLoginListener(this.loginListener)); - } - - get dataPath(): string { - let result = this.util.getNTUserDataInfoConfig(); - if (!result) { - result = path.resolve(os.homedir(), './.config/QQ'); - fs.mkdirSync(result, { recursive: true }); - } - return result; - } - - get dataPathGlobal(): string { - return path.resolve(this.dataPath, './nt_qq/global'); - } - - private initConfig() { - this.engine.initWithDeskTopConfig({ - base_path_prefix: '', - platform_type: 3, - app_type: 4, - app_version: getFullQQVesion(), - os_version: 'Windows 10 Pro', - use_xlog: true, - qua: QQVersionQua, - global_path_config: { - desktopGlobalPath: this.dataPathGlobal, - }, - thumb_config: { maxSide: 324, minSide: 48, longLimit: 6, density: 2 } - }, new QQWrapper.NodeIGlobalAdapter(new GlobalAdapter())); - this.loginService.initConfig({ - machineId: '', - appid: QQVersionAppid, - platVer: systemVersion, - commonPath: this.dataPathGlobal, - clientVer: getFullQQVesion(), - hostName: hostname - }); - } - - private initSession(uin: string, uid: string): Promise { - return new Promise(async (res, rej) => { - - const sessionConfig = await genSessionConfig(uin, uid, this.dataPath); - const sessionListener = new SessionListener(); - sessionListener.onSessionInitComplete = (r: unknown) => { - if ((r as number) === 0) { - return res(0); - } - rej(r); - }; - // const oldOnSendOidbRepl = this.session.onSendOidbRepl; - // this.session.onSendOidbRepl = (...args: unknown[]) => { - // console.log('onSendOidbRepl', args); - // return oldOnSendOidbRepl(...args); - // }; - this.session.init(sessionConfig, - new QQWrapper.NodeIDependsAdapter(new DependsAdapter()), - new QQWrapper.NodeIDispatcherAdapter(new DispatcherAdapter()), - new QQWrapper.NodeIKernelSessionListener(sessionListener) - ); - try { - this.session.startNT(0); - } catch (__) { /* Empty */ - try { - this.session.startNT(); - } catch (e) { - rej('init failed ' + e); - } - } - }); - } - private initDataListener() { - // 消息相关 - interface LineDevice { - instanceId: number - clientType: number - devUid: string - } - interface KickedOffLineInfo { - appId: number - instanceId: number - sameDevice: boolean - tipsDesc: string - tipsTitle: string - kickedType: number - securityKickedType: number - } - const msgListener = new MsgListener(); - msgListener.onLineDev = (Devices: LineDevice[]) => { - DeviceList.splice(0, DeviceList.length); - Devices.map((Device: LineDevice) => { - let DeviceData = { - app_id: Device.devUid, - device_name: Device.clientType.toString(), - device_kind: Device.clientType.toString(), - }; - DeviceList.push(DeviceData); - // if (Device.clientType === 2) { - // log('账号设备(' + Device.devUid + ') 在线状态变更'); - // } - }); - }; - msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => { - // 下线通知 - log('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc); - }; - // msgListener.onMsgInfoListUpdate = (msgInfoList: RawMessage[]) => { - // stat.packet_received += 1; - // msgInfoList.map(msg => { - // console.log("onMsgInfoListUpdate", msg); - // if (msg.recallTime === '0') { // 不是撤回消息才入库/更新 - // dbUtil.addMsg(msg).then().catch(); - // } - // else { - // // 撤回的消息 - // dbUtil.getMsgByLongId(msg.msgId).then(existMsg => { - // if (existMsg) { - // existMsg.recallTime = msg.recallTime; - // dbUtil.updateMsg(existMsg).then(); - // } - // }); - // } - // }); - // }; - msgListener.onAddSendMsg = (msg: RawMessage) => { - stat.packet_sent += 1; - stat.message_sent += 1; - stat.last_message_time = Math.floor(Date.now() / 1000); - }; - msgListener.onRecvMsg = (msgList: RawMessage[]) => { - // console.log(JSON.stringify(msgList[0],null,2)); - stat.packet_received += 1; - stat.message_received += msgList.length; - stat.last_message_time = Math.floor(Date.now() / 1000); - }; - msgListener.onRecvSysMsg = (...args) => { - stat.packet_received += 1; - }; - this.addListener(msgListener); - // 好友相关 - const buddyListener = new BuddyListener(); - - - this.addListener(buddyListener); - // 刷新一次好友列表 26702版本以下需要手动刷新一次获取 高版本NTQQ自带缓存 - if (!requireMinNTQQBuild('26702')) { - this.session.getBuddyService().getBuddyList(true).then(arg => { - // console.log('getBuddyList', arg); - }); - } else { - // NTQQFriendApi.getBuddyV2(true).then((res) => { - // res.forEach((item) => { - // CachedIdMap.set(item.uid!, item.uin!); - // }); - // }).catch(); - } - interface SelfStatusInfo { - uid: string - status: number - extStatus: number - termType: number - netType: number - iconType: number - customStatus: any - setTime: string - } - const profileListener = new ProfileListener(); - profileListener.onProfileDetailInfoChanged = (profile) => { - if (profile.uid === selfInfo.uid) { - Object.assign(selfInfo, profile); - } - }; - profileListener.onSelfStatusChanged = (Info: SelfStatusInfo) => { - // if (Info.status == 20) { - // log("账号状态变更为离线") - // } - }; - this.addListener(profileListener); - - // 群相关 - const groupListener = new GroupListener(); - groupListener.onGroupListUpdate = (updateType, groupList) => { - // console.log("onGroupListUpdate", updateType, groupList) - groupList.map(g => { - const existGroup = groups.get(g.groupCode); - //群成员数量变化 应该刷新缓存 - if (existGroup && g.memberCount === existGroup.memberCount) { - Object.assign(existGroup, g); - } - else { - groups.set(g.groupCode, g); - // 获取群成员 - } - const sceneId = this.session.getGroupService().createMemberListScene(g.groupCode, 'groupMemberList_MainWindow'); - this.session.getGroupService().getNextMemberList(sceneId!, undefined, 3000).then(r => { - // console.log(`get group ${g.groupCode} members`, r); - // r.result.infos.forEach(member => { - // }); - // groupMembers.set(g.groupCode, r.result.infos); - }); - }); - }; - groupListener.onMemberListChange = (arg) => { - // todo: 应该加一个内部自己维护的成员变动callback,用于判断成员变化通知 - const groupCode = arg.sceneId.split('_')[0]; - if (groupMembers.has(groupCode)) { - const existMembers = groupMembers.get(groupCode)!; - arg.infos.forEach((member, uid) => { - //console.log('onMemberListChange', member); - const existMember = existMembers.get(uid); - if (existMember) { - Object.assign(existMember, member); - } - else { - existMembers!.set(uid, member); - } - //移除成员 - if (member.isDelete) { - existMembers.delete(uid); - } - }); - } - else { - groupMembers.set(groupCode, arg.infos); - } - // console.log('onMemberListChange', groupCode, arg); - }; - groupListener.onMemberInfoChange = (groupCode, changeType, members) => { - //console.log('onMemberInfoChange', groupCode, changeType, members); - if (changeType === 0 && members.get(selfInfo.uid)?.isDelete) { - // 自身退群或者被踢退群 5s用于Api操作 之后不再出现 - setTimeout(() => { - groups.delete(groupCode); - }, 5000); - - } - const existMembers = groupMembers.get(groupCode); - if (existMembers) { - members.forEach((member, uid) => { - const existMember = existMembers.get(uid); - if (existMember) { - // 检查管理变动 - member.isChangeRole = this.checkAdminEvent(groupCode, member, existMember); - // 更新成员信息 - Object.assign(existMember, member); - } - else { - existMembers.set(uid, member); - } - //移除成员 - if (member.isDelete) { - existMembers.delete(uid); - } - }); - } - else { - groupMembers.set(groupCode, members); - } - }; - this.addListener(groupListener); - } - - addListener( - listener: BuddyListener | GroupListener | MsgListener | ProfileListener - ): number { - // 根据listener的类型,找到对应的service,然后调用addListener方法 - // logDebug('addListener', listener.constructor.name); - - // proxy listener,调用 listener 不存在的方法时不会报错 - - listener = new Proxy(listener, this.proxyHandler); - switch (listener.constructor.name) { - case 'BuddyListener': { - return this.session.getBuddyService().addKernelBuddyListener(new QQWrapper.NodeIKernelBuddyListener(listener as BuddyListener)); - } - case 'GroupListener': { - return this.session.getGroupService().addKernelGroupListener(new QQWrapper.NodeIKernelGroupListener(listener as GroupListener)); - } - case 'MsgListener': { - return this.session.getMsgService().addKernelMsgListener(new QQWrapper.NodeIKernelMsgListener(listener as MsgListener)); - } - case 'ProfileListener': { - return this.session.getProfileService().addKernelProfileListener(new QQWrapper.NodeIKernelProfileListener(listener as ProfileListener)); - } - default: - return -1; - } - } - - onLoginSuccess(func: OnLoginSuccess) { - NTEventDispatch.init({ - ListenerMap: QQWrapper, - WrapperSession: this.session, - }); - this.onLoginSuccessFuncList.push(func); - } - - async quickLogin(uin: string): Promise { - const loginList = await this.loginService.getLoginList(); - - if (loginList.result !== 0) throw new Error('没有可快速登录的QQ号'); - const currentLogin = loginList.LocalLoginInfoList.find((item) => item.uin === uin); - if (!currentLogin || !currentLogin?.isQuickLogin) throw new Error(`${uin}快速登录不可用`); - - await sleep(1000); - const loginRet = await this.loginService.quickLoginWithUin(uin); - if (!loginRet.result) { - throw new Error('快速登录失败 ' + loginRet.loginErrorInfo.errMsg); - } - return loginRet; - } - - async qrLogin(cb: (url: string, base64: string, buffer: Buffer) => Promise) { - return new Promise<{ url: string, base64: string, buffer: Buffer }>((resolve, reject) => { - this.loginListener.onQRCodeGetPicture = (arg) => { - const base64Data = arg.pngBase64QrcodeData.split('data:image/png;base64,')[1]; - const buffer = Buffer.from(base64Data, 'base64'); - cb(arg.qrcodeUrl, arg.pngBase64QrcodeData, buffer); - }; - this.loginService.getQRCodePicture(); - }); - } - - async passwordLogin(uin: string, password: string, proofSig?: string, proofRand?: string, proofSid?: string) { - const passwordMd5 = crypto.createHash('md5').update(password).digest('hex'); - const loginArg: passwordLoginArgType = { - uin, - passwordMd5, - step: proofSig && proofRand && proofSid ? 1 : 0, - newDeviceLoginSig: '', - proofWaterSig: proofSig || '', - proofWaterRand: proofRand || '', - proofWaterSid: proofSid || '' - }; - - await this.loginService.getLoginList(); - await sleep(1000); - - const ret = await this.loginService.passwordLogin(loginArg); - - switch (ret.result) { - case '0': { // Success - break; - } - case '140022008': { // CAPTCHA required - break; - } - case '4': // Mobile verify required - case '140022013': // Incorrect password - default: - } - } - async getQuickLoginList() { - const loginList = await this.loginService.getLoginList(); - return loginList; - } - checkAdminEvent(groupCode: string, memberNew: GroupMember, memberOld: GroupMember | undefined): boolean { - if (memberNew.role !== memberOld?.role) { - log(`群 ${groupCode} ${memberNew.nick} 角色变更为 ${memberNew.role === 3 ? '管理员' : '群员'}`); - return true; - } - return false; - } -} - -export const napCatCore = new NapCatCore(); - - diff --git a/src/core/src/data.ts b/src/core/src/data.ts deleted file mode 100644 index edeb662d..00000000 --- a/src/core/src/data.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { - type Friend, - type Group, - type GroupMember, - type SelfInfo, - type BuddyCategoryType, - FriendV2 -} from './entities'; -import { isNumeric } from '@/common/utils/helper'; -import { LimitedHashTable } from '@/common/utils/MessageUnique'; -import { NTQQGroupApi } from '@/core/apis'; - -export const selfInfo: SelfInfo = { - uid: '', - uin: '', - nick: '', - online: true -}; -export const groups: Map = new Map(); - -export function deleteGroup(groupQQ: string) { - groups.delete(groupQQ); - groupMembers.delete(groupQQ); -} - -// 群号 -> 群成员map(uid=>GroupMember) -export const groupMembers: Map> = new Map>(); - -export const friends: Map = new Map(); - -//转换列表 -//export const CachedIdMap = new LimitedHashTable(1000); - -export async function getGroup(qq: string | number): Promise { - let group = groups.get(qq.toString()); - if (!group) { - try { - const _groups = await NTQQGroupApi.getGroups(); - if (_groups.length) { - _groups.forEach(g => { - groups.set(g.groupCode, g); - }); - } - } catch (e) { - return undefined; - } - } - group = groups.get(qq.toString()); - return group; -} - -export async function getGroupMember(groupQQ: string | number, memberUinOrUid: string | number) { - groupQQ = groupQQ.toString(); - memberUinOrUid = memberUinOrUid.toString(); - let members = groupMembers.get(groupQQ); - if (!members) { - try { - members = await NTQQGroupApi.getGroupMembers(groupQQ); - // 更新群成员列表 - groupMembers.set(groupQQ, members); - } - catch (e) { - return null; - } - } - // log('getGroupMember', members); - const getMember = () => { - let member: GroupMember | undefined = undefined; - if (isNumeric(memberUinOrUid)) { - member = Array.from(members!.values()).find(member => member.uin === memberUinOrUid); - } else { - member = members!.get(memberUinOrUid); - } - return member; - }; - let member = getMember(); - if (!member) { - members = await NTQQGroupApi.getGroupMembers(groupQQ); - member = getMember(); - } - return member; -} -// 考虑优化 移入QQ缓存或使用Api直接获取 -export const tempGroupCodeMap: Record = {}; // peerUid => 群号 - -// 保留 需要频繁读写 -export const stat = { - packet_received: 0, - packet_sent: 0, - message_received: 0, - message_sent: 0, - last_message_time: 0, - // 以下字段无用, 全部为0 - disconnect_times: 0, - lost_times: 0, - packet_lost: 0, -}; diff --git a/src/core/src/entities/cache.ts b/src/core/src/entities/cache.ts deleted file mode 100644 index 8c53d1b0..00000000 --- a/src/core/src/entities/cache.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { ChatType } from './msg'; - -export interface CacheScanResult { - result: number; - size: [ // 单位为字节 - string, // 系统总存储空间 - string, // 系统可用存储空间 - string, // 系统已用存储空间 - string, // QQ总大小 - string, // 「聊天与文件」大小 - string, // 未知 - string, // 「缓存数据」大小 - string, // 「其他数据」大小 - string, // 未知 - ] -} - -export interface ChatCacheList { - pageCount: number; - infos: ChatCacheListItem[] -}; - -export interface ChatCacheListItem { - chatType: ChatType; - basicChatCacheInfo: ChatCacheListItemBasic; - guildChatCacheInfo: unknown[]; // TODO: 没用过频道所以不知道这里边的详细内容 -} - -export interface ChatCacheListItemBasic { - chatSize: string; - chatTime: string; - uid: string; - uin: string; - remarkName: string; - nickName: string; - chatType?: ChatType; - isChecked?: boolean; -} - -export enum CacheFileType { - IMAGE = 0, - VIDEO = 1, - AUDIO = 2, - DOCUMENT = 3, - OTHER = 4, -} - -export interface CacheFileList { - infos: CacheFileListItem[], -} - -export interface CacheFileListItem { - fileSize: string; - fileTime: string; - fileKey: string; - elementId: string; - elementIdStr: string; - fileType: CacheFileType; - path: string; - fileName: string; - senderId: string; - previewPath: string; - senderName: string; - isChecked?: boolean; -} diff --git a/src/core/src/entities/constructor.ts b/src/core/src/entities/constructor.ts deleted file mode 100644 index 44b6c2d2..00000000 --- a/src/core/src/entities/constructor.ts +++ /dev/null @@ -1,404 +0,0 @@ -import { - AtType, - ElementType, FaceIndex, FaceType, PicElement, - PicType, - SendArkElement, - SendFaceElement, - SendFileElement, SendMarkdownElement, SendMarketFaceElement, - SendPicElement, - SendPttElement, - SendReplyElement, - sendShareLocationElement, - SendTextElement, - SendVideoElement, - viedo_type -} from './index'; -import { promises as fs } from 'node:fs'; -import ffmpeg from 'fluent-ffmpeg'; -import { NTQQFileApi } from '@/core/apis/file'; -import { calculateFileMD5, isGIF } from '@/common/utils/file'; -import { log, logDebug, logError } from '@/common/utils/log'; -import { defaultVideoThumb, getVideoInfo } from '@/common/utils/video'; -import { encodeSilk } from '@/common/utils/audio'; -import { isNull } from '@/common/utils/helper'; -import faceConfig from './face_config.json'; -import * as pathLib from 'node:path'; -import { SignMiniApp } from '../apis'; - -export const mFaceCache = new Map(); // emojiId -> faceName - - -export class SendMsgElementConstructor { - static location(): sendShareLocationElement { - return { - elementType: ElementType.SHARELOCATION, - elementId: '', - shareLocationElement: { - text: "测试", - ext: "" - } - } - } - static text(content: string): SendTextElement { - return { - elementType: ElementType.TEXT, - elementId: '', - textElement: { - content, - atType: AtType.notAt, - atUid: '', - atTinyId: '', - atNtUid: '', - }, - }; - } - - static at(atUid: string, atNtUid: string, atType: AtType, atName: string): SendTextElement { - return { - elementType: ElementType.TEXT, - elementId: '', - textElement: { - content: `@${atName}`, - atType, - atUid, - atTinyId: '', - atNtUid, - }, - }; - } - - static reply(msgSeq: string, msgId: string, senderUin: string, senderUinStr: string): SendReplyElement { - return { - elementType: ElementType.REPLY, - elementId: '', - replyElement: { - replayMsgSeq: msgSeq, // raw.msgSeq - replayMsgId: msgId, // raw.msgId - senderUin: senderUin, - senderUinStr: senderUinStr, - } - }; - } - - static async pic(picPath: string, summary: string = '', subType: 0 | 1 = 0): Promise { - const { md5, fileName, path, fileSize } = await NTQQFileApi.uploadFile(picPath, ElementType.PIC, subType); - if (fileSize === 0) { - throw '文件异常,大小为0'; - } - const imageSize = await NTQQFileApi.getImageSize(picPath); - const picElement: any = { - md5HexStr: md5, - fileSize: fileSize.toString(), - picWidth: imageSize?.width, - picHeight: imageSize?.height, - fileName: fileName, - sourcePath: path, - original: true, - picType: isGIF(picPath) ? PicType.gif : PicType.jpg, - picSubType: subType, - fileUuid: '', - fileSubId: '', - thumbFileSize: 0, - summary - }; - //logDebug('图片信息', picElement); - return { - elementType: ElementType.PIC, - elementId: '', - picElement, - }; - } - - static async file(filePath: string, fileName: string = '', folderId: string = ''): Promise { - const { md5, fileName: _fileName, path, fileSize } = await NTQQFileApi.uploadFile(filePath, ElementType.FILE); - if (fileSize === 0) { - throw '文件异常,大小为0'; - } - const element: SendFileElement = { - elementType: ElementType.FILE, - elementId: '', - fileElement: { - fileName: fileName || _fileName, - folderId: folderId, - 'filePath': path!, - 'fileSize': (fileSize).toString(), - } - }; - - return element; - } - - static async video(filePath: string, fileName: string = '', diyThumbPath: string = '', videotype: viedo_type = viedo_type.VIDEO_FORMAT_MP4): Promise { - const { fileName: _fileName, path, fileSize, md5 } = await NTQQFileApi.uploadFile(filePath, ElementType.VIDEO); - if (fileSize === 0) { - throw '文件异常,大小为0'; - } - let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`); - thumb = pathLib.dirname(thumb); - // log("thumb 目录", thumb) - let videoInfo = { - width: 1920, height: 1080, - time: 15, - format: 'mp4', - size: fileSize, - filePath - }; - try { - videoInfo = await getVideoInfo(path); - //logDebug('视频信息', videoInfo); - } catch (e) { - logError('获取视频信息失败', e); - } - const createThumb = new Promise((resolve, reject) => { - const thumbFileName = `${md5}_0.png`; - const thumbPath = pathLib.join(thumb, thumbFileName); - ffmpeg(filePath) - .on('end', () => { - }) - .on('error', (err) => { - logDebug('获取视频封面失败,使用默认封面', err); - if (diyThumbPath) { - fs.copyFile(diyThumbPath, thumbPath).then(() => { - resolve(thumbPath); - }).catch(reject); - } else { - fs.writeFile(thumbPath, defaultVideoThumb).then(() => { - resolve(thumbPath); - }).catch(reject); - } - }) - .screenshots({ - timestamps: [0], - filename: thumbFileName, - folder: thumb, - size: videoInfo.width + 'x' + videoInfo.height - }).on('end', () => { - resolve(thumbPath); - }); - }); - const thumbPath = new Map(); - const _thumbPath = await createThumb; - const thumbSize = (await fs.stat(_thumbPath)).size; - // log("生成缩略图", _thumbPath) - thumbPath.set(0, _thumbPath); - const thumbMd5 = await calculateFileMD5(_thumbPath); - const element: SendVideoElement = { - elementType: ElementType.VIDEO, - elementId: '', - videoElement: { - fileName: fileName || _fileName, - filePath: path, - videoMd5: md5, - thumbMd5, - fileTime: videoInfo.time, - thumbPath: thumbPath, - thumbSize, - thumbWidth: videoInfo.width, - thumbHeight: videoInfo.height, - fileSize: '' + fileSize, - //fileFormat: videotype - // fileUuid: "", - // transferStatus: 0, - // progress: 0, - // invalidState: 0, - // fileSubId: "", - // fileBizId: null, - // originVideoMd5: "", - // fileFormat: 2, - // import_rich_media_context: null, - // sourceVideoCodecFormat: 2 - } - }; - return element; - } - - static async ptt(pttPath: string): Promise { - const { converted, path: silkPath, duration } = await encodeSilk(pttPath); - // log("生成语音", silkPath, duration); - if (!silkPath) { - throw '语音转换失败, 请检查语音文件是否正常'; - } - const { md5, fileName, path, fileSize } = await NTQQFileApi.uploadFile(silkPath!, ElementType.PTT); - if (fileSize === 0) { - throw '文件异常,大小为0'; - } - if (converted) { - fs.unlink(silkPath).then(); - } - return { - elementType: ElementType.PTT, - elementId: '', - pttElement: { - fileName: fileName, - filePath: path, - md5HexStr: md5, - fileSize: fileSize, - // duration: Math.max(1, Math.round(fileSize / 1024 / 3)), // 一秒钟大概是3kb大小, 小于1秒的按1秒算 - duration: duration || 1, - formatType: 1, - voiceType: 1, - voiceChangeType: 0, - canConvert2Text: true, - waveAmplitudes: [ - 0, 18, 9, 23, 16, 17, 16, 15, 44, 17, 24, 20, 14, 15, 17, - ], - fileSubId: '', - playState: 1, - autoConvertText: 0, - } - }; - } - // NodeIQQNTWrapperSession sendMsg [ - // "0", - // { - // "peerUid": "u_e_RIxgTs2NaJ68h0PwOPSg", - // "chatType": 1, - // "guildId": "" - // }, - // [ - // { - // "elementId": "0", - // "elementType": 6, - // "faceElement": { - // "faceIndex": 0, - // "faceType": 5, - // "msgType": 0, - // "pokeType": 1, - // "pokeStrength": 0 - // } - // } - // ], - // {} - // ] - static face(faceId: number): SendFaceElement { - // 从face_config.json中获取表情名称 - const sysFaces = faceConfig.sysface; - const emojiFaces = faceConfig.emoji; - const face: any = sysFaces.find((face) => face.QSid === faceId.toString()); - faceId = parseInt(faceId.toString()); - // let faceType = parseInt(faceId.toString().substring(0, 1)); - let faceType = 1; - if (faceId >= 222) { - faceType = 2; - } - if (face.AniStickerType) { - faceType = 3; - } - return { - elementType: ElementType.FACE, - elementId: '', - faceElement: { - faceIndex: faceId, - faceType, - faceText: face.QDes, - stickerId: face.AniStickerId, - stickerType: face.AniStickerType, - packId: face.AniStickerPackId, - sourceType: 1, - }, - }; - } - - static mface(emojiPackageId: number, emojiId: string, key: string, faceName: string): SendMarketFaceElement { - return { - elementType: ElementType.MFACE, - marketFaceElement: { - emojiPackageId, - emojiId, - key, - faceName: faceName || mFaceCache.get(emojiId) || '[商城表情]', - }, - }; - } - - static dice(resultId: number | null): SendFaceElement { - // 实际测试并不能控制结果 - - // 随机1到6 - // if (isNull(resultId)) resultId = Math.floor(Math.random() * 6) + 1; - return { - elementType: ElementType.FACE, - elementId: '', - faceElement: { - faceIndex: FaceIndex.dice, - faceType: FaceType.dice, - 'faceText': '[骰子]', - 'packId': '1', - 'stickerId': '33', - 'sourceType': 1, - 'stickerType': 2, - // resultId: resultId.toString(), - 'surpriseId': '', - // "randomType": 1, - } - }; - } - - // 猜拳(石头剪刀布)表情 - static rps(resultId: number | null): SendFaceElement { - // 实际测试并不能控制结果 - // if (isNull(resultId)) resultId = Math.floor(Math.random() * 3) + 1; - return { - elementType: ElementType.FACE, - elementId: '', - faceElement: { - 'faceIndex': FaceIndex.RPS, - 'faceText': '[包剪锤]', - 'faceType': 3, - 'packId': '1', - 'stickerId': '34', - 'sourceType': 1, - 'stickerType': 2, - // 'resultId': resultId.toString(), - 'surpriseId': '', - // "randomType": 1, - } - }; - } - - static ark(data: any): SendArkElement { - if (typeof data !== 'string') { - data = JSON.stringify(data); - } - return { - elementType: ElementType.ARK, - elementId: '', - arkElement: { - bytesData: data, - linkInfo: null, - subElementType: null - } - }; - } - - static markdown(content: string): SendMarkdownElement { - return { - elementType: ElementType.MARKDOWN, - elementId: '', - markdownElement: { - content - } - }; - } - static async miniapp(): Promise { - let ret = await SignMiniApp({ - prompt: "Bot Test", - title: "Bot Test", - preview: "https://tianquan.gtimg.cn/qqAIAgent/item/7/square.png", - jumpUrl: "https://www.bilibili.com/", - tag: "Bot Test", - tagIcon: "https://tianquan.gtimg.cn/shoal/qqAIAgent/3e9d70c9-d98c-45b8-80b4-79d82971b514.png", - source: "Bot Test", - sourcelogo: "https://tianquan.gtimg.cn/shoal/qqAIAgent/3e9d70c9-d98c-45b8-80b4-79d82971b514.png" - }); - return { - elementType: ElementType.ARK, - elementId: '', - arkElement: { - bytesData: ret, - linkInfo: null, - subElementType: null - } - }; - } -} diff --git a/src/core/src/entities/face_config.json b/src/core/src/entities/face_config.json deleted file mode 100644 index 84bb8fec..00000000 --- a/src/core/src/entities/face_config.json +++ /dev/null @@ -1,3665 +0,0 @@ -{ - "sysface": [ - { - "QSid": "392", - "QDes": "/龙年快乐", - "IQLid": "392", - "AQLid": "392", - "EMCode": "10392", - "AniStickerType": 3, - "AniStickerPackId": "1", - "AniStickerId": "38" - }, - { - "QSid": "393", - "QDes": "/新年中龙", - "IQLid": "393", - "AQLid": "393", - "EMCode": "10393", - "QHide": "1", - "AniStickerType": 3, - "AniStickerPackId": "1", - "AniStickerId": "39" - }, - { - "QSid": "364", - "QDes": "/超级赞", - "IQLid": "364", - "AQLid": "364", - "EMCode": "10364", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "1", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "366", - "QDes": "/芒狗", - "IQLid": "366", - "AQLid": "366", - "EMCode": "10366", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "2", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "362", - "QDes": "/好兄弟", - "IQLid": "362", - "AQLid": "362", - "EMCode": "10362", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "3", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "397", - "QDes": "/抛媚眼", - "IQLid": "397", - "AQLid": "397", - "EMCode": "10397", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "4", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "396", - "QDes": "/狼狗", - "IQLid": "396", - "AQLid": "396", - "EMCode": "10396", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "5", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "360", - "QDes": "/亲亲", - "IQLid": "360", - "AQLid": "360", - "EMCode": "10360", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "6", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "361", - "QDes": "/狗狗笑哭", - "IQLid": "361", - "AQLid": "361", - "EMCode": "10361", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "7", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "363", - "QDes": "/狗狗可怜", - "IQLid": "363", - "AQLid": "363", - "EMCode": "10363", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "8", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "365", - "QDes": "/狗狗生气", - "IQLid": "365", - "AQLid": "365", - "EMCode": "10365", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "9", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "367", - "QDes": "/狗狗疑问", - "IQLid": "367", - "AQLid": "367", - "EMCode": "10367", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "10", - "AniStickerPackId": "2", - "AniStickerPackName": "汪汪" - }, - { - "QSid": "399", - "QDes": "/tui", - "IQLid": "399", - "AQLid": "399", - "EMCode": "10399", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "1", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "398", - "QDes": "/超级ok", - "IQLid": "398", - "AQLid": "398", - "EMCode": "10398", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "2", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "373", - "QDes": "/忙", - "IQLid": "373", - "AQLid": "373", - "EMCode": "10373", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "3", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "370", - "QDes": "/祝贺", - "IQLid": "370", - "AQLid": "370", - "EMCode": "10370", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "4", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "375", - "QDes": "/超级鼓掌", - "IQLid": "375", - "AQLid": "375", - "EMCode": "10375", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "5", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "368", - "QDes": "/奥特笑哭", - "IQLid": "368", - "AQLid": "368", - "EMCode": "10368", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "6", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "369", - "QDes": "/彩虹", - "IQLid": "369", - "AQLid": "369", - "EMCode": "10369", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "7", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "371", - "QDes": "/冒泡", - "IQLid": "371", - "AQLid": "371", - "EMCode": "10371", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "8", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "372", - "QDes": "/气呼呼", - "IQLid": "372", - "AQLid": "372", - "EMCode": "10372", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "9", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "374", - "QDes": "/波波流泪", - "IQLid": "374", - "AQLid": "374", - "EMCode": "10374", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "10", - "AniStickerPackId": "6", - "AniStickerPackName": "噗噗星人" - }, - { - "QSid": "382", - "QDes": "/emo", - "IQLid": "382", - "AQLid": "382", - "EMCode": "10382", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "1", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "383", - "QDes": "/企鹅爱心", - "IQLid": "383", - "AQLid": "383", - "EMCode": "10383", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "2", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "401", - "QDes": "/超级转圈", - "IQLid": "401", - "AQLid": "401", - "EMCode": "10401", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "3", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "400", - "QDes": "/快乐", - "IQLid": "400", - "AQLid": "400", - "EMCode": "10400", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "4", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "380", - "QDes": "/真棒", - "IQLid": "380", - "AQLid": "380", - "EMCode": "10380", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "5", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "381", - "QDes": "/路过", - "IQLid": "381", - "AQLid": "381", - "EMCode": "10381", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "6", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "379", - "QDes": "/企鹅流泪", - "IQLid": "379", - "AQLid": "379", - "EMCode": "10379", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "7", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "376", - "QDes": "/跺脚", - "IQLid": "376", - "AQLid": "376", - "EMCode": "10376", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "8", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "378", - "QDes": "/企鹅笑哭", - "IQLid": "378", - "AQLid": "378", - "EMCode": "10378", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "9", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "377", - "QDes": "/嗨", - "IQLid": "377", - "AQLid": "377", - "EMCode": "10377", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "10", - "AniStickerPackId": "5", - "AniStickerPackName": "企鹅" - }, - { - "QSid": "403", - "QDes": "/出去玩", - "IQLid": "403", - "AQLid": "403", - "EMCode": "10403", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "1", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "402", - "QDes": "/别说话", - "IQLid": "402", - "AQLid": "402", - "EMCode": "10402", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "2", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "390", - "QDes": "/太头秃", - "IQLid": "390", - "AQLid": "390", - "EMCode": "10390", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "3", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "391", - "QDes": "/太沧桑", - "IQLid": "391", - "AQLid": "391", - "EMCode": "10391", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "4", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "388", - "QDes": "/太头疼", - "IQLid": "388", - "AQLid": "388", - "EMCode": "10388", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "5", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "389", - "QDes": "/太赞了", - "IQLid": "389", - "AQLid": "389", - "EMCode": "10389", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "6", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "386", - "QDes": "/呜呜呜", - "IQLid": "386", - "AQLid": "386", - "EMCode": "10386", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "7", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "385", - "QDes": "/太气了", - "IQLid": "385", - "AQLid": "385", - "EMCode": "10385", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "8", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "384", - "QDes": "/晚安", - "IQLid": "384", - "AQLid": "384", - "EMCode": "10384", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "9", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "387", - "QDes": "/太好笑", - "IQLid": "387", - "AQLid": "387", - "EMCode": "10387", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "10", - "AniStickerPackId": "4", - "AniStickerPackName": "QQ黄脸" - }, - { - "QSid": "413", - "QDes": "/摇起来", - "IQLid": "413", - "AQLid": "413", - "EMCode": "10413", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "1", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "405", - "QDes": "/好运来", - "IQLid": "405", - "AQLid": "405", - "EMCode": "10405", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "2", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "404", - "QDes": "/闪亮登场", - "IQLid": "404", - "AQLid": "404", - "EMCode": "10404", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "3", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "406", - "QDes": "/姐是女王", - "IQLid": "406", - "AQLid": "406", - "EMCode": "10406", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "4", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "410", - "QDes": "/么么哒", - "IQLid": "410", - "AQLid": "410", - "EMCode": "10410", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "5", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "411", - "QDes": "/一起嗨", - "IQLid": "411", - "AQLid": "411", - "EMCode": "10411", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "6", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "407", - "QDes": "/我听听", - "IQLid": "407", - "AQLid": "407", - "EMCode": "10407", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "7", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "408", - "QDes": "/臭美", - "IQLid": "408", - "AQLid": "408", - "EMCode": "10408", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "8", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "412", - "QDes": "/开心", - "IQLid": "412", - "AQLid": "412", - "EMCode": "10412", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "9", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "409", - "QDes": "/送你花花", - "IQLid": "409", - "AQLid": "409", - "EMCode": "10409", - "QHide": "1", - "AniStickerType": 1, - "AniStickerId": "10", - "AniStickerPackId": "3", - "AniStickerPackName": "喜花妮" - }, - { - "QSid": "394", - "QDes": "/新年大龙", - "IQLid": "394", - "AQLid": "394", - "EMCode": "10394", - "QHide": "1", - "AniStickerType": 3, - "AniStickerPackId": "1", - "AniStickerId": "40" - }, - { - "QSid": "14", - "QDes": "/微笑", - "IQLid": "23", - "AQLid": "23", - "EMCode": "100" - }, - { - "QSid": "1", - "QDes": "/撇嘴", - "IQLid": "40", - "AQLid": "40", - "EMCode": "101" - }, - { - "QSid": "2", - "QDes": "/色", - "IQLid": "19", - "AQLid": "19", - "EMCode": "102" - }, - { - "QSid": "3", - "QDes": "/发呆", - "IQLid": "43", - "AQLid": "43", - "EMCode": "103" - }, - { - "QSid": "4", - "QDes": "/得意", - "IQLid": "21", - "AQLid": "21", - "EMCode": "104" - }, - { - "QSid": "6", - "QDes": "/害羞", - "IQLid": "20", - "AQLid": "20", - "EMCode": "106" - }, - { - "QSid": "7", - "QDes": "/闭嘴", - "IQLid": "104", - "AQLid": "106", - "EMCode": "107" - }, - { - "QSid": "8", - "QDes": "/睡", - "IQLid": "35", - "AQLid": "35", - "EMCode": "108" - }, - { - "QSid": "9", - "QDes": "/大哭", - "IQLid": "10", - "AQLid": "10", - "EMCode": "109" - }, - { - "QSid": "5", - "QDes": "/流泪", - "IQLid": "9", - "AQLid": "9", - "EMCode": "105", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "16" - }, - { - "QSid": "10", - "QDes": "/尴尬", - "IQLid": "25", - "AQLid": "25", - "EMCode": "110" - }, - { - "QSid": "11", - "QDes": "/发怒", - "IQLid": "24", - "AQLid": "24", - "EMCode": "111" - }, - { - "QSid": "12", - "QDes": "/调皮", - "IQLid": "1", - "AQLid": "1", - "EMCode": "112" - }, - { - "QSid": "13", - "QDes": "/呲牙", - "IQLid": "0", - "AQLid": "0", - "EMCode": "113" - }, - { - "QSid": "0", - "QDes": "/惊讶", - "IQLid": "33", - "AQLid": "33", - "EMCode": "114" - }, - { - "QSid": "15", - "QDes": "/难过", - "IQLid": "32", - "AQLid": "32", - "EMCode": "115" - }, - { - "QSid": "16", - "QDes": "/酷", - "IQLid": "12", - "AQLid": "12", - "EMCode": "116" - }, - { - "QSid": "96", - "QDes": "/冷汗", - "IQLid": "27", - "AQLid": "27", - "EMCode": "117" - }, - { - "QSid": "18", - "QDes": "/抓狂", - "IQLid": "13", - "AQLid": "13", - "EMCode": "118" - }, - { - "QSid": "19", - "QDes": "/吐", - "IQLid": "22", - "AQLid": "22", - "EMCode": "119" - }, - { - "QSid": "20", - "QDes": "/偷笑", - "IQLid": "3", - "AQLid": "3", - "EMCode": "120" - }, - { - "QSid": "21", - "QDes": "/可爱", - "IQLid": "18", - "AQLid": "18", - "EMCode": "121" - }, - { - "QSid": "22", - "QDes": "/白眼", - "IQLid": "30", - "AQLid": "30", - "EMCode": "122" - }, - { - "QSid": "23", - "QDes": "/傲慢", - "IQLid": "31", - "AQLid": "31", - "EMCode": "123" - }, - { - "QSid": "24", - "QDes": "/饥饿", - "IQLid": "79", - "AQLid": "81", - "EMCode": "124" - }, - { - "QSid": "25", - "QDes": "/困", - "IQLid": "80", - "AQLid": "82", - "EMCode": "125" - }, - { - "QSid": "26", - "QDes": "/惊恐", - "IQLid": "26", - "AQLid": "26", - "EMCode": "126" - }, - { - "QSid": "27", - "QDes": "/流汗", - "IQLid": "2", - "AQLid": "2", - "EMCode": "127" - }, - { - "QSid": "28", - "QDes": "/憨笑", - "IQLid": "37", - "AQLid": "37", - "EMCode": "128" - }, - { - "QSid": "29", - "QDes": "/悠闲", - "IQLid": "50", - "AQLid": "50", - "EMCode": "129" - }, - { - "QSid": "30", - "QDes": "/奋斗", - "IQLid": "42", - "AQLid": "42", - "EMCode": "130" - }, - { - "QSid": "31", - "QDes": "/咒骂", - "IQLid": "81", - "AQLid": "83", - "EMCode": "131" - }, - { - "QSid": "32", - "QDes": "/疑问", - "IQLid": "34", - "AQLid": "34", - "EMCode": "132" - }, - { - "QSid": "33", - "QDes": "/嘘", - "IQLid": "11", - "AQLid": "11", - "EMCode": "133" - }, - { - "QSid": "34", - "QDes": "/晕", - "IQLid": "49", - "AQLid": "49", - "EMCode": "134" - }, - { - "QSid": "35", - "QDes": "/折磨", - "IQLid": "82", - "AQLid": "84", - "EMCode": "135" - }, - { - "QSid": "36", - "QDes": "/衰", - "IQLid": "39", - "AQLid": "39", - "EMCode": "136" - }, - { - "QSid": "37", - "QDes": "/骷髅", - "isStatic": "1", - "IQLid": "76", - "AQLid": "78", - "EMCode": "137" - }, - { - "QSid": "38", - "QDes": "/敲打", - "IQLid": "5", - "AQLid": "5", - "EMCode": "138" - }, - { - "QSid": "39", - "QDes": "/再见", - "IQLid": "4", - "AQLid": "4", - "EMCode": "139" - }, - { - "QSid": "97", - "QDes": "/擦汗", - "IQLid": "6", - "AQLid": "6", - "EMCode": "140" - }, - { - "QSid": "98", - "QDes": "/抠鼻", - "IQLid": "83", - "AQLid": "85", - "EMCode": "141" - }, - { - "QSid": "99", - "QDes": "/鼓掌", - "IQLid": "84", - "AQLid": "86", - "EMCode": "142" - }, - { - "QSid": "100", - "QDes": "/糗大了", - "IQLid": "85", - "AQLid": "87", - "EMCode": "143" - }, - { - "QSid": "101", - "QDes": "/坏笑", - "IQLid": "46", - "AQLid": "46", - "EMCode": "144" - }, - { - "QSid": "102", - "QDes": "/左哼哼", - "IQLid": "86", - "AQLid": "88", - "EMCode": "145" - }, - { - "QSid": "103", - "QDes": "/右哼哼", - "IQLid": "44", - "AQLid": "44", - "EMCode": "146" - }, - { - "QSid": "104", - "QDes": "/哈欠", - "IQLid": "87", - "AQLid": "89", - "EMCode": "147" - }, - { - "QSid": "105", - "QDes": "/鄙视", - "IQLid": "48", - "AQLid": "48", - "EMCode": "148" - }, - { - "QSid": "106", - "QDes": "/委屈", - "IQLid": "14", - "AQLid": "14", - "EMCode": "149" - }, - { - "QSid": "107", - "QDes": "/快哭了", - "IQLid": "88", - "AQLid": "90", - "EMCode": "150" - }, - { - "QSid": "108", - "QDes": "/阴险", - "IQLid": "41", - "AQLid": "41", - "EMCode": "151" - }, - { - "QSid": "305", - "QDes": "/右亲亲", - "IQLid": "305", - "AQLid": "305", - "EMCode": "10305" - }, - { - "QSid": "109", - "QDes": "/左亲亲", - "IQLid": "36", - "AQLid": "36", - "EMCode": "152" - }, - { - "QSid": "110", - "QDes": "/吓", - "IQLid": "89", - "AQLid": "91", - "EMCode": "153" - }, - { - "QSid": "111", - "QDes": "/可怜", - "IQLid": "51", - "AQLid": "51", - "EMCode": "154" - }, - { - "QSid": "172", - "QDes": "/眨眼睛", - "IQLid": "142", - "AQLid": "164", - "EMCode": "242" - }, - { - "QSid": "182", - "QDes": "/笑哭", - "IQLid": "152", - "AQLid": "174", - "EMCode": "252" - }, - { - "QSid": "179", - "QDes": "/doge", - "IQLid": "149", - "AQLid": "171", - "EMCode": "249" - }, - { - "QSid": "173", - "QDes": "/泪奔", - "IQLid": "143", - "AQLid": "165", - "EMCode": "243" - }, - { - "QSid": "174", - "QDes": "/无奈", - "IQLid": "144", - "AQLid": "166", - "EMCode": "244" - }, - { - "QSid": "212", - "QDes": "/托腮", - "IQLid": "182", - "AQLid": "161", - "EMCode": "282" - }, - { - "QSid": "175", - "QDes": "/卖萌", - "IQLid": "145", - "AQLid": "167", - "EMCode": "245" - }, - { - "QSid": "178", - "QDes": "/斜眼笑", - "IQLid": "148", - "AQLid": "170", - "EMCode": "248" - }, - { - "QSid": "177", - "QDes": "/喷血", - "IQLid": "147", - "AQLid": "169", - "EMCode": "247" - }, - { - "QSid": "176", - "QDes": "/小纠结", - "IQLid": "146", - "AQLid": "168", - "EMCode": "246" - }, - { - "QSid": "183", - "QDes": "/我最美", - "IQLid": "153", - "AQLid": "175", - "EMCode": "253" - }, - { - "QSid": "262", - "QDes": "/脑阔疼", - "IQLid": "262", - "AQLid": "262", - "EMCode": "10262" - }, - { - "QSid": "263", - "QDes": "/沧桑", - "IQLid": "263", - "AQLid": "263", - "EMCode": "10263" - }, - { - "QSid": "264", - "QDes": "/捂脸", - "IQLid": "264", - "AQLid": "264", - "EMCode": "10264" - }, - { - "QSid": "265", - "QDes": "/辣眼睛", - "IQLid": "265", - "AQLid": "265", - "EMCode": "10265" - }, - { - "QSid": "266", - "QDes": "/哦哟", - "IQLid": "266", - "AQLid": "266", - "EMCode": "10266" - }, - { - "QSid": "267", - "QDes": "/头秃", - "IQLid": "267", - "AQLid": "267", - "EMCode": "10267" - }, - { - "QSid": "268", - "QDes": "/问号脸", - "IQLid": "268", - "AQLid": "268", - "EMCode": "10268" - }, - { - "QSid": "269", - "QDes": "/暗中观察", - "IQLid": "269", - "AQLid": "269", - "EMCode": "10269" - }, - { - "QSid": "270", - "QDes": "/emm", - "IQLid": "270", - "AQLid": "270", - "EMCode": "10270" - }, - { - "QSid": "271", - "QDes": "/吃瓜", - "IQLid": "271", - "AQLid": "271", - "EMCode": "10271" - }, - { - "QSid": "272", - "QDes": "/呵呵哒", - "IQLid": "272", - "AQLid": "272", - "EMCode": "10272" - }, - { - "QSid": "277", - "QDes": "/汪汪", - "IQLid": "277", - "AQLid": "277", - "EMCode": "10277" - }, - { - "QSid": "307", - "QDes": "/喵喵", - "IQLid": "307", - "AQLid": "307", - "EMCode": "10307" - }, - { - "QSid": "306", - "QDes": "/牛气冲天", - "isStatic": "1", - "IQLid": "306", - "AQLid": "306", - "EMCode": "10306" - }, - { - "QSid": "281", - "QDes": "/无眼笑", - "IQLid": "281", - "AQLid": "281", - "EMCode": "10281" - }, - { - "QSid": "282", - "QDes": "/敬礼", - "IQLid": "282", - "AQLid": "282", - "EMCode": "10282" - }, - { - "QSid": "283", - "QDes": "/狂笑", - "IQLid": "283", - "AQLid": "283", - "EMCode": "10283" - }, - { - "QSid": "284", - "QDes": "/面无表情", - "IQLid": "284", - "AQLid": "284", - "EMCode": "10284" - }, - { - "QSid": "285", - "QDes": "/摸鱼", - "IQLid": "285", - "AQLid": "285", - "EMCode": "10285" - }, - { - "QSid": "293", - "QDes": "/摸锦鲤", - "IQLid": "293", - "AQLid": "293", - "EMCode": "10293" - }, - { - "QSid": "286", - "QDes": "/魔鬼笑", - "IQLid": "286", - "AQLid": "286", - "EMCode": "10286" - }, - { - "QSid": "287", - "QDes": "/哦", - "IQLid": "287", - "AQLid": "287", - "EMCode": "10287" - }, - { - "QSid": "289", - "QDes": "/睁眼", - "IQLid": "289", - "AQLid": "289", - "EMCode": "10289" - }, - { - "QSid": "294", - "QDes": "/期待", - "IQLid": "294", - "AQLid": "294", - "EMCode": "10294" - }, - { - "QSid": "297", - "QDes": "/拜谢", - "IQLid": "297", - "AQLid": "297", - "EMCode": "10297" - }, - { - "QSid": "298", - "QDes": "/元宝", - "IQLid": "298", - "AQLid": "298", - "EMCode": "10298" - }, - { - "QSid": "299", - "QDes": "/牛啊", - "IQLid": "299", - "AQLid": "299", - "EMCode": "10299" - }, - { - "QSid": "300", - "QDes": "/胖三斤", - "IQLid": "300", - "AQLid": "300", - "EMCode": "10300" - }, - { - "QSid": "323", - "QDes": "/嫌弃", - "IQLid": "323", - "AQLid": "323", - "EMCode": "10323" - }, - { - "QSid": "332", - "QDes": "/举牌牌", - "IQLid": "332", - "AQLid": "332", - "EMCode": "10332" - }, - { - "QSid": "336", - "QDes": "/豹富", - "IQLid": "336", - "AQLid": "336", - "EMCode": "10336" - }, - { - "QSid": "353", - "QDes": "/拜托", - "IQLid": "353", - "AQLid": "353", - "EMCode": "10353" - }, - { - "QSid": "355", - "QDes": "/耶", - "IQLid": "355", - "AQLid": "355", - "EMCode": "10355" - }, - { - "QSid": "356", - "QDes": "/666", - "IQLid": "356", - "AQLid": "356", - "EMCode": "10356" - }, - { - "QSid": "354", - "QDes": "/尊嘟假嘟", - "IQLid": "354", - "AQLid": "354", - "EMCode": "10354" - }, - { - "QSid": "352", - "QDes": "/咦", - "IQLid": "352", - "AQLid": "352", - "EMCode": "10352" - }, - { - "QSid": "357", - "QDes": "/裂开", - "IQLid": "357", - "AQLid": "357", - "EMCode": "10357" - }, - { - "QSid": "334", - "QDes": "/虎虎生威", - "IQLid": "334", - "AQLid": "334", - "EMCode": "10334" - }, - { - "QSid": "347", - "QDes": "/大展宏兔", - "IQLid": "347", - "AQLid": "347", - "EMCode": "10347" - }, - { - "QSid": "303", - "QDes": "/右拜年", - "IQLid": "303", - "AQLid": "303", - "EMCode": "10303" - }, - { - "QSid": "302", - "QDes": "/左拜年", - "IQLid": "302", - "AQLid": "302", - "EMCode": "10302" - }, - { - "QSid": "295", - "QDes": "/拿到红包", - "IQLid": "295", - "AQLid": "295", - "EMCode": "10295" - }, - { - "QSid": "311", - "QDes": "/打call", - "IQLid": "311", - "AQLid": "311", - "EMCode": "10311", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "1" - }, - { - "QSid": "312", - "QDes": "/变形", - "IQLid": "312", - "AQLid": "312", - "EMCode": "10312", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "2" - }, - { - "QSid": "314", - "QDes": "/仔细分析", - "IQLid": "314", - "AQLid": "314", - "EMCode": "10314", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "4" - }, - { - "QSid": "317", - "QDes": "/菜汪", - "IQLid": "317", - "AQLid": "317", - "EMCode": "10317", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "7" - }, - { - "QSid": "318", - "QDes": "/崇拜", - "IQLid": "318", - "AQLid": "318", - "EMCode": "10318", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "8" - }, - { - "QSid": "319", - "QDes": "/比心", - "IQLid": "319", - "AQLid": "319", - "EMCode": "10319", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "9" - }, - { - "QSid": "320", - "QDes": "/庆祝", - "IQLid": "320", - "AQLid": "320", - "EMCode": "10320", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "10" - }, - { - "QSid": "324", - "QDes": "/吃糖", - "IQLid": "324", - "AQLid": "324", - "EMCode": "10324", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "12" - }, - { - "QSid": "325", - "QDes": "/惊吓", - "IQLid": "325", - "AQLid": "325", - "EMCode": "10325", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "14" - }, - { - "QSid": "337", - "QDes": "/花朵脸", - "IQLid": "337", - "AQLid": "337", - "EMCode": "10337", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "22" - }, - { - "QSid": "338", - "QDes": "/我想开了", - "IQLid": "338", - "AQLid": "338", - "EMCode": "10338", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "20" - }, - { - "QSid": "339", - "QDes": "/舔屏", - "IQLid": "339", - "AQLid": "339", - "EMCode": "10339", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "21" - }, - { - "QSid": "341", - "QDes": "/打招呼", - "IQLid": "341", - "AQLid": "341", - "EMCode": "10341", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "24" - }, - { - "QSid": "342", - "QDes": "/酸Q", - "IQLid": "342", - "AQLid": "342", - "EMCode": "10342", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "26" - }, - { - "QSid": "343", - "QDes": "/我方了", - "IQLid": "343", - "AQLid": "343", - "EMCode": "10343", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "27" - }, - { - "QSid": "344", - "QDes": "/大怨种", - "IQLid": "344", - "AQLid": "344", - "EMCode": "10344", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "28" - }, - { - "QSid": "345", - "QDes": "/红包多多", - "IQLid": "345", - "AQLid": "345", - "EMCode": "10345", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "29" - }, - { - "QSid": "346", - "QDes": "/你真棒棒", - "IQLid": "346", - "AQLid": "346", - "EMCode": "10346", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "25" - }, - { - "QSid": "181", - "QDes": "/戳一戳", - "IQLid": "151", - "AQLid": "173", - "EMCode": "251", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "37" - }, - { - "QSid": "74", - "QDes": "/太阳", - "isStatic": "1", - "IQLid": "73", - "AQLid": "75", - "EMCode": "176", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "35" - }, - { - "QSid": "75", - "QDes": "/月亮", - "isStatic": "1", - "IQLid": "67", - "AQLid": "68", - "EMCode": "175", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "36" - }, - { - "QSid": "351", - "QDes": "/敲敲", - "IQLid": "351", - "AQLid": "351", - "EMCode": "10351", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "30" - }, - { - "QSid": "349", - "QDes": "/坚强", - "IQLid": "349", - "AQLid": "349", - "EMCode": "10349", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "32" - }, - { - "QSid": "350", - "QDes": "/贴贴", - "IQLid": "350", - "AQLid": "350", - "EMCode": "10350", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "31" - }, - { - "QSid": "395", - "QDes": "/略略略", - "IQLid": "395", - "AQLid": "395", - "EMCode": "10395", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "41" - }, - { - "QSid": "114", - "QDes": "/篮球", - "IQLid": "90", - "AQLid": "92", - "EMCode": "158", - "AniStickerType": 2, - "AniStickerPackId": "1", - "AniStickerId": "13" - }, - { - "QSid": "358", - "QDes": "/骰子", - "IQLid": "358", - "AQLid": "358", - "QHide": "1", - "EMCode": "10358", - "AniStickerType": 2, - "AniStickerPackId": "1", - "AniStickerId": "33" - }, - { - "QSid": "359", - "QDes": "/包剪锤", - "IQLid": "359", - "AQLid": "359", - "QHide": "1", - "EMCode": "10359", - "AniStickerType": 2, - "AniStickerPackId": "1", - "AniStickerId": "34" - }, - { - "QSid": "326", - "QDes": "/生气", - "IQLid": "326", - "AQLid": "326", - "EMCode": "10326", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "15" - }, - { - "QSid": "53", - "QDes": "/蛋糕", - "IQLid": "59", - "AQLid": "59", - "EMCode": "168", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "17" - }, - { - "QSid": "49", - "QDes": "/拥抱", - "IQLid": "45", - "AQLid": "45", - "EMCode": "178" - }, - { - "QSid": "66", - "QDes": "/爱心", - "IQLid": "28", - "AQLid": "28", - "EMCode": "166" - }, - { - "QSid": "63", - "QDes": "/玫瑰", - "IQLid": "8", - "AQLid": "8", - "EMCode": "163" - }, - { - "QSid": "64", - "QDes": "/凋谢", - "IQLid": "57", - "AQLid": "57", - "EMCode": "164" - }, - { - "QSid": "187", - "QDes": "/幽灵", - "IQLid": "157", - "AQLid": "179", - "EMCode": "257" - }, - { - "QSid": "146", - "QDes": "/爆筋", - "IQLid": "116", - "AQLid": "118", - "EMCode": "121011" - }, - { - "QSid": "116", - "QDes": "/示爱", - "IQLid": "29", - "AQLid": "29", - "EMCode": "165" - }, - { - "QSid": "67", - "QDes": "/心碎", - "IQLid": "72", - "AQLid": "74", - "EMCode": "167" - }, - { - "QSid": "60", - "QDes": "/咖啡", - "IQLid": "66", - "AQLid": "66", - "EMCode": "160" - }, - { - "QSid": "185", - "QDes": "/羊驼", - "IQLid": "155", - "AQLid": "177", - "EMCode": "255" - }, - { - "QSid": "137", - "QDes": "/鞭炮", - "isStatic": "1", - "IQLid": "107", - "AQLid": "109", - "EMCode": "121002", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "18" - }, - { - "QSid": "333", - "QDes": "/烟花", - "isStatic": "1", - "IQLid": "333", - "AQLid": "333", - "EMCode": "10333", - "AniStickerType": 1, - "AniStickerPackId": "1", - "AniStickerId": "19" - }, - { - "QSid": "76", - "QDes": "/赞", - "IQLid": "52", - "AQLid": "52", - "EMCode": "179" - }, - { - "QSid": "124", - "QDes": "/OK", - "IQLid": "64", - "AQLid": "64", - "EMCode": "189" - }, - { - "QSid": "118", - "QDes": "/抱拳", - "IQLid": "56", - "AQLid": "56", - "EMCode": "183" - }, - { - "QSid": "78", - "QDes": "/握手", - "IQLid": "54", - "AQLid": "54", - "EMCode": "181" - }, - { - "QSid": "119", - "QDes": "/勾引", - "IQLid": "63", - "AQLid": "63", - "EMCode": "184" - }, - { - "QSid": "79", - "QDes": "/胜利", - "IQLid": "55", - "AQLid": "55", - "EMCode": "182" - }, - { - "QSid": "120", - "QDes": "/拳头", - "IQLid": "71", - "AQLid": "73", - "EMCode": "185" - }, - { - "QSid": "121", - "QDes": "/差劲", - "IQLid": "70", - "AQLid": "72", - "EMCode": "186" - }, - { - "QSid": "77", - "QDes": "/踩", - "IQLid": "53", - "AQLid": "53", - "EMCode": "180" - }, - { - "QSid": "123", - "QDes": "/NO", - "IQLid": "92", - "AQLid": "94", - "EMCode": "188" - }, - { - "QSid": "201", - "QDes": "/点赞", - "IQLid": "171", - "AQLid": "150", - "EMCode": "271" - }, - { - "QSid": "273", - "QDes": "/我酸了", - "isStatic": "1", - "IQLid": "273", - "AQLid": "273", - "EMCode": "10273" - }, - { - "QSid": "46", - "QDes": "/猪头", - "isStatic": "1", - "IQLid": "7", - "AQLid": "7", - "EMCode": "162" - }, - { - "QSid": "112", - "QDes": "/菜刀", - "IQLid": "17", - "AQLid": "17", - "EMCode": "155" - }, - { - "QSid": "56", - "QDes": "/刀", - "IQLid": "68", - "AQLid": "70", - "EMCode": "171" - }, - { - "QSid": "169", - "QDes": "/手枪", - "isStatic": "1", - "IQLid": "139", - "AQLid": "141", - "EMCode": "121034" - }, - { - "QSid": "171", - "QDes": "/茶", - "IQLid": "141", - "AQLid": "163", - "EMCode": "241" - }, - { - "QSid": "59", - "QDes": "/便便", - "IQLid": "15", - "AQLid": "15", - "EMCode": "174" - }, - { - "QSid": "144", - "QDes": "/喝彩", - "isStatic": "1", - "IQLid": "114", - "AQLid": "116", - "EMCode": "121009" - }, - { - "QSid": "147", - "QDes": "/棒棒糖", - "isStatic": "1", - "IQLid": "117", - "AQLid": "119", - "EMCode": "121012" - }, - { - "QSid": "89", - "QDes": "/西瓜", - "isStatic": "1", - "IQLid": "60", - "AQLid": "60", - "EMCode": "156" - }, - { - "QSid": "148", - "QDes": "/喝奶", - "isStatic": "1", - "IQLid": "118", - "AQLid": "120", - "QHide": "1", - "EMCode": "121013" - }, - { - "QSid": "55", - "QDes": "/炸弹", - "isStatic": "1", - "IQLid": "16", - "AQLid": "16", - "QHide": "1", - "EMCode": "170" - }, - { - "QSid": "41", - "QDes": "/发抖", - "isStatic": "1", - "IQLid": "69", - "AQLid": "71", - "EMCode": "193" - }, - { - "QSid": "125", - "QDes": "/转圈", - "IQLid": "95", - "AQLid": "97", - "EMCode": "195" - }, - { - "QSid": "42", - "QDes": "/爱情", - "IQLid": "38", - "AQLid": "38", - "EMCode": "190" - }, - { - "QSid": "43", - "QDes": "/跳跳", - "IQLid": "93", - "AQLid": "95", - "EMCode": "192" - }, - { - "QSid": "86", - "QDes": "/怄火", - "IQLid": "94", - "AQLid": "96", - "EMCode": "194" - }, - { - "QSid": "129", - "QDes": "/挥手", - "IQLid": "77", - "AQLid": "79", - "EMCode": "199" - }, - { - "QSid": "226", - "QDes": "/拍桌", - "IQLid": "196", - "isCMEmoji": "1", - "AQLid": "198", - "QHide": "1", - "EMCode": "297" - }, - { - "QSid": "85", - "QDes": "/飞吻", - "isStatic": "1", - "IQLid": "47", - "AQLid": "47", - "EMCode": "191" - }, - { - "QSid": "215", - "QDes": "/糊脸", - "IQLid": "185", - "isCMEmoji": "1", - "AQLid": "187", - "QHide": "1", - "EMCode": "285" - }, - { - "QSid": "214", - "QDes": "/啵啵", - "IQLid": "184", - "isCMEmoji": "1", - "AQLid": "186", - "QHide": "1", - "EMCode": "284" - }, - { - "QSid": "222", - "QDes": "/抱抱", - "IQLid": "192", - "isCMEmoji": "1", - "AQLid": "194", - "QHide": "1", - "EMCode": "292" - }, - { - "QSid": "203", - "QDes": "/托脸", - "IQLid": "173", - "AQLid": "152", - "QHide": "1", - "EMCode": "273" - }, - { - "QSid": "235", - "QDes": "/颤抖", - "IQLid": "205", - "isCMEmoji": "1", - "AQLid": "207", - "QHide": "1", - "EMCode": "305" - }, - { - "QSid": "241", - "QDes": "/生日快乐", - "IQLid": "211", - "isCMEmoji": "1", - "AQLid": "213", - "QHide": "1", - "EMCode": "311" - }, - { - "QSid": "237", - "QDes": "/偷看", - "IQLid": "207", - "isCMEmoji": "1", - "AQLid": "209", - "QHide": "1", - "EMCode": "307" - }, - { - "QSid": "218", - "QDes": "/舔一舔", - "IQLid": "188", - "isCMEmoji": "1", - "AQLid": "190", - "QHide": "1", - "EMCode": "288" - }, - { - "QSid": "233", - "QDes": "/掐一掐", - "IQLid": "203", - "isCMEmoji": "1", - "AQLid": "205", - "QHide": "1", - "EMCode": "303" - }, - { - "QSid": "232", - "QDes": "/佛系", - "IQLid": "202", - "isCMEmoji": "1", - "AQLid": "204", - "QHide": "1", - "EMCode": "302" - }, - { - "QSid": "238", - "QDes": "/扇脸", - "IQLid": "208", - "isCMEmoji": "1", - "AQLid": "210", - "QHide": "1", - "EMCode": "308" - }, - { - "QSid": "217", - "QDes": "/扯一扯", - "IQLid": "187", - "isCMEmoji": "1", - "AQLid": "189", - "QHide": "1", - "EMCode": "287" - }, - { - "QSid": "225", - "QDes": "/撩一撩", - "IQLid": "195", - "isCMEmoji": "1", - "AQLid": "197", - "QHide": "1", - "EMCode": "296" - }, - { - "QSid": "230", - "QDes": "/嘲讽", - "IQLid": "200", - "isCMEmoji": "1", - "AQLid": "202", - "QHide": "1", - "EMCode": "300" - }, - { - "QSid": "194", - "QDes": "/不开心", - "IQLid": "164", - "AQLid": "143", - "QHide": "1", - "EMCode": "264" - }, - { - "QSid": "210", - "QDes": "/飙泪", - "IQLid": "180", - "AQLid": "159", - "QHide": "1", - "EMCode": "280" - }, - { - "QSid": "193", - "QDes": "/大笑", - "IQLid": "163", - "AQLid": "185", - "QHide": "1", - "EMCode": "263" - }, - { - "QSid": "204", - "QDes": "/吃", - "IQLid": "174", - "AQLid": "153", - "QHide": "1", - "EMCode": "274" - }, - { - "QSid": "200", - "QDes": "/求求", - "IQLid": "170", - "AQLid": "149", - "QHide": "1", - "EMCode": "270" - }, - { - "QSid": "290", - "QDes": "/敲开心", - "IQLid": "290", - "isCMEmoji": "1", - "AQLid": "290", - "QHide": "1", - "EMCode": "20240" - }, - { - "QSid": "224", - "QDes": "/开枪", - "IQLid": "194", - "isCMEmoji": "1", - "AQLid": "196", - "QHide": "1", - "EMCode": "295" - }, - { - "QSid": "229", - "QDes": "/干杯", - "IQLid": "199", - "isCMEmoji": "1", - "AQLid": "201", - "QHide": "1", - "EMCode": "299" - }, - { - "QSid": "221", - "QDes": "/顶呱呱", - "IQLid": "191", - "isCMEmoji": "1", - "AQLid": "193", - "QHide": "1", - "EMCode": "291" - }, - { - "QSid": "219", - "QDes": "/蹭一蹭", - "IQLid": "189", - "isCMEmoji": "1", - "AQLid": "191", - "QHide": "1", - "EMCode": "289" - }, - { - "QSid": "227", - "QDes": "/拍手", - "IQLid": "197", - "isCMEmoji": "1", - "AQLid": "199", - "QHide": "1", - "EMCode": "294" - }, - { - "QSid": "216", - "QDes": "/拍头", - "IQLid": "186", - "isCMEmoji": "1", - "AQLid": "188", - "QHide": "1", - "EMCode": "286" - }, - { - "QSid": "231", - "QDes": "/哼", - "IQLid": "201", - "isCMEmoji": "1", - "AQLid": "203", - "QHide": "1", - "EMCode": "301" - }, - { - "QSid": "244", - "QDes": "/扔狗", - "IQLid": "214", - "isCMEmoji": "1", - "AQLid": "216", - "QHide": "1", - "EMCode": "312" - }, - { - "QSid": "223", - "QDes": "/暴击", - "IQLid": "193", - "isCMEmoji": "1", - "AQLid": "195", - "QHide": "1", - "EMCode": "293" - }, - { - "QSid": "243", - "QDes": "/甩头", - "IQLid": "213", - "isCMEmoji": "1", - "AQLid": "215", - "QHide": "1", - "EMCode": "313" - }, - { - "QSid": "211", - "QDes": "/我不看", - "IQLid": "181", - "AQLid": "160", - "QHide": "1", - "EMCode": "281" - }, - { - "QSid": "292", - "QDes": "/让我康康", - "IQLid": "292", - "isCMEmoji": "1", - "AQLid": "292", - "QHide": "1", - "EMCode": "20242" - }, - { - "QSid": "240", - "QDes": "/喷脸", - "IQLid": "210", - "isCMEmoji": "1", - "AQLid": "212", - "QHide": "1", - "EMCode": "310" - }, - { - "QSid": "180", - "QDes": "/惊喜", - "IQLid": "150", - "AQLid": "172", - "QHide": "1", - "EMCode": "250" - }, - { - "QSid": "122", - "QDes": "/爱你", - "IQLid": "65", - "AQLid": "65", - "QHide": "1", - "EMCode": "187" - }, - { - "QSid": "202", - "QDes": "/无聊", - "IQLid": "172", - "AQLid": "151", - "QHide": "1", - "EMCode": "272" - }, - { - "QSid": "278", - "QDes": "/汗", - "IQLid": "278", - "isCMEmoji": "1", - "AQLid": "278", - "QHide": "1", - "EMCode": "20237" - }, - { - "QSid": "301", - "QDes": "/好闪", - "IQLid": "301", - "AQLid": "301", - "QHide": "1", - "EMCode": "10301" - }, - { - "QSid": "288", - "QDes": "/请", - "IQLid": "288", - "AQLid": "288", - "QHide": "1", - "EMCode": "10288" - }, - { - "QSid": "322", - "QDes": "/拒绝", - "IQLid": "322", - "AQLid": "322", - "QHide": "1", - "EMCode": "10322" - }, - { - "QSid": "198", - "QDes": "/呃", - "IQLid": "168", - "AQLid": "147", - "QHide": "1", - "EMCode": "268" - }, - { - "QSid": "348", - "QDes": "/福萝卜", - "IQLid": "348", - "AQLid": "348", - "QHide": "1", - "EMCode": "10348" - }, - { - "QSid": "206", - "QDes": "/害怕", - "IQLid": "176", - "AQLid": "155", - "QHide": "1", - "EMCode": "276" - }, - { - "QSid": "239", - "QDes": "/原谅", - "IQLid": "209", - "isCMEmoji": "1", - "AQLid": "211", - "QHide": "1", - "EMCode": "309" - } - ], - "emoji": [ - { - "QSid": "😊", - "QCid": "128522", - "AQLid": "0", - "QDes": "/嘿嘿", - "EMCode": "400832" - }, - { - "QSid": "😌", - "QCid": "128524", - "AQLid": "1", - "QDes": "/羞涩", - "EMCode": "400834" - }, - { - "QSid": "😚", - "QCid": "128538", - "AQLid": "2", - "QDes": "/亲亲", - "EMCode": "400848" - }, - { - "QSid": "😓", - "QCid": "128531", - "AQLid": "3", - "QDes": "/汗", - "EMCode": "400841" - }, - { - "QSid": "😰", - "QCid": "128560", - "AQLid": "4", - "QDes": "/紧张", - "EMCode": "400870" - }, - { - "QSid": "😝", - "QCid": "128541", - "AQLid": "5", - "QDes": "/吐舌", - "EMCode": "400851" - }, - { - "QSid": "😁", - "QCid": "128513", - "AQLid": "6", - "QDes": "/呲牙", - "EMCode": "400823" - }, - { - "QSid": "😜", - "QCid": "128540", - "AQLid": "7", - "QDes": "/淘气", - "EMCode": "400850" - }, - { - "QSid": "☺", - "QCid": "9786", - "AQLid": "8", - "QDes": "/可爱", - "EMCode": "401181" - }, - { - "QSid": "😉", - "QCid": "128521", - "AQLid": "9", - "QDes": "/媚眼", - "QHide": "1", - "EMCode": "400831" - }, - { - "QSid": "😍", - "QCid": "128525", - "AQLid": "10", - "QDes": "/花痴", - "EMCode": "400835" - }, - { - "QSid": "😔", - "QCid": "128532", - "AQLid": "11", - "QDes": "/失落", - "EMCode": "400842" - }, - { - "QSid": "😄", - "QCid": "128516", - "AQLid": "12", - "QDes": "/高兴", - "EMCode": "400826" - }, - { - "QSid": "😏", - "QCid": "128527", - "AQLid": "13", - "QDes": "/哼哼", - "EMCode": "400837" - }, - { - "QSid": "😒", - "QCid": "128530", - "AQLid": "14", - "QDes": "/不屑", - "EMCode": "400840" - }, - { - "QSid": "😳", - "QCid": "128563", - "AQLid": "15", - "QDes": "/瞪眼", - "EMCode": "400873" - }, - { - "QSid": "😘", - "QCid": "128536", - "AQLid": "16", - "QDes": "/飞吻", - "EMCode": "400846" - }, - { - "QSid": "😭", - "QCid": "128557", - "AQLid": "17", - "QDes": "/大哭", - "EMCode": "400867" - }, - { - "QSid": "😱", - "QCid": "128561", - "AQLid": "18", - "QDes": "/害怕", - "EMCode": "400871" - }, - { - "QSid": "😂", - "QCid": "128514", - "AQLid": "19", - "QDes": "/激动", - "EMCode": "400824" - }, - { - "QSid": "💪", - "QCid": "128170", - "AQLid": "20", - "QDes": "/肌肉", - "EMCode": "400644" - }, - { - "QSid": "👊", - "QCid": "128074", - "AQLid": "21", - "QDes": "/拳头", - "EMCode": "400390" - }, - { - "QSid": "👍", - "QCid": "128077", - "AQLid": "22", - "QDes": "/厉害", - "EMCode": "400408" - }, - { - "QSid": "☝", - "QCid": "9757", - "AQLid": "23", - "QDes": "/向上", - "QHide": "1", - "EMCode": "401203" - }, - { - "QSid": "👏", - "QCid": "128079", - "AQLid": "24", - "QDes": "/鼓掌", - "EMCode": "400420" - }, - { - "QSid": "✌", - "QCid": "9996", - "AQLid": "25", - "QDes": "/胜利", - "QHide": "1", - "EMCode": "401210" - }, - { - "QSid": "👎", - "QCid": "128078", - "AQLid": "26", - "QDes": "/鄙视", - "EMCode": "400414" - }, - { - "QSid": "🙏", - "QCid": "128591", - "AQLid": "27", - "QDes": "/合十", - "EMCode": "400396" - }, - { - "QSid": "👌", - "QCid": "128076", - "AQLid": "28", - "QDes": "/好的", - "EMCode": "400402" - }, - { - "QSid": "👈", - "QCid": "128072", - "AQLid": "29", - "QDes": "/向左", - "QHide": "1", - "EMCode": "400378" - }, - { - "QSid": "👉", - "QCid": "128073", - "AQLid": "30", - "QDes": "/向右", - "QHide": "1", - "EMCode": "400384" - }, - { - "QSid": "👆", - "QCid": "128070", - "AQLid": "31", - "QDes": "/向上", - "EMCode": "400366" - }, - { - "QSid": "👇", - "QCid": "128071", - "AQLid": "32", - "QDes": "/向下", - "QHide": "1", - "EMCode": "400372" - }, - { - "QSid": "👀", - "QCid": "128064", - "AQLid": "33", - "QDes": "/眼睛", - "EMCode": "400351" - }, - { - "QSid": "👃", - "QCid": "128067", - "AQLid": "34", - "QDes": "/鼻子", - "QHide": "1", - "EMCode": "400358" - }, - { - "QSid": "👄", - "QCid": "128068", - "AQLid": "35", - "QDes": "/嘴唇", - "QHide": "1", - "EMCode": "400364" - }, - { - "QSid": "👂", - "QCid": "128066", - "AQLid": "36", - "QDes": "/耳朵", - "QHide": "1", - "EMCode": "400352" - }, - { - "QSid": "🍚", - "QCid": "127834", - "AQLid": "37", - "QDes": "/米饭", - "QHide": "1", - "EMCode": "400149" - }, - { - "QSid": "🍝", - "QCid": "127837", - "AQLid": "38", - "QDes": "/意面", - "QHide": "1", - "EMCode": "400152" - }, - { - "QSid": "🍜", - "QCid": "127836", - "AQLid": "39", - "QDes": "/拉面", - "EMCode": "400151" - }, - { - "QSid": "🍙", - "QCid": "127833", - "AQLid": "40", - "QDes": "/饭团", - "QHide": "1", - "EMCode": "400148" - }, - { - "QSid": "🍧", - "QCid": "127847", - "AQLid": "41", - "QDes": "/刨冰", - "EMCode": "400162" - }, - { - "QSid": "🍣", - "QCid": "127843", - "AQLid": "42", - "QDes": "/寿司", - "QHide": "1", - "EMCode": "400158" - }, - { - "QSid": "🎂", - "QCid": "127874", - "AQLid": "43", - "QDes": "/蛋糕", - "QHide": "1", - "EMCode": "400186" - }, - { - "QSid": "🍞", - "QCid": "127838", - "AQLid": "44", - "QDes": "/面包", - "EMCode": "400153" - }, - { - "QSid": "🍔", - "QCid": "127828", - "AQLid": "45", - "QDes": "/汉堡", - "QHide": "1", - "EMCode": "400143" - }, - { - "QSid": "🍳", - "QCid": "127859", - "AQLid": "46", - "QDes": "/煎蛋", - "QHide": "1", - "EMCode": "400174" - }, - { - "QSid": "🍟", - "QCid": "127839", - "AQLid": "47", - "QDes": "/薯条", - "QHide": "1", - "EMCode": "400154" - }, - { - "QSid": "🍺", - "QCid": "127866", - "AQLid": "48", - "QDes": "/啤酒", - "EMCode": "400181" - }, - { - "QSid": "🍻", - "QCid": "127867", - "AQLid": "49", - "QDes": "/干杯", - "EMCode": "400182" - }, - { - "QSid": "🍸", - "QCid": "127864", - "AQLid": "50", - "QDes": "/高脚杯", - "QHide": "1", - "EMCode": "400179" - }, - { - "QSid": "☕", - "QCid": "9749", - "AQLid": "51", - "QDes": "/咖啡", - "EMCode": "401262" - }, - { - "QSid": "🍎", - "QCid": "127822", - "AQLid": "52", - "QDes": "/苹果", - "EMCode": "400137" - }, - { - "QSid": "🍊", - "QCid": "127818", - "AQLid": "53", - "QDes": "/橙子", - "QHide": "1", - "EMCode": "400133" - }, - { - "QSid": "🍓", - "QCid": "127827", - "AQLid": "54", - "QDes": "/草莓", - "EMCode": "400142" - }, - { - "QSid": "🍉", - "QCid": "127817", - "AQLid": "55", - "QDes": "/西瓜", - "EMCode": "400132" - }, - { - "QSid": "💊", - "QCid": "128138", - "AQLid": "56", - "QDes": "/药丸", - "QHide": "1", - "EMCode": "400612" - }, - { - "QSid": "🚬", - "QCid": "128684", - "AQLid": "57", - "QDes": "/吸烟", - "EMCode": "400987" - }, - { - "QSid": "🎄", - "QCid": "127876", - "AQLid": "58", - "QDes": "/圣诞树", - "QHide": "1", - "EMCode": "400188" - }, - { - "QSid": "🌹", - "QCid": "127801", - "AQLid": "59", - "QDes": "/玫瑰", - "EMCode": "400116" - }, - { - "QSid": "🎉", - "QCid": "127881", - "AQLid": "60", - "QDes": "/庆祝", - "EMCode": "400198" - }, - { - "QSid": "🌴", - "QCid": "127796", - "AQLid": "61", - "QDes": "/椰子树", - "QHide": "1", - "EMCode": "400112" - }, - { - "QSid": "💝", - "QCid": "128157", - "AQLid": "62", - "QDes": "/礼物", - "EMCode": "400631" - }, - { - "QSid": "🎀", - "QCid": "127872", - "AQLid": "63", - "QDes": "/蝴蝶结", - "QHide": "1", - "EMCode": "400184" - }, - { - "QSid": "🎈", - "QCid": "127880", - "AQLid": "64", - "QDes": "/气球", - "QHide": "1", - "EMCode": "400197" - }, - { - "QSid": "🐚", - "QCid": "128026", - "AQLid": "65", - "QDes": "/海螺", - "QHide": "1", - "EMCode": "400314" - }, - { - "QSid": "💍", - "QCid": "128141", - "AQLid": "66", - "QDes": "/戒指", - "QHide": "1", - "EMCode": "400615" - }, - { - "QSid": "💣", - "QCid": "128163", - "AQLid": "67", - "QDes": "/炸弹", - "EMCode": "400637" - }, - { - "QSid": "👑", - "QCid": "128081", - "AQLid": "68", - "QDes": "/皇冠", - "QHide": "1", - "EMCode": "400432" - }, - { - "QSid": "🔔", - "QCid": "128276", - "AQLid": "69", - "QDes": "/铃铛", - "QHide": "1", - "EMCode": "400751" - }, - { - "QSid": "⭐", - "QCid": "11088", - "AQLid": "70", - "QDes": "/星星", - "QHide": "1", - "EMCode": "401686" - }, - { - "QSid": "✨", - "QCid": "10024", - "AQLid": "71", - "QDes": "/闪光", - "EMCode": "401137" - }, - { - "QSid": "💨", - "QCid": "128168", - "AQLid": "72", - "QDes": "/吹气", - "EMCode": "400642" - }, - { - "QSid": "💦", - "QCid": "128166", - "AQLid": "73", - "QDes": "/水", - "EMCode": "400640" - }, - { - "QSid": "🔥", - "QCid": "128293", - "AQLid": "74", - "QDes": "/火", - "EMCode": "400768" - }, - { - "QSid": "🏆", - "QCid": "127942", - "AQLid": "75", - "QDes": "/奖杯", - "QHide": "1", - "EMCode": "400256" - }, - { - "QSid": "💰", - "QCid": "128176", - "AQLid": "76", - "QDes": "/钱", - "QHide": "1", - "EMCode": "400655" - }, - { - "QSid": "💤", - "QCid": "128164", - "AQLid": "77", - "QDes": "/睡觉", - "EMCode": "400638" - }, - { - "QSid": "⚡", - "QCid": "9889", - "AQLid": "78", - "QDes": "/闪电", - "QHide": "1", - "EMCode": "401685" - }, - { - "QSid": "👣", - "QCid": "128099", - "AQLid": "79", - "QDes": "/脚印", - "QHide": "1", - "EMCode": "400450" - }, - { - "QSid": "💩", - "QCid": "128169", - "AQLid": "80", - "QDes": "/便便", - "EMCode": "400643" - }, - { - "QSid": "💉", - "QCid": "128137", - "AQLid": "81", - "QDes": "/打针", - "EMCode": "400611" - }, - { - "QSid": "♨", - "QCid": "9832", - "AQLid": "82", - "QDes": "/热", - "QHide": "1", - "EMCode": "401287" - }, - { - "QSid": "📫", - "QCid": "128235", - "AQLid": "83", - "QDes": "/邮箱", - "EMCode": "400714" - }, - { - "QSid": "🔑", - "QCid": "128273", - "AQLid": "84", - "QDes": "/钥匙", - "QHide": "1", - "EMCode": "400748" - }, - { - "QSid": "🔒", - "QCid": "128274", - "AQLid": "85", - "QDes": "/锁", - "QHide": "1", - "EMCode": "400749" - }, - { - "QSid": "✈", - "QCid": "9992", - "AQLid": "86", - "QDes": "/飞机", - "QHide": "1", - "EMCode": "401298" - }, - { - "QSid": "🚄", - "QCid": "128644", - "AQLid": "87", - "QDes": "/列车", - "QHide": "1", - "EMCode": "400942" - }, - { - "QSid": "🚗", - "QCid": "128663", - "AQLid": "88", - "QDes": "/汽车", - "QHide": "1", - "EMCode": "400961" - }, - { - "QSid": "🚤", - "QCid": "128676", - "AQLid": "89", - "QDes": "/快艇", - "QHide": "1", - "EMCode": "400979" - }, - { - "QSid": "🚲", - "QCid": "128690", - "AQLid": "90", - "QDes": "/自行车", - "QHide": "1", - "EMCode": "400993" - }, - { - "QSid": "🐎", - "QCid": "128014", - "AQLid": "91", - "QDes": "/骑马", - "EMCode": "400302" - }, - { - "QSid": "🚀", - "QCid": "128640", - "AQLid": "92", - "QDes": "/火箭", - "QHide": "1", - "EMCode": "400938" - }, - { - "QSid": "🚌", - "QCid": "128652", - "AQLid": "93", - "QDes": "/公交", - "QHide": "1", - "EMCode": "400950" - }, - { - "QSid": "⛵", - "QCid": "9973", - "AQLid": "94", - "QDes": "/船", - "QHide": "1", - "EMCode": "401294" - }, - { - "QSid": "👩", - "QCid": "128105", - "AQLid": "95", - "QDes": "/妈妈", - "QHide": "1", - "EMCode": "400482" - }, - { - "QSid": "👨", - "QCid": "128104", - "AQLid": "96", - "QDes": "/爸爸", - "QHide": "1", - "EMCode": "400465" - }, - { - "QSid": "👧", - "QCid": "128103", - "AQLid": "97", - "QDes": "/女孩", - "EMCode": "400459" - }, - { - "QSid": "👦", - "QCid": "128102", - "AQLid": "98", - "QDes": "/男孩", - "EMCode": "400453" - }, - { - "QSid": "🐵", - "QCid": "128053", - "AQLid": "99", - "QDes": "/猴", - "EMCode": "400341" - }, - { - "QSid": "🐙", - "QCid": "128025", - "AQLid": "100", - "QDes": "/章鱼", - "QHide": "1", - "EMCode": "400313" - }, - { - "QSid": "🐷", - "QCid": "128055", - "AQLid": "101", - "QDes": "/猪", - "EMCode": "400343" - }, - { - "QSid": "💀", - "QCid": "128128", - "AQLid": "102", - "QDes": "/骷髅", - "QHide": "1", - "EMCode": "400572" - }, - { - "QSid": "🐤", - "QCid": "128036", - "AQLid": "103", - "QDes": "/小鸡", - "QHide": "1", - "EMCode": "400324" - }, - { - "QSid": "🐨", - "QCid": "128040", - "AQLid": "104", - "QDes": "/树懒", - "QHide": "1", - "EMCode": "400328" - }, - { - "QSid": "🐮", - "QCid": "128046", - "AQLid": "105", - "QDes": "/牛", - "EMCode": "400334" - }, - { - "QSid": "🐔", - "QCid": "128020", - "AQLid": "106", - "QDes": "/公鸡", - "EMCode": "400308" - }, - { - "QSid": "🐸", - "QCid": "128056", - "AQLid": "107", - "QDes": "/青蛙", - "EMCode": "400344" - }, - { - "QSid": "👻", - "QCid": "128123", - "AQLid": "108", - "QDes": "/幽灵", - "EMCode": "400562" - }, - { - "QSid": "🐛", - "QCid": "128027", - "AQLid": "109", - "QDes": "/虫", - "EMCode": "400315" - }, - { - "QSid": "🐠", - "QCid": "128032", - "AQLid": "110", - "QDes": "/鱼", - "QHide": "1", - "EMCode": "400320" - }, - { - "QSid": "🐶", - "QCid": "128054", - "AQLid": "111", - "QDes": "/狗", - "EMCode": "400342" - }, - { - "QSid": "🐯", - "QCid": "128047", - "AQLid": "112", - "QDes": "/老虎", - "QHide": "1", - "EMCode": "400335" - }, - { - "QSid": "👼", - "QCid": "128124", - "AQLid": "113", - "QDes": "/天使", - "QHide": "1", - "EMCode": "400563" - }, - { - "QSid": "🐧", - "QCid": "128039", - "AQLid": "114", - "QDes": "/企鹅", - "QHide": "1", - "EMCode": "400327" - }, - { - "QSid": "🐳", - "QCid": "128051", - "AQLid": "115", - "QDes": "/鲸鱼", - "EMCode": "400339" - }, - { - "QSid": "🐭", - "QCid": "128045", - "AQLid": "116", - "QDes": "/老鼠", - "QHide": "1", - "EMCode": "400333" - }, - { - "QSid": "👒", - "QCid": "128082", - "AQLid": "117", - "QDes": "/帽子", - "QHide": "1", - "EMCode": "400433" - }, - { - "QSid": "👗", - "QCid": "128087", - "AQLid": "118", - "QDes": "/连衣裙", - "QHide": "1", - "EMCode": "400438" - }, - { - "QSid": "💄", - "QCid": "128132", - "AQLid": "119", - "QDes": "/口红", - "QHide": "1", - "EMCode": "400591" - }, - { - "QSid": "👠", - "QCid": "128096", - "AQLid": "120", - "QDes": "/高跟鞋", - "QHide": "1", - "EMCode": "400447" - }, - { - "QSid": "👢", - "QCid": "128098", - "AQLid": "121", - "QDes": "/靴子", - "EMCode": "400449" - }, - { - "QSid": "🌂", - "QCid": "127746", - "AQLid": "122", - "QDes": "/雨伞", - "QHide": "1", - "EMCode": "400077" - }, - { - "QSid": "👜", - "QCid": "128092", - "AQLid": "123", - "QDes": "/包", - "QHide": "1", - "EMCode": "400443" - }, - { - "QSid": "👙", - "QCid": "128089", - "AQLid": "124", - "QDes": "/内衣", - "QHide": "1", - "EMCode": "400440" - }, - { - "QSid": "👕", - "QCid": "128085", - "AQLid": "125", - "QDes": "/衣服", - "QHide": "1", - "EMCode": "400436" - }, - { - "QSid": "👟", - "QCid": "128095", - "AQLid": "126", - "QDes": "/鞋子", - "QHide": "1", - "EMCode": "400446" - }, - { - "QSid": "☁", - "QCid": "9729", - "AQLid": "127", - "QDes": "/云朵", - "QHide": "1", - "EMCode": "401329" - }, - { - "QSid": "☀", - "QCid": "9728", - "AQLid": "128", - "QDes": "/晴天", - "EMCode": "401328" - }, - { - "QSid": "☔", - "QCid": "9748", - "AQLid": "129", - "QDes": "/雨天", - "QHide": "1", - "EMCode": "401342" - }, - { - "QSid": "🌙", - "QCid": "127769", - "AQLid": "130", - "QDes": "/月亮", - "QHide": "1", - "EMCode": "400100" - }, - { - "QSid": "⛄", - "QCid": "9924", - "AQLid": "131", - "QDes": "/雪人", - "QHide": "1", - "EMCode": "401346" - }, - { - "QSid": "⭕", - "QCid": "11093", - "AQLid": "132", - "QDes": "/正确", - "QHide": "1", - "EMCode": "401687" - }, - { - "QSid": "❌", - "QCid": "10060", - "AQLid": "133", - "QDes": "/错误", - "QHide": "1", - "EMCode": "401142" - }, - { - "QSid": "❔", - "QCid": "10068", - "AQLid": "134", - "QDes": "/问号", - "EMCode": "401145" - }, - { - "QSid": "❕", - "QCid": "10069", - "AQLid": "135", - "QDes": "/叹号", - "QHide": "1", - "EMCode": "401146" - }, - { - "QSid": "☎", - "QCid": "9742", - "AQLid": "136", - "QDes": "/电话", - "QHide": "1", - "EMCode": "401398" - }, - { - "QSid": "📷", - "QCid": "128247", - "AQLid": "137", - "QDes": "/相机", - "QHide": "1", - "EMCode": "400726" - }, - { - "QSid": "📱", - "QCid": "128241", - "AQLid": "138", - "QDes": "/手机", - "QHide": "1", - "EMCode": "400720" - }, - { - "QSid": "📠", - "QCid": "128224", - "AQLid": "139", - "QDes": "/传真", - "QHide": "1", - "EMCode": "400703" - }, - { - "QSid": "💻", - "QCid": "128187", - "AQLid": "140", - "QDes": "/电脑", - "QHide": "1", - "EMCode": "400666" - }, - { - "QSid": "🎥", - "QCid": "127909", - "AQLid": "141", - "QDes": "/摄影机", - "QHide": "1", - "EMCode": "400214" - }, - { - "QSid": "🎤", - "QCid": "127908", - "AQLid": "142", - "QDes": "/话筒", - "QHide": "1", - "EMCode": "400213" - }, - { - "QSid": "🔫", - "QCid": "128299", - "AQLid": "143", - "QDes": "/手枪", - "EMCode": "400774" - }, - { - "QSid": "💿", - "QCid": "128191", - "AQLid": "144", - "QDes": "/光碟", - "QHide": "1", - "EMCode": "400670" - }, - { - "QSid": "💓", - "QCid": "128147", - "AQLid": "145", - "QDes": "/爱心", - "EMCode": "400621" - }, - { - "QSid": "♣", - "QCid": "9827", - "AQLid": "146", - "QDes": "/扑克", - "QHide": "1", - "EMCode": "401385" - }, - { - "QSid": "🀄", - "QCid": "126980", - "AQLid": "147", - "QDes": "/麻将", - "QHide": "1", - "EMCode": "401386" - }, - { - "QSid": "〽", - "QCid": "12349", - "AQLid": "148", - "QDes": "/股票", - "QHide": "1", - "EMCode": "401691" - }, - { - "QSid": "🎰", - "QCid": "127920", - "AQLid": "149", - "QDes": "/老虎机", - "QHide": "1", - "EMCode": "400225" - }, - { - "QSid": "🚥", - "QCid": "128677", - "AQLid": "150", - "QDes": "/信号灯", - "QHide": "1", - "EMCode": "400980" - }, - { - "QSid": "🚧", - "QCid": "128679", - "AQLid": "151", - "QDes": "/路障", - "QHide": "1", - "EMCode": "400982" - }, - { - "QSid": "🎸", - "QCid": "127928", - "AQLid": "152", - "QDes": "/吉他", - "QHide": "1", - "EMCode": "400233" - }, - { - "QSid": "💈", - "QCid": "128136", - "AQLid": "153", - "QDes": "/理发厅", - "QHide": "1", - "EMCode": "400610" - }, - { - "QSid": "🛀", - "QCid": "128704", - "AQLid": "154", - "QDes": "/浴缸", - "QHide": "1", - "EMCode": "401022" - }, - { - "QSid": "🚽", - "QCid": "128701", - "AQLid": "155", - "QDes": "/马桶", - "QHide": "1", - "EMCode": "401019" - }, - { - "QSid": "🏠", - "QCid": "127968", - "AQLid": "156", - "QDes": "/家", - "QHide": "1", - "EMCode": "400271" - }, - { - "QSid": "⛪", - "QCid": "9962", - "AQLid": "157", - "QDes": "/教堂", - "QHide": "1", - "EMCode": "401281" - }, - { - "QSid": "🏦", - "QCid": "127974", - "AQLid": "158", - "QDes": "/银行", - "QHide": "1", - "EMCode": "400277" - }, - { - "QSid": "🏥", - "QCid": "127973", - "AQLid": "159", - "QDes": "/医院", - "QHide": "1", - "EMCode": "400276" - }, - { - "QSid": "🏨", - "QCid": "127976", - "AQLid": "160", - "QDes": "/酒店", - "QHide": "1", - "EMCode": "400279" - }, - { - "QSid": "🏧", - "QCid": "127975", - "AQLid": "161", - "QDes": "/取款机", - "QHide": "1", - "EMCode": "400278" - }, - { - "QSid": "🏪", - "QCid": "127978", - "AQLid": "162", - "QDes": "/便利店", - "EMCode": "400281" - }, - { - "QSid": "🚹", - "QCid": "128697", - "AQLid": "163", - "QDes": "/男性", - "QHide": "1", - "EMCode": "401015" - }, - { - "QSid": "🚺", - "QCid": "128698", - "AQLid": "164", - "QDes": "/女性", - "QHide": "1", - "EMCode": "401016" - } - ] -} \ No newline at end of file diff --git a/src/core/src/entities/group.ts b/src/core/src/entities/group.ts deleted file mode 100644 index 43688fa2..00000000 --- a/src/core/src/entities/group.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { QQLevel, Sex } from './user'; -export enum GroupListUpdateType { - REFRESHALL, - GETALL, - MODIFIED, - REMOVE -} -export interface Group { - groupCode: string, - createTime?: string,//高版本才有 - maxMember: number, - memberCount: number, - groupName: string, - groupStatus: number, - memberRole: number, - isTop: boolean, - toppedTimestamp: string, - privilegeFlag: number, //65760 - isConf: boolean, - hasModifyConfGroupFace: boolean, - hasModifyConfGroupName: boolean, - remarkName: string, - hasMemo: boolean, - groupShutupExpireTime: string, //"0", - personShutupExpireTime: string, //"0", - discussToGroupUin: string, //"0", - discussToGroupMaxMsgSeq: number, - discussToGroupTime: number, - groupFlagExt: number, //1073938496, - authGroupType: number, //0, - groupCreditLevel: number, //0, - groupFlagExt3: number, //0, - groupOwnerId: { - memberUin: string, //"0", - memberUid: string, //"u_fbf8N7aeuZEnUiJAbQ9R8Q" - } -} - -export enum GroupMemberRole { - normal = 2, - admin = 3, - owner = 4 -} - -export interface GroupMember { - memberSpecialTitle?: string; - avatarPath: string; - cardName: string; - cardType: number; - isDelete: boolean; - nick: string; - qid: string; - remark: string; - role: GroupMemberRole; // 群主:4, 管理员:3,群员:2 - shutUpTime: number; // 禁言时间,单位是什么暂时不清楚 - uid: string; // 加密的字符串 - uin: string; // QQ号 - isRobot: boolean; - sex?: Sex - qqLevel?: QQLevel - isChangeRole: boolean; - joinTime: string; - lastSpeakTime: string; -} \ No newline at end of file diff --git a/src/core/src/entities/index.ts b/src/core/src/entities/index.ts deleted file mode 100644 index 97eb9b0e..00000000 --- a/src/core/src/entities/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './user'; -export * from './group'; -export * from './msg'; -export * from './notify'; -export * from './cache'; -export * from './constructor'; - diff --git a/src/core/src/entities/msg.ts b/src/core/src/entities/msg.ts deleted file mode 100644 index 3f5d1ab8..00000000 --- a/src/core/src/entities/msg.ts +++ /dev/null @@ -1,787 +0,0 @@ -import { GroupMemberRole } from './group'; - - -export interface Peer { - chatType: ChatType; - peerUid: string; // 如果是群聊uid为群号,私聊uid就是加密的字符串 - guildId?: string; -} -export interface KickedOffLineInfo { - appId: number - instanceId: number - sameDevice: boolean - tipsDesc: string - tipsTitle: string - kickedType: number - securityKickedType: number -} -export interface GetFileListParam { - sortType: number - fileCount: number - startIndex: number - sortOrder: number - showOnlinedocFolder: number -} -export enum ElementType { - UNKNOWN = 0, - TEXT = 1, - PIC = 2, - FILE = 3, - PTT = 4, - VIDEO = 5, - FACE = 6, - REPLY = 7, - WALLET = 9, - GreyTip = 8,//Poke别叫戳一搓了 官方名字拍一拍 戳一戳是另一个名字 - ARK = 10, - MFACE = 11, - LIVEGIFT = 12, - STRUCTLONGMSG = 13, - MARKDOWN = 14, - GIPHY = 15, - MULTIFORWARD = 16, - INLINEKEYBOARD = 17, - INTEXTGIFT = 18, - CALENDAR = 19, - YOLOGAMERESULT = 20, - AVRECORD = 21, - FEED = 22, - TOFURECORD = 23, - ACEBUBBLE = 24, - ACTIVITY = 25, - TOFU = 26, - FACEBUBBLE = 27, - SHARELOCATION = 28, - TASKTOPMSG = 29, - RECOMMENDEDMSG = 43, - ACTIONBAR = 44 -} -export interface ActionBarElement { - rows: InlineKeyboardRow[]; - botAppid: string; -} -export interface SendActionBarElement { - elementType: ElementType.ACTIONBAR; - elementId: string; - actionBarElement: ActionBarElement; -} -export interface RecommendedMsgElement { - rows: InlineKeyboardRow[]; - botAppid: string; -} -export interface SendRecommendedMsgElement { - elementType: ElementType.RECOMMENDEDMSG; - elementId: string; - recommendedMsgElement: RecommendedMsgElement; -} -export interface InlineKeyboardButton { - id: string; - label: string; - visitedLabel: string; - unsupportTips: string; - data: string; - specifyRoleIds: string[]; - specifyTinyids: string[]; - style: number; - type: number; - clickLimit: number; - atBotShowChannelList: boolean; - permissionType: number; -} -export interface InlineKeyboardRow { - buttons: InlineKeyboardButton[]; -} -export interface TofuElementContent { - color: string; - tittle: string; -} -export interface TaskTopMsgElement { - msgTitle: string; - msgSummary: string; - iconUrl: string; - topMsgType: number; -} -export interface SendTaskTopMsgElement { - elementType: ElementType.TASKTOPMSG; - elementId: string; - taskTopMsgElement: TaskTopMsgElement; -} -export interface TofuRecordElement { - type: number; - busiid: string; - busiuuid: string; - descriptionContent: string; - contentlist: TofuElementContent[], - background: string; - icon: string; - uinlist: string[], - uidlist: string[], - busiExtra: string; - updateTime: string; - dependedmsgid: string; - msgtime: string; - onscreennotify: boolean; -} -export interface SendTofuRecordElement { - elementType: ElementType.TOFURECORD; - elementId: string; - tofuRecordElement: TofuRecordElement; -} - -export interface FaceBubbleElement { - faceCount: number; - faceSummary: string; - faceFlag: number; - content: string; - oldVersionStr: string; - faceType: number; - others: string; - yellowFaceInfo: { - index: number; - buf: string; - compatibleText: string; - text: string; - } -} -export interface SendFaceBubbleElement { - elementType: ElementType.FACEBUBBLE; - elementId: string; - faceBubbleElement: FaceBubbleElement; - -} -export interface AvRecordElement { - type: number; - time: string; - text: string; - mainType: number; - hasRead: boolean; - extraType: number; -} -export interface SendavRecordElement { - elementType: ElementType.AVRECORD; - elementId: string; - avRecordElement: AvRecordElement; -} -export interface YoloUserInfo { - uid: string; - result: number; - rank: number; - bizId: string -} -export interface SendInlineKeyboardElement { - elementType: ElementType.INLINEKEYBOARD; - elementId: string; - inlineKeyboardElement: { - rows: number; - botAppid: string; - } - -} -export interface YoloGameResultElement { - UserInfo: YoloUserInfo[]; -} -export interface SendYoloGameResultElement { - elementType: ElementType.YOLOGAMERESULT; - yoloGameResultElement: YoloGameResultElement -} -export interface GiphyElement { - id: string; - isClip: boolean; - width: number; - height: number; -} -export interface SendGiphyElement { - elementType: ElementType.GIPHY; - elementId: string; - giphyElement: GiphyElement; -} -export interface SendWalletElement { - elementType: ElementType.UNKNOWN;//不做 设置位置 - elementId: string; - walletElement: {} -} -export interface CalendarElement { - summary: string; - msg: string; - expireTimeMs: string; - schemaType: number; - schema: string -} -export interface SendCalendarElement { - elementType: ElementType.CALENDAR; - elementId: string; - calendarElement: CalendarElement; -} -export interface SendliveGiftElement { - elementType: ElementType.LIVEGIFT; - elementId: string; - liveGiftElement: {} -} -export interface SendTextElement { - elementType: ElementType.TEXT; - elementId: string; - textElement: { - content: string; - atType: number; - atUid: string; - atTinyId: string; - atNtUid: string; - }; -} - -export interface SendPttElement { - elementType: ElementType.PTT; - elementId: string; - pttElement: { - fileName: string; - filePath: string; - md5HexStr: string; - fileSize: number; - duration: number; // 单位是秒 - formatType: number; - voiceType: number; - voiceChangeType: number; - canConvert2Text: boolean; - waveAmplitudes: number[]; - fileSubId: string; - playState: number; - autoConvertText: number; - }; -} - -export enum PicType { - gif = 2000, - jpg = 1000 -} - -export enum PicSubType { - normal = 0, // 普通图片,大图 - face = 1 // 表情包小图 -} - -export interface SendPicElement { - elementType: ElementType.PIC; - elementId: string; - picElement:PicElement -} -export interface ReplyElement { - replayMsgSeq: string; - replayMsgId: string; - senderUin: string; - senderUinStr: string; -} -export interface SendReplyElement { - elementType: ElementType.REPLY; - elementId: string; - replyElement: ReplyElement -} - -export interface SendFaceElement { - elementType: ElementType.FACE; - elementId: string; - faceElement: FaceElement; -} - -export interface SendMarketFaceElement { - elementType: ElementType.MFACE; - marketFaceElement: MarketFaceElement; -} -export interface SendstructLongMsgElement { - elementType: ElementType.STRUCTLONGMSG; - elementId: string; - structLongMsgElement: StructLongMsgElement; -} -export interface StructLongMsgElement { - xmlContent: string; - resId: string; -} -export interface SendactionBarElement { - elementType: ElementType.ACTIONBAR; - elementId: string; - actionBarElement: { - rows: number; - botAppid: string; - } -} -export interface ShareLocationElement { - text: string; - ext: string; -} -export interface sendShareLocationElement { - elementType: ElementType.SHARELOCATION; - elementId: string; - shareLocationElement?: ShareLocationElement; -} - -export interface FileElement { - fileMd5?: string; - fileName: string; - filePath: string; - fileSize: string; - picHeight?: number; - picWidth?: number; - folderId?: string; - picThumbPath?: Map; - file10MMd5?: string; - fileSha?: string; - fileSha3?: string; - fileUuid?: string; - fileSubId?: string; - thumbFileSize?: number; - fileBizId?: number -} - -export interface SendFileElement { - elementType: ElementType.FILE; - elementId: string; - fileElement: FileElement; -} - -export interface SendVideoElement { - elementType: ElementType.VIDEO; - elementId: string; - videoElement: VideoElement; -} - -export interface SendArkElement { - elementType: ElementType.ARK; - elementId: string; - arkElement: ArkElement; -} - -export interface SendMarkdownElement { - elementType: ElementType.MARKDOWN; - elementId: string; - markdownElement: MarkdownElement; -} -export type SendMessageElement = SendTextElement | SendPttElement | - SendPicElement | SendReplyElement | SendFaceElement | SendMarketFaceElement | SendFileElement | - SendVideoElement | SendArkElement | SendMarkdownElement | sendShareLocationElement; - -export interface TextElement { - content: string; - atType: number; - atUid: string; - atTinyId: string; - atNtUid: string; -} -export interface MessageElement { - elementType: ElementType, - elementId: string, - extBufForUI: string,//"0x", - textElement?: TextElement; - faceElement?: FaceElement, - marketFaceElement?: MarkdownElement, - replyElement?: ReplyElement, - picElement?: PicElement, - pttElement?: PttElement, - videoElement?: VideoElement, - grayTipElement?: GrayTipElement, - arkElement?: ArkElement, - fileElement?: FileElement, - liveGiftElement?: null, - markdownElement?: MarkdownElement, - structLongMsgElement?: StructLongMsgElement, - multiForwardMsgElement?: MultiForwardMsgElement, - giphyElement?: GiphyElement, - walletElement?: null, - inlineKeyboardElement?: InlineKeyboardElement, - textGiftElement?: null,//???? - calendarElement?: CalendarElement, - yoloGameResultElement?: YoloGameResultElement, - avRecordElement?: AvRecordElement, - structMsgElement?: null, - faceBubbleElement?: FaceBubbleElement, - shareLocationElement?: ShareLocationElement, - tofuRecordElement?: TofuRecordElement, - taskTopMsgElement?: TaskTopMsgElement, - recommendedMsgElement?: RecommendedMsgElement, - actionBarElement?:ActionBarElement - -} -export enum AtType { - notAt = 0, - atAll = 1, - atUser = 2 -} - -export enum ChatType { - friend = 1, - group = 2, - chatDevice = 8, //移动设备? - temp = 100 - -} -// 来自Android分析 -export enum ChatType2 { - KCHATTYPEADELIE = 42, - KCHATTYPEBUDDYNOTIFY = 5, - KCHATTYPEC2C = 1, - KCHATTYPECIRCLE = 113, - KCHATTYPEDATALINE = 8, - KCHATTYPEDATALINEMQQ = 134, - KCHATTYPEDISC = 3, - KCHATTYPEFAV = 41, - KCHATTYPEGAMEMESSAGE = 105, - KCHATTYPEGAMEMESSAGEFOLDER = 116, - KCHATTYPEGROUP = 2, - KCHATTYPEGROUPBLESS = 133, - KCHATTYPEGROUPGUILD = 9, - KCHATTYPEGROUPHELPER = 7, - KCHATTYPEGROUPNOTIFY = 6, - KCHATTYPEGUILD = 4, - KCHATTYPEGUILDMETA = 16, - KCHATTYPEMATCHFRIEND = 104, - KCHATTYPEMATCHFRIENDFOLDER = 109, - KCHATTYPENEARBY = 106, - KCHATTYPENEARBYASSISTANT = 107, - KCHATTYPENEARBYFOLDER = 110, - KCHATTYPENEARBYHELLOFOLDER = 112, - KCHATTYPENEARBYINTERACT = 108, - KCHATTYPEQQNOTIFY = 132, - KCHATTYPERELATEACCOUNT = 131, - KCHATTYPESERVICEASSISTANT = 118, - KCHATTYPESERVICEASSISTANTSUB = 201, - KCHATTYPESQUAREPUBLIC = 115, - KCHATTYPESUBSCRIBEFOLDER = 30, - KCHATTYPETEMPADDRESSBOOK = 111, - KCHATTYPETEMPBUSSINESSCRM = 102, - KCHATTYPETEMPC2CFROMGROUP = 100, - KCHATTYPETEMPC2CFROMUNKNOWN = 99, - KCHATTYPETEMPFRIENDVERIFY = 101, - KCHATTYPETEMPNEARBYPRO = 119, - KCHATTYPETEMPPUBLICACCOUNT = 103, - KCHATTYPETEMPWPA = 117, - KCHATTYPEUNKNOWN = 0, - KCHATTYPEWEIYUN = 40, -} - -export interface PttElement { - canConvert2Text: boolean; - duration: number; // 秒数 - fileBizId: null; - fileId: number; // 0 - fileName: string; // "e4d09c784d5a2abcb2f9980bdc7acfe6.amr" - filePath: string; // "/Users//Library/Containers/com.tencent.qq/Data/Library/Application Support/QQ/nt_qq_a6b15c9820595d25a56c1633ce19ad40/nt_data/Ptt/2023-11/Ori/e4d09c784d5a2abcb2f9980bdc7acfe6.amr" - fileSize: string; // "4261" - fileSubId: string; // "0" - fileUuid: string; // "90j3z7rmRphDPrdVgP9udFBaYar#oK0TWZIV" - formatType: string; // 1 - invalidState: number; // 0 - md5HexStr: string; // "e4d09c784d5a2abcb2f9980bdc7acfe6" - playState: number; // 0 - progress: number; // 0 - text: string; // "" - transferStatus: number; // 0 - translateStatus: number; // 0 - voiceChangeType: number; // 0 - voiceType: number; // 0 - waveAmplitudes: number[]; -} - -export interface ArkElement { - bytesData: string; - linkInfo: null; - subElementType: null; -} - -export const IMAGE_HTTP_HOST = 'https://gchat.qpic.cn'; -export const IMAGE_HTTP_HOST_NT = 'https://multimedia.nt.qq.com.cn'; - -export interface PicElement { - md5HexStr?: string; - fileSize: number | string;//number - picWidth: number; - picHeight: number; - fileName: string; - sourcePath: string; - original: boolean; - picType: PicType; - picSubType?: PicSubType; - fileUuid: string; - fileSubId: string; - thumbFileSize: number; - summary: string; - thumbPath: Map; - originImageMd5?: string; - originImageUrl?: string; // http url, 没有host,host是https://gchat.qpic.cn/, 带download参数的是https://multimedia.nt.qq.com.cn -}; - -export enum GrayTipElementSubType { - INVITE_NEW_MEMBER = 12, - MEMBER_NEW_TITLE = 17 -} - -export interface GrayTipElement { - subElementType: GrayTipElementSubType; - revokeElement: { - operatorRole: string; - operatorUid: string; - operatorNick: string; - operatorRemark: string; - operatorMemRemark?: string; - wording: string; // 自定义的撤回提示语 - } - aioOpGrayTipElement: TipAioOpGrayTipElement; - groupElement: TipGroupElement; - xmlElement: { - content: string; - templId: string; - }; - jsonGrayTipElement: { - busiId?: number; - jsonStr: string; - }; -} - -export enum FaceType { - normal = 1, // 小黄脸 - normal2 = 2, // 新小黄脸, 从faceIndex 222开始? - dice = 3 // 骰子 -} -export enum FaceIndex { - dice = 358, - RPS = 359 // 石头剪刀布 -} -export interface FaceElement { - faceIndex: number; - faceType: FaceType; - faceText?: string; - packId?: string; - stickerId?: string; - sourceType?: number; - stickerType?: number; - resultId?: string; - surpriseId?: string; - randomType?: number; -} - -export interface MarketFaceElement { - emojiPackageId: number; - faceName: string; - emojiId: string; - key: string; -} - -export interface VideoElement { - filePath: string; - fileName: string; - videoMd5?: string; - thumbMd5?: string - fileTime?: number; // second - thumbSize?: number; // byte - fileFormat?: viedo_type; // 2表示mp4 参考下面条目 - fileSize?: string; // byte - thumbWidth?: number; - thumbHeight?: number; - busiType?: 0; // - subBusiType?: 0; // 未知 - thumbPath?: Map; - transferStatus?: 0; // 未知 - progress?: 0; // 下载进度? - invalidState?: 0; // 未知 - fileUuid?: string; // 可以用于下载链接? - fileSubId?: string; - fileBizId?: null; - originVideoMd5?: string; - import_rich_media_context?: null; - sourceVideoCodecFormat?: number; -} -// export enum busiType{ -// public static final int CREATOR_SHARE_ADV_XWORLD = 21; -// public static final int MINI_APP_MINI_GAME = 11; -// public static final int OFFICIAL_ACCOUNT_ADV = 4; -// public static final int OFFICIAL_ACCOUNT_ADV_GAME = 8; -// public static final int OFFICIAL_ACCOUNT_ADV_SHOP = 9; -// public static final int OFFICIAL_ACCOUNT_ADV_VIP = 7; -// public static final int OFFICIAL_ACCOUNT_LAYER_MASK_ADV = 14; -// public static final int OFFICIAL_ACCOUNT_SPORT = 13; -// public static final int OFFICIAL_ACCOUNT_TIAN_QI = 10; -// public static final int PC_QQTAB_ADV = 18; -// public static final int QIQIAOBAN_SDK = 15; -// public static final int QQ_CPS = 16; -// public static final int QQ_WALLET_CPS = 17; -// public static final int QZONE_FEEDS = 0; -// public static final int QZONE_PHOTO_TAIL = 2; -// public static final int QZONE_VIDEO_LAYER = 1; -// public static final int REWARD_GIFT_ADV = 6; -// public static final int REWARD_GROUPGIFT_ADV = 12; -// public static final int REWARD_PERSONAL_ADV = 5; -// public static final int WEISEE_OFFICIAL_ACCOUNT = 3; -// public static final int X_WORLD_CREATOR_ADV = 20; -// public static final int X_WORLD_QZONE_LAYER = 22; -// public static final int X_WORLD_VIDEO_ADV = 19; - -// } -// export enum CategoryBusiType { -// _KCateBusiTypeDefault = 0, -// _kCateBusiTypeFaceCluster = 1, -// _kCateBusiTypeLabelCluster = 4, -// _kCateBusiTypeMonthCluster = 16, -// _kCateBusiTypePoiCluster = 2, -// _kCateBusiTypeYearCluster = 8, -// } -export enum viedo_type { - VIDEO_FORMAT_AFS = 7, - VIDEO_FORMAT_AVI = 1, - VIDEO_FORMAT_MKV = 4, - VIDEO_FORMAT_MOD = 9, - VIDEO_FORMAT_MOV = 8, - VIDEO_FORMAT_MP4 = 2, - VIDEO_FORMAT_MTS = 11, - VIDEO_FORMAT_RM = 6, - VIDEO_FORMAT_RMVB = 5, - VIDEO_FORMAT_TS = 10, - VIDEO_FORMAT_WMV = 3, -} -export interface MarkdownElement { - content: string; -} - -export interface InlineKeyboardElementRowButton { - id: string; - label: string; - visitedLabel: string; - style: 1; // 未知 - type: 2; // 未知 - clickLimit: 0; // 未知 - unsupportTips: string; - data: string; - atBotShowChannelList: boolean; - permissionType: number; - specifyRoleIds: []; - specifyTinyids: []; - isReply: false; - anchor: 0; - enter: false; - subscribeDataTemplateIds: [] -} - -export interface InlineKeyboardElement { - rows: [{ - buttons: InlineKeyboardElementRowButton[] - }]; -} - -export interface TipAioOpGrayTipElement { // 这是什么提示来着? - operateType: number; - peerUid: string; - fromGrpCodeOfTmpChat: string; -} - -export enum TipGroupElementType { - memberIncrease = 1, - kicked = 3, // 被移出群 - ban = 8 -} -// public final class MemberAddShowType { -// public static final int KOTHERADD = 0; -// public static final int KOTHERADDBYOTHERQRCODE = 2; -// public static final int KOTHERADDBYYOURQRCODE = 3; -// public static final int KOTHERINVITEOTHER = 5; -// public static final int KOTHERINVITEYOU = 6; -// public static final int KYOUADD = 1; -// public static final int KYOUADDBYOTHERQRCODE = 4; -// public static final int KYOUALREADYMEMBER = 8; -// public static final int KYOUINVITEOTHER = 7; -// } -export interface TipGroupElement { - type: TipGroupElementType; // 1是表示有人加入群; 自己加入群也会收到这个 - role: 0; // 暂时不知 - groupName: string; // 暂时获取不到 - memberUid: string; - memberNick: string; - memberRemark: string; - adminUid: string; - adminNick: string; - adminRemark: string; - createGroup: null; - memberAdd?: { - showType: 1; - otherAdd: null; - otherAddByOtherQRCode: null; - otherAddByYourQRCode: null; - youAddByOtherQRCode: null; - otherInviteOther: null; - otherInviteYou: null; - youInviteOther: null - }; - shutUp?: { - curTime: string; - duration: string; // 禁言时间,秒 - admin: { - uid: string; - card: string; - name: string; - role: GroupMemberRole - }; - member: { - uid: string - card: string; - name: string; - role: GroupMemberRole - } - } -} - -export interface MultiForwardMsgElement { - xmlContent: string; // xml格式的消息内容 - resId: string; - fileName: string; -} - -export interface RawMessage { - parentMsgPeer: Peer; - parentMsgIdList:string[]; - id?: number;//扩展字段 用于处理OB11 ID - guildId: string; - msgRandom: string; - - - msgId: string; - - // 时间戳,秒 - msgTime: string; - - msgSeq: string; - msgType: number; - subMsgType: number; - senderUid: string; - senderUin: string; // 发送者QQ号 - peerUid: string; // 群号 或者 QQ uid - peerUin: string; // 群号 或者 发送者QQ号 - sendNickName: string; - sendMemberName?: string; // 发送者群名片 - chatType: ChatType; - sendStatus?: number; // 消息状态,别人发的2是已撤回,自己发的2是已发送 - recallTime: string; // 撤回时间, "0"是没有撤回 - records: RawMessage[]; - elements: { - elementId: string; - elementType: ElementType; - replyElement: { - sourceMsgIdInRecords: string; - senderUid: string; // 原消息发送者QQ号 - sourceMsgIsIncPic: boolean; // 原消息是否有图片 - sourceMsgText: string; - replayMsgSeq: string; // 源消息的msgSeq,可以通过这个找到源消息的msgId - }; - textElement: { - atType: AtType; - atUid: string; // QQ号 - content: string; - atNtUid: string; // uid号 - }; - picElement: PicElement; - pttElement: PttElement; - arkElement: ArkElement; - grayTipElement: GrayTipElement; - faceElement: FaceElement; - videoElement: VideoElement; - fileElement: FileElement; - marketFaceElement: MarketFaceElement; - inlineKeyboardElement: InlineKeyboardElement; - markdownElement: MarkdownElement; - multiForwardMsgElement: MultiForwardMsgElement; - }[]; -} diff --git a/src/core/src/entities/notify.ts b/src/core/src/entities/notify.ts deleted file mode 100644 index 6041eab7..00000000 --- a/src/core/src/entities/notify.ts +++ /dev/null @@ -1,116 +0,0 @@ -export enum GroupNotifyTypes { - INVITE_ME = 1, - INVITED_JOIN = 4, // 有人接受了邀请入群 - JOIN_REQUEST = 7, - ADMIN_SET = 8, - KICK_MEMBER = 9, - MEMBER_EXIT = 11, // 主动退出 - ADMIN_UNSET = 12, - ADMIN_UNSET_OTHER = 13, // 其他人取消管理员 -} - -export interface GroupNotifies { - doubt: boolean; - nextStartSeq: string; - notifies: GroupNotify[]; -} - -export enum GroupNotifyStatus { - IGNORE = 0, - WAIT_HANDLE = 1, - APPROVE = 2, - REJECT = 3 -} - -export interface GroupNotify { - time: number; // 自己添加的字段,时间戳,毫秒, 用于判断收到短时间内收到重复的notify - seq: string; // 唯一标识符,转成数字再除以1000应该就是时间戳? - type: GroupNotifyTypes; - status: GroupNotifyStatus; // 0是已忽略?,1是未处理,2是已同意 - group: { groupCode: string; groupName: string }; - user1: { uid: string; nickName: string }; // 被设置管理员的人 - user2: { uid: string; nickName: string }; // 操作者 - actionUser: { uid: string; nickName: string }; //未知 - actionTime: string; - invitationExt: { - srcType: number; // 0?未知 - groupCode: string; waitStatus: number - }; - postscript: string; // 加群用户填写的验证信息 - repeatSeqs: []; - warningTips: string -} - -export enum GroupRequestOperateTypes { - approve = 1, - reject = 2 -} -export enum BuddyReqType { - KMEINITIATOR, - KPEERINITIATOR, - KMEAGREED, - KMEAGREEDANDADDED, - KPEERAGREED, - KPEERAGREEDANDADDED, - KPEERREFUSED, - KMEREFUSED, - KMEIGNORED, - KMEAGREEANYONE, - KMESETQUESTION, - KMEAGREEANDADDFAILED, - KMSGINFO, - KMEINITIATORWAITPEERCONFIRM -} -export interface FriendRequest { - isInitiator?: boolean; - isDecide: boolean; - friendUid: string; - reqType: BuddyReqType, - reqTime: string; // 时间戳;秒 - extWords: string; // 申请人填写的验证消息 - isUnread: boolean; - friendNick: string; - sourceId: number; - groupCode: string -} - -export interface FriendRequestNotify { - unreadNums: number; - buddyReqs: FriendRequest[]; -} -export enum MemberExtSourceType { - DEFAULTTYPE = 0, - TITLETYPE = 1, - NEWGROUPTYPE = 2, -} -export interface GroupExtParam { - groupCode: string - seq: string - beginUin: string - dataTime: string - uinList: Array - uinNum: string - groupType: string - richCardNameVer: string - sourceType: MemberExtSourceType - memberExtFilter: { - memberLevelInfoUin: number - memberLevelInfoPoint: number - memberLevelInfoActiveDay: number - memberLevelInfoLevel: number - memberLevelInfoName: number - levelName: number - dataTime: number - userShowFlag: number - sysShowFlag: number - timeToUpdate: number - nickName: number - specialTitle: number - levelNameNew: number - userShowFlagNew: number - msgNeedField: number - cmdUinFlagExt3Grocery: number - memberIcon: number - memberInfoSeq: number - } -} \ No newline at end of file diff --git a/src/core/src/entities/user.ts b/src/core/src/entities/user.ts deleted file mode 100644 index f80c128b..00000000 --- a/src/core/src/entities/user.ts +++ /dev/null @@ -1,347 +0,0 @@ -export enum Sex { - male = 1, - female = 2, - unknown = 255, -} -export interface BuddyCategoryType { - categoryId: number; - categroyName: string; - categroyMbCount: number; - buddyList: User[]; -} -export interface CoreInfo { - uid: string; - uin: string; - nick: string; - remark: string; -} - -export interface BaseInfo { - qid: string; - longNick: string; - birthday_year: number; - birthday_month: number; - birthday_day: number; - age: number; - sex: number; - eMail: string; - phoneNum: string; - categoryId: number; - richTime: number; - richBuffer: string; -} - -interface MusicInfo { - buf: string; -} - -interface VideoBizInfo { - cid: string; - tvUrl: string; - synchType: string; -} - -interface VideoInfo { - name: string; -} - -interface ExtOnlineBusinessInfo { - buf: string; - customStatus: any; - videoBizInfo: VideoBizInfo; - videoInfo: VideoInfo; -} - -interface ExtBuffer { - buf: string; -} - -interface UserStatus { - uid: string; - uin: string; - status: number; - extStatus: number; - batteryStatus: number; - termType: number; - netType: number; - iconType: number; - customStatus: any; - setTime: string; - specialFlag: number; - abiFlag: number; - eNetworkType: number; - showName: string; - termDesc: string; - musicInfo: MusicInfo; - extOnlineBusinessInfo: ExtOnlineBusinessInfo; - extBuffer: ExtBuffer; -} - -interface PrivilegeIcon { - jumpUrl: string; - openIconList: any[]; - closeIconList: any[]; -} - -interface VasInfo { - vipFlag: boolean; - yearVipFlag: boolean; - svipFlag: boolean; - vipLevel: number; - bigClub: boolean; - bigClubLevel: number; - nameplateVipType: number; - grayNameplateFlag: number; - superVipTemplateId: number; - diyFontId: number; - pendantId: number; - pendantDiyId: number; - faceId: number; - vipFont: number; - vipFontType: number; - magicFont: number; - fontEffect: number; - newLoverDiamondFlag: number; - extendNameplateId: number; - diyNameplateIDs: any[]; - vipStartFlag: number; - vipDataFlag: number; - gameNameplateId: string; - gameLastLoginTime: string; - gameRank: number; - gameIconShowFlag: boolean; - gameCardId: string; - vipNameColorId: string; - privilegeIcon: PrivilegeIcon; -} - -interface RelationFlags { - topTime: string; - isBlock: boolean; - isMsgDisturb: boolean; - isSpecialCareOpen: boolean; - isSpecialCareZone: boolean; - ringId: string; - isBlocked: boolean; - recommendImgFlag: number; - disableEmojiShortCuts: number; - qidianMasterFlag: number; - qidianCrewFlag: number; - qidianCrewFlag2: number; - isHideQQLevel: number; - isHidePrivilegeIcon: number; -} - - -interface CommonExt { - constellation: number; - shengXiao: number; - kBloodType: number; - homeTown: string; - makeFriendCareer: number; - pos: string; - college: string; - country: string; - province: string; - city: string; - postCode: string; - address: string; - regTime: number; - interest: string; - labels: any[]; - qqLevel: QQLevel; -} - -interface Pic { - picId: string; - picTime: number; - picUrlMap: Record; -} - -interface PhotoWall { - picList: Pic[]; -} - -export interface SimpleInfo { - uid?: string; - uin?: string; - coreInfo: CoreInfo; - baseInfo: BaseInfo; - status: UserStatus | null; - vasInfo: VasInfo | null; - relationFlags: RelationFlags | null; - otherFlags: any | null; - intimate: any | null; -} -export interface FriendV2 extends SimpleInfo { - categoryId?: number; - categroyName?: string; -} -export interface UserDetailInfoListenerArg { - uid: string; - uin: string; - simpleInfo: SimpleInfo; - commonExt: CommonExt; - photoWall: PhotoWall; -} -export interface ModifyProfileParams { - nick: string, - longNick: string, - sex: Sex, - birthday: { birthday_year: string, birthday_month: string, birthday_day: string }, - location: any//undefined -} - -export interface BuddyProfileLikeReq { - friendUids: string[]; - basic: number; - vote: number; - favorite: number; - userProfile: number; - type: number; - start: number; - limit: number; -} -export interface QQLevel { - crownNum: number; - sunNum: number; - moonNum: number; - starNum: number -} -export interface User { - uid: string; // 加密的字符串 - uin: string; // QQ号 - nick: string; - avatarUrl?: string; - longNick?: string; // 签名 - remark?: string; - sex?: Sex; - qqLevel?: QQLevel; - qid?: string - birthday_year?: number; - birthday_month?: number; - birthday_day?: number; - topTime?: string; - constellation?: number; - shengXiao?: number; - kBloodType?: number; - homeTown?: string; //"0-0-0"; - makeFriendCareer?: number; - pos?: string; - eMail?: string - phoneNum?: string; - college?: string; - country?: string; - province?: string; - city?: string; - postCode?: string; - address?: string; - isBlock?: boolean; - isSpecialCareOpen?: boolean; - isSpecialCareZone?: boolean; - ringId?: string; - regTime?: number; - interest?: string; - labels?: string[]; - isHideQQLevel?: number; - privilegeIcon?: { - jumpUrl: string; - openIconList: unknown[]; - closeIconList: unknown[] - }; - photoWall?: { - picList: unknown[] - }; - vipFlag?: boolean; - yearVipFlag?: boolean; - svipFlag?: boolean; - vipLevel?: number; - status?: number; - qidianMasterFlag?: number; - qidianCrewFlag?: number; - qidianCrewFlag2?: number; - extStatus?: number; - recommendImgFlag?: number; - disableEmojiShortCuts?: number; - pendantId?: string; -} - -export interface SelfInfo extends User { - online?: boolean; -} - -export interface Friend extends User { } - -export enum BizKey { - KPRIVILEGEICON, - KPHOTOWALL -} -export interface UserDetailInfoByUinV2 { - result: number, - errMsg: string, - detail: { - uid: string, - uin: string, - simpleInfo: SimpleInfo, - commonExt: CommonExt, - photoWall: null - } -} -export interface UserDetailInfoByUin { - result: number, - errMsg: string, - info: { - uid: string,//这个没办法用 - qid: string, - uin: string, - nick: string, - remark: string, - longNick: string, - avatarUrl: string, - birthday_year: number, - birthday_month: number, - birthday_day: number, - sex: number,//0 - topTime: string, - constellation: number, - shengXiao: number, - kBloodType: number, - homeTown: string, - makeFriendCareer: number, - pos: string, - eMail: string, - phoneNum: string, - college: string, - country: string, - province: string, - city: string, - postCode: string, - address: string, - isBlock: boolean, - isSpecialCareOpen: boolean, - isSpecialCareZone: boolean, - ringId: string, - regTime: number, - interest: string, - termType: number, - labels: any[], - qqLevel: { crownNum: number, sunNum: number, moonNum: number, starNum: number }, - isHideQQLevel: number, - privilegeIcon: { jumpUrl: string, openIconList: any[], closeIconList: any[] }, - isHidePrivilegeIcon: number, - photoWall: { picList: any[] }, - vipFlag: boolean, - yearVipFlag: boolean, - svipFlag: boolean, - vipLevel: number, - status: number, - qidianMasterFlag: number, - qidianCrewFlag: number, - qidianCrewFlag2: number, - extStatus: number, - recommendImgFlag: number, - disableEmojiShortCuts: number, - pendantId: string, - vipNameColorId: string - } -} \ No newline at end of file diff --git a/src/core/src/external/appid.json b/src/core/src/external/appid.json deleted file mode 100644 index 44fd31c7..00000000 --- a/src/core/src/external/appid.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "3.1.2-13107": { - "appid": 537146866, - "qua": "V1_LNX_NQ_3.1.2-13107_RDM_B" - }, - "3.2.10-25765": { - "appid": 537234773, - "qua": "V1_LNX_NQ_3.2.10_25765_GW_B" - }, - "3.2.12-26702": { - "appid": 537237950, - "qua": "V1_LNX_NQ_3.2.12_26702_GW_B" - }, - "3.2.12-26740": { - "appid": 537237950, - "qua": "V1_WIN_NQ_9.9.15_26740_GW_B" - }, - "9.9.11-24815": { - "appid": 537226656, - "qua": "V1_WIN_NQ_9.9.11_24815_GW_B" - }, - "9.9.12-25493": { - "appid": 537231759, - "qua": "V1_WIN_NQ_9.9.12_25493_GW_B" - }, - "9.9.12-25765": { - "appid": 537234702, - "qua": "V1_WIN_NQ_9.9.12_25765_GW_B" - }, - "9.9.12-26299": { - "appid": 537234826, - "qua": "V1_WIN_NQ_9.9.12_26299_GW_B" - }, - "9.9.12-26339": { - "appid": 537234826, - "qua": "V1_WIN_NQ_9.9.12_26339_GW_B" - }, - "9.9.12-26466": { - "appid": 537234826, - "qua": "V1_WIN_NQ_9.9.12_26466_GW_B" - }, - "9.9.15-26702": { - "appid": 537237765, - "qua": "V1_WIN_NQ_9.9.15_26702_GW_B" - }, - "9.9.15-26740": { - "appid": 537237765, - "qua": "V1_WIN_NQ_9.9.15_26702_GW_B" - } -} \ No newline at end of file diff --git a/src/core/src/index.ts b/src/core/src/index.ts deleted file mode 100644 index 4dcf5fe8..00000000 --- a/src/core/src/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import QQWrapper from './wrapper'; - -export * from './adapters'; -export * from './apis'; -export * from './entities'; -export * from './listeners'; -export * from './services'; - -export * as Adapters from './adapters'; -export * as APIs from './apis'; -export * as Entities from './entities'; -export * as Listeners from './listeners'; -export * as Services from './services'; -export { QQWrapper as Wrapper }; -export * as WrapperInterface from './wrapper'; -export * as SessionConfig from './sessionConfig'; - -export { napCatCore } from './core'; diff --git a/src/core/src/listeners/NodeIKernelBuddyListener.ts b/src/core/src/listeners/NodeIKernelBuddyListener.ts deleted file mode 100644 index 1a15bcc0..00000000 --- a/src/core/src/listeners/NodeIKernelBuddyListener.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { BuddyCategoryType, FriendRequestNotify } from '@/core/entities'; - -export type OnBuddyChangeParams = BuddyCategoryType[] - -interface IBuddyListener { - onBuddyListChangedV2(arg: unknown): void,//V2版本 还没兼容 - - onBuddyListChange(arg: OnBuddyChangeParams): void, - - onBuddyInfoChange(arg: unknown): void, - - onBuddyDetailInfoChange(arg: unknown): void, - - onNickUpdated(arg: unknown): void, - - onBuddyRemarkUpdated(arg: unknown): void, - - onAvatarUrlUpdated(arg: unknown): void, - - onBuddyReqChange(arg: FriendRequestNotify): void, - - onBuddyReqUnreadCntChange(arg: unknown): void, - - onCheckBuddySettingResult(arg: unknown): void, - - onAddBuddyNeedVerify(arg: unknown): void, - - onSmartInfos(arg: unknown): void, - - onSpacePermissionInfos(arg: unknown): void, - - onDoubtBuddyReqChange(arg: unknown): void, - - onDoubtBuddyReqUnreadNumChange(arg: unknown): void, - - onBlockChanged(arg: unknown): void, - - onAddMeSettingChanged(arg: unknown): void, - - onDelBatchBuddyInfos(arg: unknown): void -} - -export interface NodeIKernelBuddyListener extends IBuddyListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(listener: IBuddyListener): NodeIKernelBuddyListener; -} - -export class BuddyListener implements IBuddyListener { - onBuddyListChangedV2(arg: unknown): void { - //throw new Error('Method not implemented.'); - } - onAddBuddyNeedVerify(arg: unknown) { - } - - onAddMeSettingChanged(arg: unknown) { - } - - onAvatarUrlUpdated(arg: unknown) { - } - - onBlockChanged(arg: unknown) { - } - - onBuddyDetailInfoChange(arg: unknown) { - } - - onBuddyInfoChange(arg: unknown) { - } - - onBuddyListChange(arg: OnBuddyChangeParams): void { - } - - onBuddyRemarkUpdated(arg: unknown): void { - } - - onBuddyReqChange(arg: FriendRequestNotify): void { - } - - onBuddyReqUnreadCntChange(arg: unknown): void { - } - - onCheckBuddySettingResult(arg: unknown): void { - } - - onDelBatchBuddyInfos(arg: unknown): void { - } - - onDoubtBuddyReqChange(arg: unknown): void { - } - - onDoubtBuddyReqUnreadNumChange(arg: unknown): void { - } - - onNickUpdated(arg: unknown): void { - } - - onSmartInfos(arg: unknown): void { - } - - onSpacePermissionInfos(arg: unknown): void { - } -} diff --git a/src/core/src/listeners/NodeIKernelFileAssistantListener.ts b/src/core/src/listeners/NodeIKernelFileAssistantListener.ts deleted file mode 100644 index 8d7a604f..00000000 --- a/src/core/src/listeners/NodeIKernelFileAssistantListener.ts +++ /dev/null @@ -1,27 +0,0 @@ -export interface IKernelFileAssistantListener { - onFileStatusChanged(...args: unknown[]): unknown; - - onSessionListChanged(...args: unknown[]): unknown; - - onSessionChanged(...args: unknown[]): unknown; - - onFileListChanged(...args: unknown[]): unknown; - - onFileSearch(...args: unknown[]): unknown; -} -export interface NodeIKernelFileAssistantListener extends IKernelFileAssistantListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(adapter: IKernelFileAssistantListener): NodeIKernelFileAssistantListener; -} - -export class KernelFileAssistantListener implements IKernelFileAssistantListener { - onFileStatusChanged(...args: unknown[]) { } - - onSessionListChanged(...args: unknown[]) { } - - onSessionChanged(...args: unknown[]) { } - - onFileListChanged(...args: unknown[]) { } - - onFileSearch(...args: unknown[]) { } -} \ No newline at end of file diff --git a/src/core/src/listeners/NodeIKernelGroupListener.ts b/src/core/src/listeners/NodeIKernelGroupListener.ts deleted file mode 100644 index 9434d4e4..00000000 --- a/src/core/src/listeners/NodeIKernelGroupListener.ts +++ /dev/null @@ -1,240 +0,0 @@ -import { Group, GroupListUpdateType, GroupMember, GroupNotify } from '@/core/entities'; - -interface IGroupListener { - onGroupListUpdate(updateType: GroupListUpdateType, groupList: Group[]): void; - - onGroupExtListUpdate(...args: unknown[]): void; - - onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]): void; - - onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]): void; - - onGroupNotifiesUnreadCountUpdated(...args: unknown[]): void; - - onGroupDetailInfoChange(...args: unknown[]): void; - - onGroupAllInfoChange(...args: unknown[]): void; - - onGroupsMsgMaskResult(...args: unknown[]): void; - - onGroupConfMemberChange(...args: unknown[]): void; - - onGroupBulletinChange(...args: unknown[]): void; - - onGetGroupBulletinListResult(...args: unknown[]): void; - - onMemberListChange(arg: { - sceneId: string, - ids: string[], - infos: Map, - finish: boolean, - hasRobot: boolean - }): void; - - onMemberInfoChange(groupCode: string, changeType: number, members: Map): void; - - onSearchMemberChange(...args: unknown[]): void; - - onGroupBulletinRichMediaDownloadComplete(...args: unknown[]): void; - - onGroupBulletinRichMediaProgressUpdate(...args: unknown[]): void; - - onGroupStatisticInfoChange(...args: unknown[]): void; - - onJoinGroupNotify(...args: unknown[]): void; - - onShutUpMemberListChanged(...args: unknown[]): void; - - onGroupBulletinRemindNotify(...args: unknown[]): void; - - onGroupFirstBulletinNotify(...args: unknown[]): void; - - onJoinGroupNoVerifyFlag(...args: unknown[]): void; - - onGroupArkInviteStateResult(...args: unknown[]): void; - // 发现于Win 9.9.9 23159 - onGroupMemberLevelInfoChange(...args: unknown[]): void; -} - -export interface NodeIKernelGroupListener extends IGroupListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(listener: IGroupListener): NodeIKernelGroupListener; -} - -export class GroupListener implements IGroupListener { - // 发现于Win 9.9.9 23159 - onGroupMemberLevelInfoChange(...args: unknown[]): void { - - } - onGetGroupBulletinListResult(...args: unknown[]) { - } - - onGroupAllInfoChange(...args: unknown[]) { - } - - onGroupBulletinChange(...args: unknown[]) { - } - - onGroupBulletinRemindNotify(...args: unknown[]) { - } - - onGroupArkInviteStateResult(...args: unknown[]) { - } - - onGroupBulletinRichMediaDownloadComplete(...args: unknown[]) { - } - - onGroupConfMemberChange(...args: unknown[]) { - } - - onGroupDetailInfoChange(...args: unknown[]) { - } - - onGroupExtListUpdate(...args: unknown[]) { - } - - onGroupFirstBulletinNotify(...args: unknown[]) { - } - - onGroupListUpdate(updateType: GroupListUpdateType, groupList: Group[]) { - } - - onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]) { - } - - onGroupBulletinRichMediaProgressUpdate(...args: unknown[]) { - } - - onGroupNotifiesUnreadCountUpdated(...args: unknown[]) { - } - - onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]) { - } - - onGroupsMsgMaskResult(...args: unknown[]) { - } - - onGroupStatisticInfoChange(...args: unknown[]) { - } - - onJoinGroupNotify(...args: unknown[]) { - } - - onJoinGroupNoVerifyFlag(...args: unknown[]) { - } - - onMemberInfoChange(groupCode: string, changeType: number, members: Map) { - } - - onMemberListChange(arg: { - sceneId: string, - ids: string[], - infos: Map, // uid -> GroupMember - finish: boolean, - hasRobot: boolean - }) { - } - - onSearchMemberChange(...args: unknown[]) { - } - - onShutUpMemberListChanged(...args: unknown[]) { - } -} - -export class DebugGroupListener implements IGroupListener { - onGroupMemberLevelInfoChange(...args: unknown[]): void { - console.log('onGroupMemberLevelInfoChange:', ...args); - } - onGetGroupBulletinListResult(...args: unknown[]) { - console.log('onGetGroupBulletinListResult:', ...args); - } - - onGroupAllInfoChange(...args: unknown[]) { - console.log('onGroupAllInfoChange:', ...args); - } - - onGroupBulletinChange(...args: unknown[]) { - console.log('onGroupBulletinChange:', ...args); - } - - onGroupBulletinRemindNotify(...args: unknown[]) { - console.log('onGroupBulletinRemindNotify:', ...args); - } - - onGroupArkInviteStateResult(...args: unknown[]) { - console.log('onGroupArkInviteStateResult:', ...args); - } - - onGroupBulletinRichMediaDownloadComplete(...args: unknown[]) { - console.log('onGroupBulletinRichMediaDownloadComplete:', ...args); - } - - onGroupConfMemberChange(...args: unknown[]) { - console.log('onGroupConfMemberChange:', ...args); - } - - onGroupDetailInfoChange(...args: unknown[]) { - console.log('onGroupDetailInfoChange:', ...args); - } - - onGroupExtListUpdate(...args: unknown[]) { - console.log('onGroupExtListUpdate:', ...args); - } - - onGroupFirstBulletinNotify(...args: unknown[]) { - console.log('onGroupFirstBulletinNotify:', ...args); - } - - onGroupListUpdate(...args: unknown[]) { - console.log('onGroupListUpdate:', ...args); - } - - onGroupNotifiesUpdated(...args: unknown[]) { - console.log('onGroupNotifiesUpdated:', ...args); - } - - onGroupBulletinRichMediaProgressUpdate(...args: unknown[]) { - console.log('onGroupBulletinRichMediaProgressUpdate:', ...args); - } - - onGroupNotifiesUnreadCountUpdated(...args: unknown[]) { - console.log('onGroupNotifiesUnreadCountUpdated:', ...args); - } - - onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]) { - console.log('onGroupSingleScreenNotifies:'); - } - - onGroupsMsgMaskResult(...args: unknown[]) { - console.log('onGroupsMsgMaskResult:', ...args); - } - - onGroupStatisticInfoChange(...args: unknown[]) { - console.log('onGroupStatisticInfoChange:', ...args); - } - - onJoinGroupNotify(...args: unknown[]) { - console.log('onJoinGroupNotify:', ...args); - } - - onJoinGroupNoVerifyFlag(...args: unknown[]) { - console.log('onJoinGroupNoVerifyFlag:', ...args); - } - - onMemberInfoChange(groupCode: string, changeType: number, members: Map) { - console.log('onMemberInfoChange:', groupCode, changeType, members); - } - - onMemberListChange(...args: unknown[]) { - console.log('onMemberListChange:', ...args); - } - - onSearchMemberChange(...args: unknown[]) { - console.log('onSearchMemberChange:', ...args); - } - - onShutUpMemberListChanged(...args: unknown[]) { - console.log('onShutUpMemberListChanged:', ...args); - } -} diff --git a/src/core/src/listeners/NodeIKernelLoginListener.ts b/src/core/src/listeners/NodeIKernelLoginListener.ts deleted file mode 100644 index 4c799ebf..00000000 --- a/src/core/src/listeners/NodeIKernelLoginListener.ts +++ /dev/null @@ -1,108 +0,0 @@ -export interface IKernelLoginListener { - onLoginConnected(...args: any[]): void; - - onLoginDisConnected(...args: any[]): void; - - onLoginConnecting(...args: any[]): void; - - onQRCodeGetPicture(...args: any[]): void; - - onQRCodeLoginPollingStarted(...args: any[]): void; - - onQRCodeSessionUserScaned(...args: any[]): void; - - onQRCodeLoginSucceed(...args: any[]): void; - - onQRCodeSessionFailed(...args: any[]): void; - - onLoginFailed(...args: any[]): void; - - onLogoutSucceed(...args: any[]): void; - - onLogoutFailed(...args: any[]): void; - - onUserLoggedIn(...args: any[]): void; - - onQRCodeSessionQuickLoginFailed(...args: any[]): void; - - onPasswordLoginFailed(...args: any[]): void; - - OnConfirmUnusualDeviceFailed(...args: any[]): void; - - onQQLoginNumLimited(...args: any[]): void; - - onLoginState(...args: any[]): void; -} - -export interface NodeIKernelLoginListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(listener: IKernelLoginListener): NodeIKernelLoginListener; -} - -export class LoginListener implements IKernelLoginListener { - onLoginConnected(...args: any[]): void { - } - - onLoginDisConnected(...args: any[]): void { - } - - onLoginConnecting(...args: any[]): void { - } - - onQRCodeGetPicture(arg: { pngBase64QrcodeData: string, qrcodeUrl: string }): void { - // let base64Data: string = arg.pngBase64QrcodeData - // base64Data = base64Data.split("data:image/png;base64,")[1] - // let buffer = Buffer.from(base64Data, 'base64') - // console.log("onQRCodeGetPicture", arg); - } - - onQRCodeLoginPollingStarted(...args: any[]): void { - } - - onQRCodeSessionUserScaned(...args: any[]): void { - } - - onQRCodeLoginSucceed(arg: QRCodeLoginSucceedResult): void { - } - - onQRCodeSessionFailed(...args: any[]): void { - } - - onLoginFailed(...args: any[]): void { - } - - onLogoutSucceed(...args: any[]): void { - } - - onLogoutFailed(...args: any[]): void { - } - - onUserLoggedIn(...args: any[]): void { - } - - onQRCodeSessionQuickLoginFailed(...args: any[]): void { - } - - onPasswordLoginFailed(...args: any[]): void { - } - - OnConfirmUnusualDeviceFailed(...args: any[]): void { - } - - onQQLoginNumLimited(...args: any[]): void { - } - - onLoginState(...args: any[]): void { - } -} - -export interface QRCodeLoginSucceedResult { - account: string; - mainAccount: string; - uin: string; //拿UIN - uid: string; //拿UID - nickName: string; //一般是空的 拿不到 - gender: number; - age: number; - faceUrl: string;//一般是空的 拿不到 -} diff --git a/src/core/src/listeners/NodeIKernelMsgListener.ts b/src/core/src/listeners/NodeIKernelMsgListener.ts deleted file mode 100644 index 31e962f1..00000000 --- a/src/core/src/listeners/NodeIKernelMsgListener.ts +++ /dev/null @@ -1,512 +0,0 @@ -import { ChatType, RawMessage } from '@/core/entities'; - -export interface OnRichMediaDownloadCompleteParams { - fileModelId: string, - msgElementId: string, - msgId: string, - fileId: string, - fileProgress: string, // '0' - fileSpeed: string, // '0' - fileErrCode: string, // '0' - fileErrMsg: string, - fileDownType: number, // 暂时未知 - thumbSize: number, - filePath: string, - totalSize: string, - trasferStatus: number, - step: number, - commonFileInfo: unknown | null, - fileSrvErrCode: string, - clientMsg: string, - businessId: number, - userTotalSpacePerDay: unknown | null, - userUsedSpacePerDay: unknown | null -} -export interface onGroupFileInfoUpdateParamType { - retCode: number - retMsg: string - clientWording: string - isEnd: boolean - item: Array - allFileCount: string - nextIndex: string - reqId: string -} -// { -// sessionType: 1, -// chatType: 100, -// peerUid: 'u_PVQ3tl6K78xxxx', -// groupCode: '809079648', -// fromNick: '拾xxxx, -// sig: '0x' -// } -export interface TempOnRecvParams { - sessionType: number,//1 - chatType: ChatType,//100 - peerUid: string,//uid - groupCode: string,//gc - fromNick: string,//gc name - sig: string, - -} -export interface IKernelMsgListener { - onAddSendMsg(msgRecord: RawMessage): void; - - onBroadcastHelperDownloadComplete(broadcastHelperTransNotifyInfo: unknown): void; - - onBroadcastHelperProgressUpdate(broadcastHelperTransNotifyInfo: unknown): void; - - onChannelFreqLimitInfoUpdate(contact: unknown, z: unknown, freqLimitInfo: unknown): void; - - onContactUnreadCntUpdate(hashMap: unknown): void; - - onCustomWithdrawConfigUpdate(customWithdrawConfig: unknown): void; - - onDraftUpdate(contact: unknown, arrayList: unknown, j2: unknown): void; - - onEmojiDownloadComplete(emojiNotifyInfo: unknown): void; - - onEmojiResourceUpdate(emojiResourceInfo: unknown): void; - - onFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown): void; - - onFileMsgCome(arrayList: unknown): void; - - onFirstViewDirectMsgUpdate(firstViewDirectMsgNotifyInfo: unknown): void; - - onFirstViewGroupGuildMapping(arrayList: unknown): void; - - onGrabPasswordRedBag(i2: unknown, str: unknown, i3: unknown, recvdOrder: unknown, msgRecord: unknown): void; - - onGroupFileInfoAdd(groupItem: unknown): void; - - onGroupFileInfoUpdate(groupFileListResult: onGroupFileInfoUpdateParamType): void; - - onGroupGuildUpdate(groupGuildNotifyInfo: unknown): void; - - onGroupTransferInfoAdd(groupItem: unknown): void; - - onGroupTransferInfoUpdate(groupFileListResult: unknown): void; - - onGuildInteractiveUpdate(guildInteractiveNotificationItem: unknown): void; - - onGuildMsgAbFlagChanged(guildMsgAbFlag: unknown): void; - - onGuildNotificationAbstractUpdate(guildNotificationAbstractInfo: unknown): void; - - onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: unknown): void; - - onHitEmojiKeywordResult(hitRelatedEmojiWordsResult: unknown): void; - - onHitRelatedEmojiResult(relatedWordEmojiInfo: unknown): void; - - onImportOldDbProgressUpdate(importOldDbMsgNotifyInfo: unknown): void; - - onInputStatusPush(inputStatusInfo: unknown): void; - - onKickedOffLine(kickedInfo: unknown): void; - - onLineDev(arrayList: unknown): void; - - onLogLevelChanged(j2: unknown): void; - - onMsgAbstractUpdate(arrayList: unknown): void; - - onMsgBoxChanged(arrayList: unknown): void; - - onMsgDelete(contact: unknown, arrayList: unknown): void; - - onMsgEventListUpdate(hashMap: unknown): void; - - onMsgInfoListAdd(arrayList: unknown): void; - - onMsgInfoListUpdate(msgList: RawMessage[]): void; - - onMsgQRCodeStatusChanged(i2: unknown): void; - - onMsgRecall(i2: unknown, str: unknown, j2: unknown): void; - - onMsgSecurityNotify(msgRecord: unknown): void; - - onMsgSettingUpdate(msgSetting: unknown): void; - - onNtFirstViewMsgSyncEnd(): void; - - onNtMsgSyncEnd(): void; - - onNtMsgSyncStart(): void; - - onReadFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown): void; - - onRecvGroupGuildFlag(i2: unknown): void; - - onRecvMsg(...arrayList: unknown[]): void; - - onRecvMsgSvrRspTransInfo(j2: unknown, contact: unknown, i2: unknown, i3: unknown, str: unknown, bArr: unknown): void; - - onRecvOnlineFileMsg(arrayList: unknown): void; - - onRecvS2CMsg(arrayList: unknown): void; - - onRecvSysMsg(arrayList: unknown): void; - - onRecvUDCFlag(i2: unknown): void; - - onRichMediaDownloadComplete(fileTransNotifyInfo: OnRichMediaDownloadCompleteParams): void; - - onRichMediaProgerssUpdate(fileTransNotifyInfo: unknown): void; - - onRichMediaUploadComplete(fileTransNotifyInfo: unknown): void; - - onSearchGroupFileInfoUpdate(searchGroupFileResult: - { - result: { - retCode: number, - retMsg: string, - clientWording: string - }, - syncCookie: string, - totalMatchCount: number, - ownerMatchCount: number, - isEnd: boolean, - reqId: number, - item: Array<{ - groupCode: string, - groupName: string, - uploaderUin: string, - uploaderName: string, - matchUin: string, - matchWords: Array, - fileNameHits: Array<{ - start: number, - end: number - }>, - fileModelId: string, - fileId: string, - fileName: string, - fileSize: string, - busId: number, - uploadTime: number, - modifyTime: number, - deadTime: number, - downloadTimes: number, - localPath: string - }> - }): void; - - onSendMsgError(j2: unknown, contact: unknown, i2: unknown, str: unknown): void; - - onSysMsgNotification(i2: unknown, j2: unknown, j3: unknown, arrayList: unknown): void; - - onTempChatInfoUpdate(tempChatInfo: TempOnRecvParams): void; - - onUnreadCntAfterFirstView(hashMap: unknown): void; - - onUnreadCntUpdate(hashMap: unknown): void; - - onUserChannelTabStatusChanged(z: unknown): void; - - onUserOnlineStatusChanged(z: unknown): void; - - onUserTabStatusChanged(arrayList: unknown): void; - - onlineStatusBigIconDownloadPush(i2: unknown, j2: unknown, str: unknown): void; - - onlineStatusSmallIconDownloadPush(i2: unknown, j2: unknown, str: unknown): void; - - // 第一次发现于Linux - onUserSecQualityChanged(...args: unknown[]): void; - - onMsgWithRichLinkInfoUpdate(...args: unknown[]): void; - - onRedTouchChanged(...args: unknown[]): void; - - // 第一次发现于Win 9.9.9 23159 - onBroadcastHelperProgerssUpdate(...args: unknown[]): void; - -} - -export interface NodeIKernelMsgListener extends IKernelMsgListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(listener: IKernelMsgListener): NodeIKernelMsgListener; -} - - -export class MsgListener implements IKernelMsgListener { - onAddSendMsg(msgRecord: RawMessage) { - - } - - onBroadcastHelperDownloadComplete(broadcastHelperTransNotifyInfo: unknown) { - - } - - onBroadcastHelperProgressUpdate(broadcastHelperTransNotifyInfo: unknown) { - - } - - onChannelFreqLimitInfoUpdate(contact: unknown, z: unknown, freqLimitInfo: unknown) { - - } - - onContactUnreadCntUpdate(hashMap: unknown) { - - } - - onCustomWithdrawConfigUpdate(customWithdrawConfig: unknown) { - - } - - onDraftUpdate(contact: unknown, arrayList: unknown, j2: unknown) { - - } - - onEmojiDownloadComplete(emojiNotifyInfo: unknown) { - - } - - onEmojiResourceUpdate(emojiResourceInfo: unknown) { - - } - - onFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown) { - - } - - onFileMsgCome(arrayList: unknown) { - - } - - onFirstViewDirectMsgUpdate(firstViewDirectMsgNotifyInfo: unknown) { - - } - - onFirstViewGroupGuildMapping(arrayList: unknown) { - - } - - onGrabPasswordRedBag(i2: unknown, str: unknown, i3: unknown, recvdOrder: unknown, msgRecord: unknown) { - - } - - onGroupFileInfoAdd(groupItem: unknown) { - - } - - onGroupFileInfoUpdate(groupFileListResult: onGroupFileInfoUpdateParamType) { - - } - - onGroupGuildUpdate(groupGuildNotifyInfo: unknown) { - - } - - - onGroupTransferInfoAdd(groupItem: unknown) { - - } - - onGroupTransferInfoUpdate(groupFileListResult: unknown) { - - } - - onGuildInteractiveUpdate(guildInteractiveNotificationItem: unknown) { - - } - - onGuildMsgAbFlagChanged(guildMsgAbFlag: unknown) { - - } - - onGuildNotificationAbstractUpdate(guildNotificationAbstractInfo: unknown) { - - } - - onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: unknown) { - - } - - onHitEmojiKeywordResult(hitRelatedEmojiWordsResult: unknown) { - - } - - onHitRelatedEmojiResult(relatedWordEmojiInfo: unknown) { - - } - - onImportOldDbProgressUpdate(importOldDbMsgNotifyInfo: unknown) { - - } - - onInputStatusPush(inputStatusInfo: unknown) { - - } - - onKickedOffLine(kickedInfo: unknown) { - - } - - onLineDev(arrayList: unknown) { - - } - - onLogLevelChanged(j2: unknown) { - - } - - onMsgAbstractUpdate(arrayList: unknown) { - - } - - onMsgBoxChanged(arrayList: unknown) { - - } - - onMsgDelete(contact: unknown, arrayList: unknown) { - - } - - onMsgEventListUpdate(hashMap: unknown) { - - } - - onMsgInfoListAdd(arrayList: unknown) { - - } - - onMsgInfoListUpdate(msgList: RawMessage[]) { - - } - - onMsgQRCodeStatusChanged(i2: unknown) { - - } - - onMsgRecall(i2: unknown, str: unknown, j2: unknown) { - - } - - onMsgSecurityNotify(msgRecord: unknown) { - - } - - onMsgSettingUpdate(msgSetting: unknown) { - - } - - onNtFirstViewMsgSyncEnd() { - - } - - onNtMsgSyncEnd() { - - } - - onNtMsgSyncStart() { - - } - - onReadFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown) { - - } - - onRecvGroupGuildFlag(i2: unknown) { - - } - - onRecvMsg(arrayList: RawMessage[]) { - - } - - onRecvMsgSvrRspTransInfo(j2: unknown, contact: unknown, i2: unknown, i3: unknown, str: unknown, bArr: unknown) { - - } - - onRecvOnlineFileMsg(arrayList: unknown) { - - } - - onRecvS2CMsg(arrayList: unknown) { - - } - - onRecvSysMsg(arrayList: unknown) { - - } - - onRecvUDCFlag(i2: unknown) { - - } - - onRichMediaDownloadComplete(fileTransNotifyInfo: OnRichMediaDownloadCompleteParams) { - } - - onRichMediaProgerssUpdate(fileTransNotifyInfo: unknown) { - - } - - onRichMediaUploadComplete(fileTransNotifyInfo: unknown) { - - } - - onSearchGroupFileInfoUpdate(searchGroupFileResult: unknown) { - - } - - onSendMsgError(j2: unknown, contact: unknown, i2: unknown, str: unknown) { - - } - - onSysMsgNotification(i2: unknown, j2: unknown, j3: unknown, arrayList: unknown) { - - } - - onTempChatInfoUpdate(tempChatInfo: TempOnRecvParams) { - - } - - onUnreadCntAfterFirstView(hashMap: unknown) { - - } - - onUnreadCntUpdate(hashMap: unknown) { - - } - - onUserChannelTabStatusChanged(z: unknown) { - - } - - onUserOnlineStatusChanged(z: unknown) { - - } - - onUserTabStatusChanged(arrayList: unknown) { - - } - - onlineStatusBigIconDownloadPush(i2: unknown, j2: unknown, str: unknown) { - - } - - onlineStatusSmallIconDownloadPush(i2: unknown, j2: unknown, str: unknown) { - - } - - // 第一次发现于Linux - onUserSecQualityChanged(...args: unknown[]) { - - } - - onMsgWithRichLinkInfoUpdate(...args: unknown[]) { - - } - - onRedTouchChanged(...args: unknown[]) { - - } - // 第一次发现于Win 9.9.9-23159 - onBroadcastHelperProgerssUpdate(...args: unknown[]) { - - } -} diff --git a/src/core/src/listeners/NodeIKernelProfileListener.ts b/src/core/src/listeners/NodeIKernelProfileListener.ts deleted file mode 100644 index 10212d07..00000000 --- a/src/core/src/listeners/NodeIKernelProfileListener.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { User, UserDetailInfoListenerArg } from '@/core/entities'; - -interface IProfileListener { - onProfileSimpleChanged(...args: unknown[]): void; - onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void; - onProfileDetailInfoChanged(profile: User): void; - - onStatusUpdate(...args: unknown[]): void; - - onSelfStatusChanged(...args: unknown[]): void; - - onStrangerRemarkChanged(...args: unknown[]): void; -} - -export interface NodeIKernelProfileListener extends IProfileListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(listener: IProfileListener): NodeIKernelProfileListener; -} - -export class ProfileListener implements IProfileListener { - onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void { - - } - onProfileSimpleChanged(...args: unknown[]) { - - } - - onProfileDetailInfoChanged(profile: User) { - - } - - onStatusUpdate(...args: unknown[]) { - - } - - onSelfStatusChanged(...args: unknown[]) { - - } - - onStrangerRemarkChanged(...args: unknown[]) { - - } -} diff --git a/src/core/src/listeners/NodeIKernelRecentContactListener.ts b/src/core/src/listeners/NodeIKernelRecentContactListener.ts deleted file mode 100644 index 0c03904b..00000000 --- a/src/core/src/listeners/NodeIKernelRecentContactListener.ts +++ /dev/null @@ -1,44 +0,0 @@ -interface IKernelRecentContactListener { - onDeletedContactsNotify(...args: unknown[]): unknown; - - onRecentContactNotification(...args: unknown[]): unknown; - - onMsgUnreadCountUpdate(...args: unknown[]): unknown; - - onGuildDisplayRecentContactListChanged(...args: unknown[]): unknown; - - onRecentContactListChanged(...args: unknown[]): unknown; - - onRecentContactListChangedVer2(...args: unknown[]): unknown; -} - -export interface NodeIKernelRecentContactListener extends IKernelRecentContactListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(listener: IKernelRecentContactListener): NodeIKernelRecentContactListener; -} - -export class KernelRecentContactListener implements IKernelRecentContactListener { - onDeletedContactsNotify(...args: unknown[]) { - - } - - onRecentContactNotification(...args: unknown[]) { - - } - - onMsgUnreadCountUpdate(...args: unknown[]) { - - } - - onGuildDisplayRecentContactListChanged(...args: unknown[]) { - - } - - onRecentContactListChanged(...args: unknown[]) { - - } - - onRecentContactListChangedVer2(...args: unknown[]) { - - } -} diff --git a/src/core/src/listeners/NodeIKernelRobotListener.ts b/src/core/src/listeners/NodeIKernelRobotListener.ts deleted file mode 100644 index 9c319fee..00000000 --- a/src/core/src/listeners/NodeIKernelRobotListener.ts +++ /dev/null @@ -1,28 +0,0 @@ - - -export interface IKernelRobotListener { - onRobotFriendListChanged(...args: unknown[]): void; - - onRobotListChanged(...args: unknown[]): void; - - onRobotProfileChanged(...args: unknown[]): void; -} - -export interface NodeIKernelRobotListener extends IKernelRobotListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(adapter: IKernelRobotListener): NodeIKernelRobotListener; -} - -export class KernelRobotListener implements IKernelRobotListener { - onRobotFriendListChanged(...args: unknown[]){ - - } - - onRobotListChanged(...args: unknown[]){ - - } - - onRobotProfileChanged(...args: unknown[]){ - - } -} diff --git a/src/core/src/listeners/NodeIKernelSessionListener.ts b/src/core/src/listeners/NodeIKernelSessionListener.ts deleted file mode 100644 index 4653a484..00000000 --- a/src/core/src/listeners/NodeIKernelSessionListener.ts +++ /dev/null @@ -1,44 +0,0 @@ -export interface ISessionListener { - onNTSessionCreate(args: unknown): void; - - onGProSessionCreate(args: unknown): void; - - onSessionInitComplete(args: unknown): void; - - onOpentelemetryInit(args: unknown): void; - - onUserOnlineResult(args: unknown): void; - - onGetSelfTinyId(args: unknown): void; -} - -export interface NodeIKernelSessionListener extends ISessionListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(adapter: ISessionListener): NodeIKernelSessionListener; -} - -export class SessionListener implements ISessionListener { - onNTSessionCreate(args: unknown) { - - } - - onGProSessionCreate(args: unknown) { - - } - - onSessionInitComplete(args: unknown) { - - } - - onOpentelemetryInit(args: unknown) { - - } - - onUserOnlineResult(args: unknown) { - - } - - onGetSelfTinyId(args: unknown) { - - } -} diff --git a/src/core/src/listeners/NodeIKernelStorageCleanListener.ts b/src/core/src/listeners/NodeIKernelStorageCleanListener.ts deleted file mode 100644 index ed872d88..00000000 --- a/src/core/src/listeners/NodeIKernelStorageCleanListener.ts +++ /dev/null @@ -1,37 +0,0 @@ -export interface IStorageCleanListener { - onCleanCacheProgressChanged(args: unknown): void; - - onScanCacheProgressChanged(args: unknown): void; - - onCleanCacheStorageChanged(args: unknown): void; - - onFinishScan(args: unknown): void; - - onChatCleanDone(args: unknown): void; - -} -export interface NodeIKernelStorageCleanListener extends IStorageCleanListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(adapter: IStorageCleanListener): NodeIKernelStorageCleanListener; -} - -export class StorageCleanListener implements IStorageCleanListener { - onCleanCacheProgressChanged(args: unknown) { - - } - - onScanCacheProgressChanged(args: unknown) { - - } - - onCleanCacheStorageChanged(args: unknown) { - - } - onFinishScan(args: unknown) { - - } - - onChatCleanDone(args: unknown) { - - } -} \ No newline at end of file diff --git a/src/core/src/listeners/NodeIKernelTicketListener.ts b/src/core/src/listeners/NodeIKernelTicketListener.ts deleted file mode 100644 index 1fe32a15..00000000 --- a/src/core/src/listeners/NodeIKernelTicketListener.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface IKernelTicketListener { -} -export interface NodeIKernelTicketListener extends IKernelTicketListener { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(adapter: IKernelTicketListener): NodeIKernelTicketListener; -} - -export class KernelTicketListener implements IKernelTicketListener { -} \ No newline at end of file diff --git a/src/core/src/listeners/index.ts b/src/core/src/listeners/index.ts deleted file mode 100644 index cc8ad4a2..00000000 --- a/src/core/src/listeners/index.ts +++ /dev/null @@ -1,12 +0,0 @@ - -export * from './NodeIKernelSessionListener'; -export * from './NodeIKernelLoginListener'; -export * from './NodeIKernelMsgListener'; -export * from './NodeIKernelGroupListener'; -export * from './NodeIKernelBuddyListener'; -export * from './NodeIKernelProfileListener'; -export * from './NodeIKernelRobotListener'; -export * from './NodeIKernelTicketListener'; -export * from './NodeIKernelStorageCleanListener'; -export * from './NodeIKernelFileAssistantListener'; - diff --git a/src/core/src/services/NodeIKernelAlbumService.ts b/src/core/src/services/NodeIKernelAlbumService.ts deleted file mode 100644 index 651f764b..00000000 --- a/src/core/src/services/NodeIKernelAlbumService.ts +++ /dev/null @@ -1,46 +0,0 @@ -export interface NodeIKernelAlbumService { - setAlbumServiceInfo(...args: any[]): unknown;// needs 3 arguments - - getMainPage(...args: any[]): unknown;// needs 2 arguments - - getAlbumList(...args: any[]): unknown;// needs 1 arguments - - getAlbumInfo(...args: any[]): unknown;// needs 1 arguments - - deleteAlbum(...args: any[]): unknown;// needs 3 arguments - - addAlbum(...args: any[]): unknown;// needs 2 arguments - - deleteMedias(...args: any[]): unknown;// needs 4 arguments - - modifyAlbum(...args: any[]): unknown;// needs 3 arguments - - getMediaList(...args: any[]): unknown;// needs 1 arguments - - quoteToQzone(...args: any[]): unknown;// needs 1 arguments - - quoteToQunAlbum(...args: any[]): unknown;// needs 1 arguments - - queryQuoteToQunAlbumStatus(...args: any[]): unknown;// needs 1 arguments - - getQunFeeds(...args: any[]): unknown;//needs 1 arguments - - getQunFeedDetail(...args: any[]): unknown;// needs 1 arguments - - getQunNoticeList(...args: any[]): unknown;// needs 4 arguments - - getQunComment(...args: any[]): unknown;// needs 1 arguments - - getQunLikes(...args: any[]): unknown;// needs 4 arguments - - deleteQunFeed(...args: any[]): unknown;// needs 1 arguments - - doQunComment(...args: any[]): unknown;// needs 6 arguments - - doQunReply(...args: any[]): unknown;// needs 7 arguments - - doQunLike(...args: any[]): unknown;// needs 5 arguments - - getRedPoints(...args: any[]): unknown;// needs 3 arguments - -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelAvatarService.ts b/src/core/src/services/NodeIKernelAvatarService.ts deleted file mode 100644 index e8541846..00000000 --- a/src/core/src/services/NodeIKernelAvatarService.ts +++ /dev/null @@ -1,31 +0,0 @@ -export interface NodeIKernelAvatarService { - addAvatarListener(arg: unknown): unknown; - - removeAvatarListener(arg: unknown): unknown; - - getAvatarPath(arg1: unknown, arg2: unknown): unknown; - - forceDownloadAvatar(uid: string, useCache: number): Promise; - - getGroupAvatarPath(arg1: unknown, arg2: unknown): unknown; - - getConfGroupAvatarPath(arg: unknown): unknown; - - forceDownloadGroupAvatar(arg1: unknown, arg2: unknown): unknown; - - getGroupPortraitPath(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - forceDownloadGroupPortrait(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - getAvatarPaths(arg1: unknown, arg2: unknown): unknown; - - getGroupAvatarPaths(arg1: unknown, arg2: unknown): unknown; - - getConfGroupAvatarPaths(arg: unknown): unknown; - - getAvatarPathByUin(arg1: unknown, arg2: unknown): unknown; - - forceDownloadAvatarByUin(arg1: unknown, arg2: unknown): unknown; - - isNull(): boolean; -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelBuddyService.ts b/src/core/src/services/NodeIKernelBuddyService.ts deleted file mode 100644 index 1d28a300..00000000 --- a/src/core/src/services/NodeIKernelBuddyService.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { Friend } from '@/core/entities'; -import { GeneralCallResult } from '@/core/services/common'; -import { NodeIKernelBuddyListener } from '@/core/listeners'; -export enum BuddyListReqType { - KNOMAL, - KLETTER -} -export interface NodeIKernelBuddyService { - // 26702 以上 - getBuddyListV2(callFrom: string, reqType: BuddyListReqType): Promise - }> - }>; - //26702 以上 - getBuddyListFromCache(callFrom: string): Promise//Uids - }>>; - // 以下为原生方法 - addKernelBuddyListener(listener: NodeIKernelBuddyListener): number; - - getAllBuddyCount(): number; - - removeKernelBuddyListener(listener: unknown): void; - - /** - * @deprecated - * @param nocache 使用缓存 - */ - getBuddyList(nocache: boolean): Promise; - - getBuddyNick(uid: number): string; - - getBuddyRemark(uid: number): string; - - setBuddyRemark(uid: number, remark: string): void; - - getAvatarUrl(uid: number): string; - - isBuddy(uid: string): boolean; - - getCategoryNameWithUid(uid: number): string; - - getTargetBuddySetting(uid: number): unknown; - - getTargetBuddySettingByType(uid: number, type: number): unknown; - - getBuddyReqUnreadCnt(): number; - - getBuddyReq(): unknown; - - delBuddyReq(uid: number): void; - - clearBuddyReqUnreadCnt(): void; - - reqToAddFriends(uid: number, msg: string): void; - - setSpacePermission(uid: number, permission: number): void; - - approvalFriendRequest(arg: { - friendUid: string; - reqTime: string; - accept: boolean; - }): Promise; - - delBuddy(uid: number): void; - - delBatchBuddy(uids: number[]): void; - - getSmartInfos(uid: number): unknown; - - setBuddyCategory(uid: number, category: number): void; - - setBatchBuddyCategory(uids: number[], category: number): void; - - addCategory(category: string): void; - - delCategory(category: string): void; - - renameCategory(oldCategory: string, newCategory: string): void; - - resortCategory(categorys: string[]): void; - - pullCategory(uid: number, category: string): void; - - setTop(uid: number, isTop: boolean): void; - - SetSpecialCare(uid: number, isSpecialCare: boolean): void; - - setMsgNotify(uid: number, isNotify: boolean): void; - - hasBuddyList(): boolean; - - setBlock(uid: number, isBlock: boolean): void; - - isBlocked(uid: number): boolean; - - modifyAddMeSetting(setting: unknown): void; - - getAddMeSetting(): unknown; - - getDoubtBuddyReq(): unknown; - - getDoubtBuddyUnreadNum(): number; - - approvalDoubtBuddyReq(uid: number, isAgree: boolean): void; - - delDoubtBuddyReq(uid: number): void; - - delAllDoubtBuddyReq(): void; - - reportDoubtBuddyReqUnread(): void; - - getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise; - - isNull(): boolean; -} diff --git a/src/core/src/services/NodeIKernelCollectionService.ts b/src/core/src/services/NodeIKernelCollectionService.ts deleted file mode 100644 index 74ed399f..00000000 --- a/src/core/src/services/NodeIKernelCollectionService.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { GeneralCallResult } from "./common"; - -export interface NodeIKernelCollectionService { - addKernelCollectionListener(...args: any[]): unknown;//needs 1 arguments - - removeKernelCollectionListener(...args: any[]): unknown;//needs 1 arguments - - getCollectionItemList(param: { - category: number, - groupId: number, - forceSync: boolean, - forceFromDb: boolean, - timeStamp: string, - count: number, - searchDown: boolean - }): Promise, - hasMore: boolean, - bottomTimeStamp: string - } - } - >;//needs 1 arguments - - getCollectionContent(...args: any[]): unknown;//needs 5 arguments - - getCollectionCustomGroupList(...args: any[]): unknown;//needs 0 arguments - - getCollectionUserInfo(...args: any[]): unknown;//needs 0 arguments - - searchCollectionItemList(...args: any[]): unknown;//needs 2 arguments - - addMsgToCollection(...args: any[]): unknown;//needs 2 arguments - - collectionArkShare(...args: any[]): unknown;//needs 1 arguments - - collectionFileForward(...args: any[]): unknown;//needs 3 arguments - - downloadCollectionFile(...args: any[]): unknown;//needs 4 arguments - - downloadCollectionFileThumbPic(...args: any[]): unknown;//needs 4 arguments - - downloadCollectionPic(...args: any[]): unknown;//needs 3 arguments - - cancelDownloadCollectionFile(...args: any[]): unknown;//needs 1 arguments - - deleteCollectionItemList(...args: any[]): unknown;//needs 1 arguments - - editCollectionItem(...args: any[]): unknown;//needs 2 arguments - - getEditPicInfoByPath(...args: any[]): unknown;//needs 1 arguments - - collectionFastUpload(...args: any[]): unknown;//needs 1 arguments - - editCollectionItemAfterFastUpload(...args: any[]): unknown;//needs 2 arguments - - createNewCollectionItem(...args: any[]): unknown;//needs 1 arguments -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelDbToolsService.ts b/src/core/src/services/NodeIKernelDbToolsService.ts deleted file mode 100644 index 7c2b3ceb..00000000 --- a/src/core/src/services/NodeIKernelDbToolsService.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface NodeIKernelDbToolsService { - depositDatabase(...args: unknown[]): unknown; - backupDatabase(...args: unknown[]): unknown; - retrieveDatabase(...args: unknown[]): unknown; -} diff --git a/src/core/src/services/NodeIKernelECDHService.ts b/src/core/src/services/NodeIKernelECDHService.ts deleted file mode 100644 index 8196b269..00000000 --- a/src/core/src/services/NodeIKernelECDHService.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface NodeIKernelECDHService{ - -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelFileAssistantService.ts b/src/core/src/services/NodeIKernelFileAssistantService.ts deleted file mode 100644 index 66037223..00000000 --- a/src/core/src/services/NodeIKernelFileAssistantService.ts +++ /dev/null @@ -1,35 +0,0 @@ -export interface NodeIKernelFileAssistantService { - addKernelFileAssistantListener(arg1: unknown[]): unknown; - - removeKernelFileAssistantListener(arg1: unknown[]): unknown; - - getFileAssistantList(arg1: unknown[]): unknown; - - getMoreFileAssistantList(arg1: unknown[]): unknown; - - getFileSessionList(): unknown; - - searchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - resetSearchFileSortType(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - searchMoreFile(arg1: unknown[]): unknown; - - cancelSearchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - downloadFile(arg1: unknown[]): unknown; - - forwardFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - cancelFileAction(arg1: unknown[]): unknown; - - retryFileAction(arg1: unknown[]): unknown; - - deleteFile(arg1: unknown[]): unknown; - - saveAs(arg1: unknown, arg2: unknown): unknown; - - saveAsWithRename(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - isNull(): boolean; -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelGroupService.ts b/src/core/src/services/NodeIKernelGroupService.ts deleted file mode 100644 index a8c23a2f..00000000 --- a/src/core/src/services/NodeIKernelGroupService.ts +++ /dev/null @@ -1,249 +0,0 @@ -import { NodeIKernelGroupListener } from '@/core/listeners/NodeIKernelGroupListener'; -import { - GroupExtParam, - GroupMember, - GroupMemberRole, - GroupNotifyTypes, - GroupRequestOperateTypes, -} from '@/core/entities'; -import { GeneralCallResult } from '@/core/services/common'; - -//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底 - -export interface NodeIKernelGroupService { - getMemberCommonInfo(Req: { - groupCode: string, - startUin: string, - identifyFlag: string, - uinList: string[], - memberCommonFilter: { - memberUin: number, - uinFlag: number, - uinFlagExt: number, - uinMobileFlag: number, - shutUpTime: number, - privilege: number, - }, - memberNum: number, - filterMethod: string, - onlineFlag: string, - realSpecialTitleFlag: number - }): Promise; - //26702 - getGroupMemberLevelInfo(groupCode: string): Promise; - //26702 - getGroupHonorList(groupCodes: Array): unknown; - - getUinByUids(uins: string[]): Promise<{ - errCode: number, - errMsg: string, - uins: Map - }>; - - getUidByUins(uins: string[]): Promise<{ - errCode: number, - errMsg: string, - uids: Map - }>; - //26702(其实更早 但是我不知道) - checkGroupMemberCache(arrayList: Array): Promise; - - //26702(其实更早 但是我不知道) - getGroupLatestEssenceList(groupCode: string): Promise; - - //26702(其实更早 但是我不知道) - shareDigest(Req: { - appId: string, - appType: number, - msgStyle: number, - recvUin: string, - sendType: number, - clientInfo: { - platform: number - }, - richMsg: { - usingArk: boolean, - title: string, - summary: string, - url: string, - pictureUrl: string, - brief: string - } - }): Promise; - //26702(其实更早 但是我不知道) - isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise; - //26702(其实更早 但是我不知道) - queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise; - //26702(其实更早 但是我不知道) - fetchGroupEssenceList(Req: { groupCode: string, pageStart: number, pageLimit: number }, Arg: unknown): Promise; - //26702 - getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{ - errCode: number, - errMsg: string, - result: { - ids: Array<{ - uid: string, - index: number//0 - }>, - infos: {}, - finish: true, - hasRobot: false - } - }>; - - setHeader(uid: string, path: string): unknown; - - addKernelGroupListener(listener: NodeIKernelGroupListener): number; - - removeKernelGroupListener(listenerId: unknown): void; - - createMemberListScene(groupCode: string, scene: string): string; - - destroyMemberListScene(SceneId:string): void; - //About Arg (a) name: lastId 根据手Q来看为object {index:?(number),uid:string} - getNextMemberList(sceneId: string, a: undefined, num: number): Promise<{ - errCode: number, errMsg: string, - result: { ids: string[], infos: Map, finish: boolean, hasRobot: boolean } - }>; - - getPrevMemberList(): unknown; - - monitorMemberList(): unknown; - - searchMember(sceneId: string, keywords: string[]): unknown; - - getMemberInfo(group_id: string, uids: string[], forceFetch: boolean): Promise; - //getMemberInfo [ '56729xxxx', [ 'u_4Nj08cwW5Hxxxxx' ], true ] - - kickMember(groupCode: string, memberUids: string[], refuseForever: boolean, kickReason: string): Promise; - - modifyMemberRole(groupCode: string, uid: string, role: GroupMemberRole): void; - - modifyMemberCardName(groupCode: string, uid: string, cardName: string): void; - - getTransferableMemberInfo(groupCode: string): unknown;//获取整个群的 - - transferGroup(uid: string): void; - - getGroupList(force: boolean): Promise; - - getGroupExtList(force: boolean): Promise; - - getGroupDetailInfo(groupCode: string): unknown; - - getMemberExtInfo(param: GroupExtParam): Promise;//req - - getGroupAllInfo(): unknown; - - getDiscussExistInfo(): unknown; - - getGroupConfMember(): unknown; - - getGroupMsgMask(): unknown; - - getGroupPortrait(): void; - - modifyGroupName(groupCode: string, groupName: string, arg: false): void; - - modifyGroupRemark(groupCode: string, remark: string): void; - - modifyGroupDetailInfo(groupCode: string, arg: unknown): void; - - setGroupMsgMask(groupCode: string, arg: unknown): void; - - changeGroupShieldSettingTemp(groupCode: string, arg: unknown): void; - - inviteToGroup(arg: unknown): void; - - inviteMembersToGroup(args: unknown[]): void; - - inviteMembersToGroupWithMsg(args: unknown): void; - - createGroup(arg: unknown): void; - - createGroupWithMembers(arg: unknown): void; - - quitGroup(groupCode: string): void; - - destroyGroup(groupCode: string): void; - //获取单屏群通知列表 - getSingleScreenNotifies(force: boolean, start_seq: string, num: number): Promise; - - clearGroupNotifies(groupCode: string): void; - - getGroupNotifiesUnreadCount(unknown: Boolean): Promise; - - clearGroupNotifiesUnreadCount(groupCode: string): void; - - operateSysNotify( - doubt: boolean, - operateMsg: { - operateType: GroupRequestOperateTypes, // 2 拒绝 - targetMsg: { - seq: string, // 通知序列号 - type: GroupNotifyTypes, - groupCode: string, - postscript: string - } - }): Promise; - - setTop(groupCode: string, isTop: boolean): void; - - getGroupBulletin(groupCode: string): unknown; - - deleteGroupBulletin(groupCode: string, seq: string): void; - - publishGroupBulletin(groupCode: string, pskey: string, data: any): Promise; - - publishInstructionForNewcomers(groupCode: string, arg: unknown): void; - - uploadGroupBulletinPic(groupCode: string, pskey: string, imagePath: string): Promise; - - downloadGroupBulletinRichMedia(groupCode: string): unknown; - - getGroupBulletinList(groupCode: string): unknown; - - getGroupStatisticInfo(groupCode: string): unknown; - - getGroupRemainAtTimes(groupCode: string): number; - - getJoinGroupNoVerifyFlag(groupCode: string): unknown; - - getGroupArkInviteState(groupCode: string): unknown; - - reqToJoinGroup(groupCode: string, arg: unknown): void; - - setGroupShutUp(groupCode: string, shutUp: boolean): void; - - getGroupShutUpMemberList(groupCode: string): unknown[]; - - setMemberShutUp(groupCode: string, memberTimes: { uid: string, timeStamp: number }[]): Promise; - - getGroupRecommendContactArkJson(groupCode: string): unknown; - - getJoinGroupLink(groupCode: string): unknown; - - modifyGroupExtInfo(groupCode: string, arg: unknown): void; - - //需要提前判断是否存在 高版本新增 - addGroupEssence(param: { - groupCode: string - msgRandom: number, - msgSeq: number - }): Promise; - //需要提前判断是否存在 高版本新增 - removeGroupEssence(param: { - groupCode: string - msgRandom: number, - msgSeq: number - }): Promise; - - isNull(): boolean; -} diff --git a/src/core/src/services/NodeIKernelLoginService.ts b/src/core/src/services/NodeIKernelLoginService.ts deleted file mode 100644 index d3941f6b..00000000 --- a/src/core/src/services/NodeIKernelLoginService.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { NodeIKernelLoginListener } from '@/core/listeners/NodeIKernelLoginListener'; - -export interface LoginInitConfig { - machineId: ''; - appid: string; - platVer: string; - commonPath: string; - clientVer: string; - hostName: string; -} - -export interface passwordLoginRetType { - result: string, - loginErrorInfo: { - step: number; - errMsg: string; - proofWaterUrl: string; - newDevicePullQrCodeSig: string; - jumpUrl: string, - jumpWord: string; - tipsTitle: string; - tipsContent: string; - } -} - -export interface passwordLoginArgType { - uin: string; - passwordMd5: string;//passwMD5 - step: number;//猜测是需要二次认证 参数 一次为0 - newDeviceLoginSig: string; - proofWaterSig: string; - proofWaterRand: string; - proofWaterSid: string; -} - -export interface LoginListItem { - uin: string; - uid: string; - nickName: string; - faceUrl: string; - facePath: string; - loginType: 1; // 1是二维码登录? - isQuickLogin: boolean; // 是否可以快速登录 - isAutoLogin: boolean; // 是否可以自动登录 -} - -export interface QuickLoginResult{ - result: string - loginErrorInfo: { - step: number, - errMsg: string, - proofWaterUrl: string, - newDevicePullQrCodeSig: string, - jumpUrl: string, - jumpWord: string, - tipsTitle: string, - tipsContent: string - } -} - -export interface NodeIKernelLoginService { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(): NodeIKernelLoginService; - - addKernelLoginListener(listener: NodeIKernelLoginListener): number; - removeKernelLoginListener(listener: number): void; - - initConfig(config: LoginInitConfig): void; - - getLoginMiscData(cb: (r: unknown) => void): void; - - getLoginList(): Promise<{ - result: number, // 0是ok - LocalLoginInfoList: LoginListItem[] - }>; - - quickLoginWithUin(uin: string): Promise; - - passwordLogin(param: passwordLoginArgType): Promise; - - getQRCodePicture(): boolean; -} diff --git a/src/core/src/services/NodeIKernelMSFService.ts b/src/core/src/services/NodeIKernelMSFService.ts deleted file mode 100644 index fe63ed60..00000000 --- a/src/core/src/services/NodeIKernelMSFService.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface NodeIKernelMSFService { - getServerTime(): string; -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelMsgBackupService.ts b/src/core/src/services/NodeIKernelMsgBackupService.ts deleted file mode 100644 index aef276fc..00000000 --- a/src/core/src/services/NodeIKernelMsgBackupService.ts +++ /dev/null @@ -1,27 +0,0 @@ -export interface NodeIKernelMsgBackupService { - addKernelMsgBackupListener(...args: any[]): unknown;// needs 1 arguments - - removeKernelMsgBackupListener(...args: any[]): unknown;// needs 1 arguments - - getMsgBackupLocation(...args: any[]): unknown;// needs 0 arguments - - setMsgBackupLocation(...args: any[]): unknown;// needs 1 arguments - - requestMsgBackup(...args: any[]): unknown;// needs 0 arguments - - requestMsgRestore(...args: any[]): unknown;// needs 1 arguments - - requestMsgMigrate(...args: any[]): unknown;// needs 1 arguments - - getLocalStorageBackup(...args: any[]): unknown;// needs 0 arguments - - deleteLocalBackup(...args: any[]): unknown;// needs 1 arguments - - clearCache(...args: any[]): unknown;// needs 0 arguments - - start(...args: any[]): unknown;// needs 1 arguments - - stop(...args: any[]): unknown;// needs 1 arguments - - pause(...args: any[]): unknown;// needs 2 arguments -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelMsgService.ts b/src/core/src/services/NodeIKernelMsgService.ts deleted file mode 100644 index 61c01d7c..00000000 --- a/src/core/src/services/NodeIKernelMsgService.ts +++ /dev/null @@ -1,727 +0,0 @@ -import { ElementType, MessageElement, Peer, RawMessage, SendMessageElement } from '@/core/entities'; -import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener'; -import { GeneralCallResult } from '@/core/services/common'; - -export interface QueryMsgsParams { - chatInfo: Peer, - filterMsgType: [], - filterSendersUid: string[], - filterMsgFromTime: string, - filterMsgToTime: string, - pageLimit: number, - isReverseOrder: boolean, - isIncludeCurrent: boolean -} -export interface NodeIKernelMsgService { - - generateMsgUniqueId(chatType: number, time: string): string; - - addKernelMsgListener(nodeIKernelMsgListener: NodeIKernelMsgListener): number; - - sendMsg(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map): Promise; - - recallMsg(peer: Peer, msgIds: string[]): Promise; - - addKernelMsgImportToolListener(arg: Object): unknown; - - removeKernelMsgListener(args: unknown): unknown; - - addKernelTempChatSigListener(...args: unknown[]): unknown; - - removeKernelTempChatSigListener(...args: unknown[]): unknown; - - setAutoReplyTextList(AutoReplyText: Array, i2: number): unknown; - - getAutoReplyTextList(...args: unknown[]): unknown; - - getOnLineDev(): void; - - kickOffLine(DevInfo: Object): unknown; - - setStatus(args: { status: number, extStatus: number, batteryStatus: number }): Promise; - - fetchStatusMgrInfo(): unknown; - - fetchStatusUnitedConfigInfo(): unknown; - - getOnlineStatusSmallIconBasePath(): unknown; - - getOnlineStatusSmallIconFileNameByUrl(Url: string): unknown; - - downloadOnlineStatusSmallIconByUrl(arg0: number, arg1: string): unknown; - - getOnlineStatusBigIconBasePath(): unknown; - - downloadOnlineStatusBigIconByUrl(arg0: number, arg1: string): unknown; - - getOnlineStatusCommonPath(arg: string): unknown; - - getOnlineStatusCommonFileNameByUrl(Url: string): unknown; - - downloadOnlineStatusCommonByUrl(arg0: string, arg1: string): unknown; - - // this.tokenType = i2; - // this.apnsToken = bArr; - // this.voipToken = bArr2; - // this.profileId = str; - - setToken(arg: Object): unknown; - - switchForeGround(): unknown; - - switchBackGround(arg: Object): unknown; - - //hex - setTokenForMqq(token: string): unknown; - - switchForeGroundForMqq(...args: unknown[]): unknown; - - switchBackGroundForMqq(...args: unknown[]): unknown; - - getMsgSetting(...args: unknown[]): unknown; - - setMsgSetting(...args: unknown[]): unknown; - - addSendMsg(...args: unknown[]): unknown; - - cancelSendMsg(...args: unknown[]): unknown; - - switchToOfflineSendMsg(peer: Peer, MsgId: string): unknown; - - reqToOfflineSendMsg(...args: unknown[]): unknown; - - refuseReceiveOnlineFileMsg(peer: Peer, MsgId: string): unknown; - - resendMsg(...args: unknown[]): unknown; - - recallMsg(...args: unknown[]): unknown; - - reeditRecallMsg(...args: unknown[]): unknown; - - forwardMsg(...args: unknown[]): Promise; - - forwardMsgWithComment(...args: unknown[]): unknown; - - forwardSubMsgWithComment(...args: unknown[]): unknown; - - forwardRichMsgInVist(...args: unknown[]): unknown; - - forwardFile(...args: unknown[]): unknown; - //Array, Peer from, Peer to - multiForwardMsg(...args: unknown[]): unknown; - - multiForwardMsgWithComment(...args: unknown[]): unknown; - - deleteRecallMsg(...args: unknown[]): unknown; - - deleteRecallMsgForLocal(...args: unknown[]): unknown; - - addLocalGrayTipMsg(...args: unknown[]): unknown; - - addLocalJsonGrayTipMsg(...args: unknown[]): unknown; - - addLocalJsonGrayTipMsgExt(...args: unknown[]): unknown; - - IsLocalJsonTipValid(...args: unknown[]): unknown; - - addLocalAVRecordMsg(...args: unknown[]): unknown; - - addLocalTofuRecordMsg(...args: unknown[]): unknown; - - addLocalRecordMsg(Peer: Peer, msgId: string, ele: MessageElement, attr: Array | number, front: boolean): Promise; - - deleteMsg(Peer: Peer, msgIds: Array): Promise; - - updateElementExtBufForUI(...args: unknown[]): unknown; - - updateMsgRecordExtPbBufForUI(...args: unknown[]): unknown; - - startMsgSync(...args: unknown[]): unknown; - - startGuildMsgSync(...args: unknown[]): unknown; - - isGuildChannelSync(...args: unknown[]): unknown; - - getMsgUniqueId(UniqueId: string): string; - - isMsgMatched(...args: unknown[]): unknown; - - getOnlineFileMsgs(...args: unknown[]): unknown; - - getAllOnlineFileMsgs(...args: unknown[]): unknown; - - getLatestDbMsgs(peer: Peer, cnt: number): Promise; - - getLastMessageList(peer: Peer[]): Promise; - - getAioFirstViewLatestMsgs(peer: Peer, num: number): unknown; - - getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise; - - getMsgsIncludeSelf(peer: Peer, msgId: string, count: number, queryOrder: boolean): Promise; - - // this.$peer = contact; - // this.$msgTime = j2; - // this.$clientSeq = j3; - // this.$cnt = i2; - - getMsgsWithMsgTimeAndClientSeqForC2C(...args: unknown[]): Promise; - - getMsgsWithStatus(params: { - peer: Peer - msgId: string - msgTime: unknown - cnt: unknown - queryOrder: boolean - isIncludeSelf: boolean - appid: unknown - }): Promise; - - getMsgsBySeqRange(peer: Peer, startSeq: string, endSeq: string): Promise; - - getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, unknownArg: boolean): Promise; - - getMsgsByMsgId(peer: Peer, ids: string[]): Promise; - - getRecallMsgsByMsgId(peer: Peer, MsgId: string[]): Promise; - - getMsgsBySeqList(peer: Peer, seqList: string[]): Promise; - - getSingleMsg(Peer: Peer, msgSeq: string): Promise; - - getSourceOfReplyMsg(peer: Peer, MsgId: string, SourceSeq: string): unknown; - - getSourceOfReplyMsgV2(peer: Peer, RootMsgId: string, ReplyMsgId: string): unknown; - - getMsgByClientSeqAndTime(peer: Peer, clientSeq: string, time: string): unknown; - - getSourceOfReplyMsgByClientSeqAndTime(peer: Peer, clientSeq: string, time: string): unknown; - //cnt clientSeq?并不是吧 - getMsgsByTypeFilter(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilter: { type: number, subtype: Array }): unknown; - - getMsgsByTypeFilters(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilters: Array<{ type: number, subtype: Array }>): unknown; - - getMsgWithAbstractByFilterParam(...args: unknown[]): unknown; - - queryMsgsWithFilter(...args: unknown[]): unknown; - - /** - * @deprecated 该函数已被标记为废弃,请使用新的替代方法。 - * 使用过滤条件查询消息列表的版本2接口。 - * - * 该函数通过一系列过滤条件来查询特定聊天中的消息列表。这些条件包括消息类型、发送者、时间范围等。 - * 函数返回一个Promise,解析为查询结果的未知类型对象。 - * - * @param MsgId 消息ID,用于特定消息的查询。 - * @param MsgTime 消息时间,用于指定消息的时间范围。 - * @param param 查询参数对象,包含详细的过滤条件和分页信息。 - * @param param.chatInfo 聊天信息,包括聊天类型和对方用户ID。 - * @param param.filterMsgType 需要过滤的消息类型数组,留空表示不过滤。 - * @param param.filterSendersUid 需要过滤的发送者用户ID数组。 - * @param param.filterMsgFromTime 查询消息的起始时间。 - * @param param.filterMsgToTime 查询消息的结束时间。 - * @param param.pageLimit 每页的消息数量限制。 - * @param param.isReverseOrder 是否按时间顺序倒序返回消息。 - * @param param.isIncludeCurrent 是否包含当前页码。 - * @returns 返回一个Promise,解析为查询结果的未知类型对象。 - */ - queryMsgsWithFilterVer2(MsgId: string, MsgTime: string, param: QueryMsgsParams): Promise; - - // this.chatType = i2; - // this.peerUid = str; - - // this.chatInfo = new ChatInfo(); - // this.filterMsgType = new ArrayList<>(); - // this.filterSendersUid = new ArrayList<>(); - // this.chatInfo = chatInfo; - // this.filterMsgType = arrayList; - // this.filterSendersUid = arrayList2; - // this.filterMsgFromTime = j2; - // this.filterMsgToTime = j3; - // this.pageLimit = i2; - // this.isReverseOrder = z; - // this.isIncludeCurrent = z2; - //queryMsgsWithFilterEx(0L, 0L, 0L, new QueryMsgsParams(new ChatInfo(2, str), new ArrayList(), new ArrayList(), 0L, 0L, 250, false, true)) - queryMsgsWithFilterEx(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): Promise; - //queryMsgsWithFilterEx(this.$msgId, this.$msgTime, this.$msgSeq, this.$param) - queryFileMsgsDesktop(...args: unknown[]): unknown; - - setMsgRichInfoFlag(...args: unknown[]): unknown; - - queryPicOrVideoMsgs(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): Promise; - - queryPicOrVideoMsgsDesktop(...args: unknown[]): unknown; - - queryEmoticonMsgs(msgId: string, msgTime: string, msgSeq: string, Params: QueryMsgsParams): Promise; - - queryTroopEmoticonMsgs(msgId: string, msgTime: string, msgSeq: string, Params: QueryMsgsParams): Promise; - - queryMsgsAndAbstractsWithFilter(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): unknown; - - setFocusOnGuild(...args: unknown[]): unknown; - - setFocusSession(...args: unknown[]): unknown; - - enableFilterUnreadInfoNotify(...args: unknown[]): unknown; - - enableFilterMsgAbstractNotify(...args: unknown[]): unknown; - - onScenesChangeForSilenceMode(...args: unknown[]): unknown; - - getContactUnreadCnt(...args: unknown[]): unknown; - - getUnreadCntInfo(...args: unknown[]): unknown; - - getGuildUnreadCntInfo(...args: unknown[]): unknown; - - getGuildUnreadCntTabInfo(...args: unknown[]): unknown; - - getAllGuildUnreadCntInfo(...args: unknown[]): unknown; - - getAllJoinGuildCnt(...args: unknown[]): unknown; - - getAllDirectSessionUnreadCntInfo(...args: unknown[]): unknown; - - getCategoryUnreadCntInfo(...args: unknown[]): unknown; - - getGuildFeedsUnreadCntInfo(...args: unknown[]): unknown; - - setUnVisibleChannelCntInfo(...args: unknown[]): unknown; - - setUnVisibleChannelTypeCntInfo(...args: unknown[]): unknown; - - setVisibleGuildCntInfo(...args: unknown[]): unknown; - - setMsgRead(peer: Peer): Promise; - - setAllC2CAndGroupMsgRead(): Promise; - - setGuildMsgRead(...args: unknown[]): unknown; - - setAllGuildMsgRead(...args: unknown[]): unknown; - - setMsgReadAndReport(...args: unknown[]): unknown; - - setSpecificMsgReadAndReport(...args: unknown[]): unknown; - - setLocalMsgRead(...args: unknown[]): unknown; - - setGroupGuildMsgRead(...args: unknown[]): unknown; - - getGuildGroupTransData(...args: unknown[]): unknown; - - setGroupGuildBubbleRead(...args: unknown[]): unknown; - - getGuildGroupBubble(...args: unknown[]): unknown; - - fetchGroupGuildUnread(...args: unknown[]): unknown; - - setGroupGuildFlag(...args: unknown[]): unknown; - - setGuildUDCFlag(...args: unknown[]): unknown; - - setGuildTabUserFlag(...args: unknown[]): unknown; - - setBuildMode(flag: number/*0 1 3*/): unknown; - - setConfigurationServiceData(...args: unknown[]): unknown; - - setMarkUnreadFlag(...args: unknown[]): unknown; - - getChannelEventFlow(...args: unknown[]): unknown; - - getMsgEventFlow(...args: unknown[]): unknown; - - getRichMediaFilePathForMobileQQSend(...args: unknown[]): unknown; - - getRichMediaFilePathForGuild(arg: { - md5HexStr: string, - fileName: string, - elementType: ElementType, - elementSubType: number, - thumbSize: 0, - needCreate: true, - downloadType: 1, - file_uuid: '' - }): string; - - assembleMobileQQRichMediaFilePath(...args: unknown[]): unknown; - - getFileThumbSavePathForSend(...args: unknown[]): unknown; - - getFileThumbSavePath(...args: unknown[]): unknown; - //猜测居多 - translatePtt2Text(MsgId: string, Peer: {}, MsgElement: {}): unknown; - - setPttPlayedState(...args: unknown[]): unknown; - // NodeIQQNTWrapperSession fetchFavEmojiList [ - // "", - // 48, - // true, - // true - // ] - fetchFavEmojiList(str: string, num: number, uk1: boolean, uk2: boolean): Promise - }>; - - addFavEmoji(...args: unknown[]): unknown; - - fetchMarketEmoticonList(...args: unknown[]): unknown; - - fetchMarketEmoticonShowImage(...args: unknown[]): unknown; - - fetchMarketEmoticonAioImage(...args: unknown[]): unknown; - - fetchMarketEmotionJsonFile(...args: unknown[]): unknown; - - getMarketEmoticonPath(...args: unknown[]): unknown; - - getMarketEmoticonPathBySync(...args: unknown[]): unknown; - - fetchMarketEmoticonFaceImages(...args: unknown[]): unknown; - - fetchMarketEmoticonAuthDetail(...args: unknown[]): unknown; - - getFavMarketEmoticonInfo(...args: unknown[]): unknown; - - addRecentUsedFace(...args: unknown[]): unknown; - - getRecentUsedFaceList(...args: unknown[]): unknown; - - getMarketEmoticonEncryptKeys(...args: unknown[]): unknown; - - downloadEmojiPic(...args: unknown[]): unknown; - - deleteFavEmoji(...args: unknown[]): unknown; - - modifyFavEmojiDesc(...args: unknown[]): unknown; - - queryFavEmojiByDesc(...args: unknown[]): unknown; - - getHotPicInfoListSearchString(...args: unknown[]): unknown; - - getHotPicSearchResult(...args: unknown[]): unknown; - - getHotPicHotWords(...args: unknown[]): unknown; - - getHotPicJumpInfo(...args: unknown[]): unknown; - - getEmojiResourcePath(...args: unknown[]): unknown; - - JoinDragonGroupEmoji(JoinDragonGroupEmojiReq: any/*joinDragonGroupEmojiReq*/): unknown; - - getMsgAbstracts(...args: unknown[]): unknown; - - getMsgAbstract(...args: unknown[]): unknown; - - getMsgAbstractList(...args: unknown[]): unknown; - - getMsgAbstractListBySeqRange(...args: unknown[]): unknown; - - refreshMsgAbstracts(...args: unknown[]): unknown; - - refreshMsgAbstractsByGuildIds(...args: unknown[]): unknown; - - getRichMediaElement(...args: unknown[]): unknown; - - cancelGetRichMediaElement(...args: unknown[]): unknown; - - refuseGetRichMediaElement(...args: unknown[]): unknown; - - switchToOfflineGetRichMediaElement(...args: unknown[]): unknown; - - downloadRichMedia(...args: unknown[]): unknown; - - getFirstUnreadMsgSeq(args: { - peerUid: string - guildId: string - }): unknown; - - getFirstUnreadCommonMsg(...args: unknown[]): unknown; - - getFirstUnreadAtmeMsg(...args: unknown[]): unknown; - - getFirstUnreadAtallMsg(...args: unknown[]): unknown; - - getNavigateInfo(...args: unknown[]): unknown; - - getChannelFreqLimitInfo(...args: unknown[]): unknown; - - getRecentUseEmojiList(...args: unknown[]): unknown; - - getRecentEmojiList(...args: unknown[]): unknown; - - setMsgEmojiLikes(...args: unknown[]): unknown; - - getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, cookie: string, bForward: boolean, number: number): Promise<{ - result: number, - errMsg: string, - emojiLikesList: - Array<{ - tinyId: string, - nickName: string, - headUrl: string - }>, - cookie: string, - isLastPage: boolean, - isFirstPage: boolean - }>; - - setMsgEmojiLikesForRole(...args: unknown[]): unknown; - - clickInlineKeyboardButton(...args: unknown[]): unknown; - - setCurOnScreenMsg(...args: unknown[]): unknown; - - setCurOnScreenMsgForMsgEvent(...args: unknown[]): unknown; - - getMiscData(key: string): unknown; - - setMiscData(key: string, value: string): unknown; - - getBookmarkData(...args: unknown[]): unknown; - - setBookmarkData(...args: unknown[]): unknown; - - sendShowInputStatusReq(ChatType: number, EventType: number, toUid: string): Promise; - - queryCalendar(...args: unknown[]): unknown; - - queryFirstMsgSeq(peer: Peer, ...args: unknown[]): unknown; - - queryRoamCalendar(...args: unknown[]): unknown; - - queryFirstRoamMsg(...args: unknown[]): unknown; - - fetchLongMsg(peer: Peer, msgId: string): unknown; - - fetchLongMsgWithCb(...args: unknown[]): unknown; - - setIsStopKernelFetchLongMsg(...args: unknown[]): unknown; - - insertGameResultAsMsgToDb(...args: unknown[]): unknown; - - getMultiMsg(...args: unknown[]): Promise; - - setDraft(...args: unknown[]): unknown; - - getDraft(...args: unknown[]): unknown; - - deleteDraft(...args: unknown[]): unknown; - - getRecentHiddenSesionList(...args: unknown[]): unknown; - - setRecentHiddenSession(...args: unknown[]): unknown; - - delRecentHiddenSession(...args: unknown[]): unknown; - - getCurHiddenSession(...args: unknown[]): unknown; - - setCurHiddenSession(...args: unknown[]): unknown; - - setReplyDraft(...args: unknown[]): unknown; - - getReplyDraft(...args: unknown[]): unknown; - - deleteReplyDraft(...args: unknown[]): unknown; - - getFirstUnreadAtMsg(peer: Peer): unknown; - - clearMsgRecords(...args: unknown[]): unknown;//设置已读后调用我觉得比较好 清理记录 现在别了 - - IsExistOldDb(...args: unknown[]): unknown; - - canImportOldDbMsg(...args: unknown[]): unknown; - - setPowerStatus(z: boolean): unknown; - - canProcessDataMigration(...args: unknown[]): unknown; - - importOldDbMsg(...args: unknown[]): unknown; - - stopImportOldDbMsgAndroid(...args: unknown[]): unknown; - - isMqqDataImportFinished(...args: unknown[]): unknown; - - getMqqDataImportTableNames(...args: unknown[]): unknown; - - getCurChatImportStatusByUin(...args: unknown[]): unknown; - - getDataImportUserLevel(): unknown; - - getMsgQRCode(...args: unknown[]): unknown; - - getGuestMsgAbstracts(...args: unknown[]): unknown; - - getGuestMsgByRange(...args: unknown[]): unknown; - - getGuestMsgAbstractByRange(...args: unknown[]): unknown; - - registerSysMsgNotification(...args: unknown[]): unknown; - - unregisterSysMsgNotification(...args: unknown[]): unknown; - - enterOrExitAio(...args: unknown[]): unknown; - - // this.peerUid = ""; - // this.peerNickname = ""; - // this.fromGroupCode = ""; - // this.sig = new byte[0]; - // this.selfUid = ""; - // this.selfPhone = ""; - // this.chatType = i2; - // this.peerUid = str; - // this.peerNickname = str2; - // this.fromGroupCode = str3; - // this.sig = bArr; - // this.selfUid = str4; - // this.selfPhone = str5; - // this.gameSession = tempChatGameSession; - prepareTempChat(args: unknown): unknown;//主动临时消息 不做 - - sendSsoCmdReqByContend(cmd: string, param: string): Promise; - - //chattype,uid->Promise - getTempChatInfo(ChatType: number, Uid: string): unknown; - - setContactLocalTop(...args: unknown[]): unknown; - - switchAnonymousChat(...args: unknown[]): unknown; - - renameAnonyChatNick(...args: unknown[]): unknown; - - getAnonymousInfo(...args: unknown[]): unknown; - - updateAnonymousInfo(...args: unknown[]): unknown; - - sendSummonMsg(peer: Peer, MsgElement: unknown, MsgAttributeInfo: unknown): Promise;//频道的东西 - - outputGuildUnreadInfo(...args: unknown[]): unknown; - - checkMsgWithUrl(...args: unknown[]): unknown; - - checkTabListStatus(...args: unknown[]): unknown; - - getABatchOfContactMsgBoxInfo(...args: unknown[]): unknown; - - insertMsgToMsgBox(peer: Peer, msgId: string, arg: 2006): unknown; - - isHitEmojiKeyword(...args: unknown[]): unknown; - - getKeyWordRelatedEmoji(...args: unknown[]): unknown; - - recordEmoji(...args: unknown[]): unknown; - - fetchGetHitEmotionsByWord(args: Object): Promise;//表情推荐? - - deleteAllRoamMsgs(...args: unknown[]): unknown;//漫游消息? - - packRedBag(...args: unknown[]): unknown; - - grabRedBag(...args: unknown[]): unknown; - - pullDetail(...args: unknown[]): unknown; - - selectPasswordRedBag(...args: unknown[]): unknown; - - pullRedBagPasswordList(...args: unknown[]): unknown; - - requestTianshuAdv(...args: unknown[]): unknown; - - tianshuReport(...args: unknown[]): unknown; - - tianshuMultiReport(...args: unknown[]): unknown; - - GetMsgSubType(a0: number, a1: number): unknown; - - setIKernelPublicAccountAdapter(...args: unknown[]): unknown; - //tempChatGameSession有关 - createUidFromTinyId(fromTinyId: string, toTinyId: string): unknown; - - dataMigrationGetDataAvaiableContactList(...args: unknown[]): unknown; - - dataMigrationGetMsgList(...args: unknown[]): unknown; - - dataMigrationStopOperation(...args: unknown[]): unknown; - - //新的希望 - dataMigrationImportMsgPbRecord(DataMigrationMsgInfo: Array<{ - extensionData: string//"Hex" - extraData: string //"" - chatType: number - chatUin: string - msgType: number - msgTime: string - msgSeq: string - msgRandom: string - }>, DataMigrationResourceInfo: { - extraData: string - filePath: string - fileSize: string - msgRandom: string - msgSeq: string - msgSubType: number - msgType: number - }): unknown; - - dataMigrationGetResourceLocalDestinyPath(...args: unknown[]): unknown; - - dataMigrationSetIOSPathPrefix(...args: unknown[]): unknown; - - getServiceAssistantSwitch(...args: unknown[]): unknown; - - setServiceAssistantSwitch(...args: unknown[]): unknown; - - setSubscribeFolderUsingSmallRedPoint(...args: unknown[]): unknown; - - clearGuildNoticeRedPoint(...args: unknown[]): unknown; - - clearFeedNoticeRedPoint(...args: unknown[]): unknown; - - clearFeedSquareRead(...args: unknown[]): unknown; - - IsC2CStyleChatType(...args: unknown[]): unknown; - - IsTempChatType(uin: number): unknown;//猜的 - - getGuildInteractiveNotification(...args: unknown[]): unknown; - - getGuildNotificationAbstract(...args: unknown[]): unknown; - - setFocusOnBase(...args: unknown[]): unknown; - - queryArkInfo(...args: unknown[]): unknown; - - queryUserSecQuality(...args: unknown[]): unknown; - - getGuildMsgAbFlag(...args: unknown[]): unknown; - - getGroupMsgStorageTime(): unknown;//这是嘛啊 - -} diff --git a/src/core/src/services/NodeIKernelNodeMiscService.ts b/src/core/src/services/NodeIKernelNodeMiscService.ts deleted file mode 100644 index 150c2a69..00000000 --- a/src/core/src/services/NodeIKernelNodeMiscService.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { GeneralCallResult } from "./common"; - -//没扒干净 因为用不着 -export interface NodeIKernelNodeMiscService { - getMiniAppPath(): unknown; - setMiniAppVersion(version:string): unknown; - wantWinScreenOCR(imagepath: string): Promise; - SendMiniAppMsg(arg1: string, arg2: string, arg3: string): unknown; - startNewMiniApp(appfile: string, params: string): unknown; - // 我的计划是转发给一个新程序避免吃掉Electron_AS_Node的环境 然后重写启动MiniApp 挂载相应JS脚本 这样有个问题 - // 需要自己转发ipc参数 然后必须处在gui环境 且完成校验破解 才能实现发包 有点抽象了 -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelOnlineStatusService.ts b/src/core/src/services/NodeIKernelOnlineStatusService.ts deleted file mode 100644 index b89f5e01..00000000 --- a/src/core/src/services/NodeIKernelOnlineStatusService.ts +++ /dev/null @@ -1,36 +0,0 @@ -export interface NodeIKernelOnlineStatusService { - - addKernelOnlineStatusListener(listener: unknown): void; - - removeKernelOnlineStatusListener(listenerId: unknown): void; - - getShouldShowAIOStatusAnimation(arg: unknown): unknown; - - setReadLikeList(arg: unknown): unknown; - - getLikeList(arg: unknown): unknown; - - setLikeStatus(arg: unknown): unknown; - - getAggregationPageEntrance(): unknown; - - didClickAggregationPageEntrance(): unknown; - - getAggregationGroupModels(): unknown; - - // { - // "businessType": 1, - // "uins": [ - // "1627126029", - // "66600000", - // "71702575" - // ] - // } - - checkLikeStatus(param: { - businessType: number, - uins: string[] - }): Promise; - - isNull(): boolean; -} diff --git a/src/core/src/services/NodeIKernelProfileLikeService.ts b/src/core/src/services/NodeIKernelProfileLikeService.ts deleted file mode 100644 index fa765695..00000000 --- a/src/core/src/services/NodeIKernelProfileLikeService.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { BuddyProfileLikeReq } from "../entities/user"; -import { GeneralCallResult } from "./common"; - -export interface NodeIKernelProfileLikeService { - addKernelProfileLikeListener(listener: NodeIKernelProfileLikeService): void; - - removeKernelProfileLikeListener(listener: unknown): void; - - setBuddyProfileLike(...args: unknown[]): { result: number, errMsg: string, succCounts: number }; - - getBuddyProfileLike(req: BuddyProfileLikeReq): Promise, - "friendMaxVotes": number, - "start": number - } - }>; - - getProfileLikeScidResourceInfo(...args: unknown[]): void; - - isNull(): boolean; -} diff --git a/src/core/src/services/NodeIKernelProfileService.ts b/src/core/src/services/NodeIKernelProfileService.ts deleted file mode 100644 index e626a332..00000000 --- a/src/core/src/services/NodeIKernelProfileService.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { AnyCnameRecord } from 'node:dns'; -import { BaseInfo, BizKey, CoreInfo, ModifyProfileParams, SimpleInfo, UserDetailInfoByUin } from '../entities'; -import { NodeIKernelProfileListener } from '../listeners'; -import { GeneralCallResult } from '@/core/services/common'; -export enum UserDetailSource { - KDB, - KSERVER -} -export enum ProfileBizType { - KALL, - KBASEEXTEND, - KVAS, - KQZONE, - KOTHER -} -export interface NodeIKernelProfileService { - - getUidByUin(callfrom: string, uin: Array): Promise>;//uin->uid - - getUinByUid(callfrom: string, uid: Array): Promise>; - // { - // coreInfo: CoreInfo, - // baseInfo: BaseInfo, - // status: null, - // vasInfo: null, - // relationFlags: null, - // otherFlags: null, - // intimate: null - // } - getCoreAndBaseInfo(callfrom: string, uids: string[]): Promise>; - - fetchUserDetailInfo(trace: string, uids: string[], arg2: number, arg3: number[]): Promise; - - addKernelProfileListener(listener: NodeIKernelProfileListener): number; - - removeKernelProfileListener(listenerId: number): void; - - prepareRegionConfig(...args: unknown[]): unknown; - - getLocalStrangerRemark(): Promise; - - enumCountryOptions(): Array; - - enumProvinceOptions(Country: string): Array; - - enumCityOptions(Country: string, Province: string): unknown; - - enumAreaOptions(...args: unknown[]): unknown; - - //SimpleInfo - // this.uid = ""; - // this.uid = str; - // this.uin = j2; - // this.isBuddy = z; - // this.coreInfo = coreInfo; - // this.baseInfo = baseInfo; - // this.status = statusInfo; - // this.vasInfo = vasInfo; - // this.relationFlags = relationFlag; - // this.otherFlags = otherFlag; - // this.intimate = intimate; - - modifySelfProfile(...args: unknown[]): Promise; - - modifyDesktopMiniProfile(param: ModifyProfileParams): Promise; - - setNickName(NickName: string): Promise; - - setLongNick(longNick: string): Promise; - - setBirthday(...args: unknown[]): Promise; - - setGander(...args: unknown[]): Promise; - - setHeader(arg: string): Promise; - - setRecommendImgFlag(...args: unknown[]): Promise; - - getUserSimpleInfo(force: boolean, uids: string[],): Promise; - - getUserDetailInfo(uid: string): Promise; - - getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise; - - getUserDetailInfoByUin(uin: string): Promise; - - getZplanAvatarInfos(args: string[]): Promise; - - getStatus(uid: string): Promise; - - startStatusPolling(isForceReset: boolean): Promise; - - getSelfStatus(): Promise; - // - setdisableEmojiShortCuts(...args: unknown[]): unknown; - - getProfileQzonePicInfo(uid: string, type: number, force: boolean): Promise; - - //profileService.getCoreInfo("UserRemarkServiceImpl::getStrangerRemarkByUid", arrayList); - getCoreInfo(name: string, arg: any[]): unknown; - //m429253e12.getOtherFlag("FriendListInfoCache_getKernelDataAndPutCache", new ArrayList<>()); - isNull(): boolean; -} diff --git a/src/core/src/services/NodeIKernelRecentContactService.ts b/src/core/src/services/NodeIKernelRecentContactService.ts deleted file mode 100644 index ffe8cc96..00000000 --- a/src/core/src/services/NodeIKernelRecentContactService.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { ChatType, Peer } from "../entities"; -import { NodeIKernelRecentContactListener } from "../listeners/NodeIKernelRecentContactListener"; -import { GeneralCallResult } from "./common"; -export interface FSABRecentContactParams { - anchorPointContact: { - contactId: string; - sortField: string; - pos: number; - }, - relativeMoveCount: number; - listType: number; - count: number; - fetchOld: boolean; -} -// { -// "anchorPointContact": { -// "contactId": "", -// "sortField": "", -// "pos": 0 -// }, -// "relativeMoveCount": 0, -// "listType": 1, -// "count": 200, -// "fetchOld": true -// } -export interface NodeIKernelRecentContactService { - setGuildDisplayStatus(...args: unknown[]): unknown; // 2 arguments - - setContactListTop(...args: unknown[]): unknown; // 2 arguments - - updateRecentContactExtBufForUI(...args: unknown[]): unknown; // 2 arguments - - upsertRecentContactManually(...args: unknown[]): unknown; // 1 arguments - - enterOrExitMsgList(...args: unknown[]): unknown; // 1 arguments - - /*!---!*/getRecentContactListSnapShot(count: number): Promise, - changedList: Array<{ - remark: any; - peerName: any; - sendMemberName: any; - sendNickName: any; - peerUid: string; peerUin: string, msgTime: string, chatType: ChatType, msgId: string - }> - } - }>; // 1 arguments - - clearMsgUnreadCount(...args: unknown[]): unknown; // 1 arguments - - getRecentContactListSyncLimit(count: number): unknown; - - jumpToSpecifyRecentContact(...args: unknown[]): unknown; // 1 arguments - - /*!---!*/fetchAndSubscribeABatchOfRecentContact(params: FSABRecentContactParams): unknown; // 1 arguments - - addRecentContact(peer: Peer): unknown; - - deleteRecentContacts(peer: Peer): unknown; // 猜测 - - getContacts(peers: Peer[]): Promise; - - setThirdPartyBusinessInfos(...args: unknown[]): unknown; // 1 arguments - - updateGameMsgConfigs(...args: unknown[]): unknown; // 1 arguments - - removeKernelRecentContactListener(listenerid: number): unknown; // 1 arguments - - addKernelRecentContactListener(listener: NodeIKernelRecentContactListener): void; - - clearRecentContactsByChatType(...args: unknown[]): unknown; // 1 arguments - - upInsertModule(...args: unknown[]): unknown; // 1 arguments - - jumpToSpecifyRecentContactVer2(...args: unknown[]): unknown; // 1 arguments - - deleteRecentContactsVer2(...args: unknown[]): unknown; // 1 arguments - - getRecentContactList(): Promise; - - getMsgUnreadCount(): unknown; - - clearRecentContacts(): unknown; - - getServiceAssistantRecentContactInfos(): unknown; - - getRecentContactInfos(): unknown; - - getUnreadDetailsInfos(): unknown; - - cleanAllModule(): unknown; - - setAllGameMsgRead(): unknown; - - getRecentContactListSync(): unknown; -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelRichMediaService.ts b/src/core/src/services/NodeIKernelRichMediaService.ts deleted file mode 100644 index b9bd321a..00000000 --- a/src/core/src/services/NodeIKernelRichMediaService.ts +++ /dev/null @@ -1,266 +0,0 @@ -import { GetFileListParam, MessageElement, Peer, SendMessageElement } from "../entities"; -import { GeneralCallResult } from "./common"; -export enum UrlFileDownloadType { - KUNKNOWN, - KURLFILEDOWNLOADPRIVILEGEICON, - KURLFILEDOWNLOADPHOTOWALL, - KURLFILEDOWNLOADQZONE, - KURLFILEDOWNLOADCOMMON, - KURLFILEDOWNLOADINSTALLAPP -} -export enum RMBizTypeEnum { - KUNKNOWN, - KC2CFILE, - KGROUPFILE, - KC2CPIC, - KGROUPPIC, - KDISCPIC, - KC2CVIDEO, - KGROUPVIDEO, - KC2CPTT, - KGROUPPTT, - KFEEDCOMMENTPIC, - KGUILDFILE, - KGUILDPIC, - KGUILDPTT, - KGUILDVIDEO -} -export interface CommonFileInfo { - bizType: number; - chatType: number; - elemId: string; - favId: string; - fileModelId: string; - fileName: string; - fileSize: string; - md5: string; - md510m: string; - msgId: string; - msgTime: string; - parent: string; - peerUid: string; - picThumbPath: Array - sha: string; - sha3: string; - subId: string; - uuid: string; -} -export interface NodeIKernelRichMediaService { - //getVideoPlayUrl(peer, msgId, elemId, videoCodecFormat, VideoRequestWay.KHAND, cb); - // public enum VideoCodecFormatType { - // KCODECFORMATH264, - // KCODECFORMATH265, - // KCODECFORMATH266, - // KCODECFORMATAV1 - // } - // public enum VideoRequestWay { - // KUNKNOW, - // KHAND, - // KAUTO - // } - getVideoPlayUrl(peer: Peer, msgId: string, elemId: string, videoCodecFormat: number, VideoRequestWay: number): Promise; - - //exParams (RMReqExParams) - // this.downSourceType = i2; - // this.triggerType = i3; - //peer, msgId, elemId, videoCodecFormat, exParams - // 1 0 频道在用 - // 1 1 - // 0 2 - - // public static final int KCOMMONREDENVELOPEMSGTYPEINMSGBOX = 1007; - // public static final int KDOWNSOURCETYPEAIOINNER = 1; - // public static final int KDOWNSOURCETYPEBIGSCREEN = 2; - // public static final int KDOWNSOURCETYPEHISTORY = 3; - // public static final int KDOWNSOURCETYPEUNKNOWN = 0; - - // public static final int KTRIGGERTYPEAUTO = 1; - // public static final int KTRIGGERTYPEMANUAL = 0; - - getVideoPlayUrlV2(peer: Peer, msgId: string, elemId: string, videoCodecFormat: number, exParams: { downSourceType: number, triggerType: number }): Promise, - videoCodecFormat: number - } - }>; - - getRichMediaFileDir(elementType: number, downType: number, isTemp: boolean): unknown; - - // this.senderUid = ""; - // this.peerUid = ""; - // this.guildId = ""; - // this.elem = new MsgElement(); - // this.downloadType = i2; - // this.thumbSize = i3; - // this.msgId = j2; - // this.msgRandom = j3; - // this.msgSeq = j4; - // this.msgTime = j5; - // this.chatType = i4; - // this.senderUid = str; - // this.peerUid = str2; - // this.guildId = str3; - // this.elem = msgElement; - // this.useHttps = num; - - getVideoPlayUrlInVisit(arg: { - downloadType: number, - thumbSize: number, - msgId: string, - msgRandom: string, - msgSeq: string, - msgTime: string, - chatType: number, - senderUid: string, - peerUid: string, - guildId: string, - ele: MessageElement, - useHttps: boolean - }): Promise; - - //arg双端number - isFileExpired(arg: number): unknown; - - deleteGroupFolder(GroupCode: string, FolderId: string): Promise; - - //参数与getVideoPlayUrlInVisit一样 - downloadRichMediaInVisit(arg: { - downloadType: number, - thumbSize: number, - msgId: string, - msgRandom: string, - msgSeq: string, - msgTime: string, - chatType: number, - senderUid: string, - peerUid: string, - guildId: string, - ele: MessageElement, - useHttps: boolean - }): unknown; - //arg3为“” - downloadFileForModelId(peer: Peer, ModelId: string[], arg3: string): unknown; - //第三个参数 Array - // this.fileId = ""; - // this.fileName = ""; - // this.fileId = str; - // this.fileName = str2; - // this.fileSize = j2; - // this.fileModelId = j3; - - downloadFileForFileUuid(peer: Peer, uuid: string, arg3: { - fileId: string, - fileName: string, - fileSize: string, - fileModelId: string - }[]): Promise; - - downloadFileByUrlList(fileDownloadTyp: UrlFileDownloadType, urlList: Array): unknown; - - downloadFileForFileInfo(fileInfo: CommonFileInfo[], savePath: string): unknown; - - createGroupFolder(GroupCode: string, FolderName: string): Promise } }> - - downloadFile(commonFile: CommonFileInfo, arg2: unknown, arg3: unknown, savePath: string): unknown; - - createGroupFolder(arg1: unknown, arg2: unknown): unknown; - - downloadGroupFolder(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - renameGroupFolder(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - deleteGroupFolder(arg1: unknown, arg2: unknown): unknown; - - deleteTransferInfo(arg1: unknown, arg2: unknown): unknown; - - cancelTransferTask(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - cancelUrlDownload(arg: unknown): unknown; - - updateOnlineVideoElemStatus(arg: unknown): unknown; - - getGroupSpace(arg: unknown): unknown; - - getGroupFileList(groupCode: string, params: GetFileListParam): Promise; - - getGroupFileInfo(arg1: unknown, arg2: unknown): unknown; - - getGroupTransferList(arg1: unknown, arg2: unknown): unknown; - - renameGroupFile(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown, arg5: unknown): unknown; - - moveGroupFile(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown, arg5: unknown): unknown; - - transGroupFile(arg1: unknown, arg2: unknown): unknown; - - searchGroupFile( - keywords: Array, - param: { - groupIds: Array, - fileType: number, - context: string, - count: number, - sortType: number, - groupNames: Array - }): Promise; - searchGroupFileByWord(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown, arg5: unknown): unknown; - - deleteGroupFile(GroupCode: string, params: Array, Files: Array): Promise - failFileIdList: Array - } - }>; - - translateEnWordToZn(words: string[]): Promise; - - getScreenOCR(path: string): Promise; - - batchGetGroupFileCount(Gids: Array): Promise, groupFileCounts: Array }>; - - queryPicDownloadSize(arg: unknown): unknown; - - searchGroupFile(arg1: unknown, arg2: unknown): unknown; - - searchMoreGroupFile(arg: unknown): unknown; - - cancelSearcheGroupFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - onlyDownloadFile(peer: Peer, arg2: unknown, arg3: Array<{ - fileId: string, - fileName: string, - fileSize: string, - fileModelId: string - } - >): unknown; - - onlyUploadFile(arg1: unknown, arg2: unknown): unknown; - - isExtraLargePic(arg1: unknown, arg2: unknown, arg3: unknown): unknown; - - uploadRMFileWithoutMsg(arg: { - bizType: RMBizTypeEnum, - filePath: string, - peerUid: string, - transferId: string - useNTV2: string - }): Promise; - - isNull(): boolean; -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelRobotService.ts b/src/core/src/services/NodeIKernelRobotService.ts deleted file mode 100644 index 9df5cdce..00000000 --- a/src/core/src/services/NodeIKernelRobotService.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { NodeIKernelRobotListener } from "@/core/listeners"; - -export interface NodeIKernelRobotService { - fetchGroupRobotStoreDiscovery(arg: unknown): unknown; - - sendGroupRobotStoreSearch(arg: unknown): unknown; - - fetchGroupRobotStoreCategoryList(arg: unknown): unknown; - - FetchSubscribeMsgTemplate(arg: unknown): unknown; - - FetchSubcribeMsgTemplateStatus(arg: unknown): unknown; - - SubscribeMsgTemplateSet(arg1: unknown, arg2: unknown): unknown; - - fetchRecentUsedRobots(arg: unknown): unknown; - - fetchShareArkInfo(arg: unknown): unknown; - - addKernelRobotListener(Listener: NodeIKernelRobotListener): number; - - removeKernelRobotListener(ListenerId: number): unknown; - - getAllRobotFriendsFromCache(): Promise; - - fetchAllRobots(arg1: unknown, arg2: unknown): unknown; - - removeAllRecommendCache(): unknown; - - setRobotPickTts(arg1: unknown, arg2: unknown): unknown; - - getRobotUinRange(data: any): Promise<{ response: { robotUinRanges: any } }> - - isNull(): boolean; -} diff --git a/src/core/src/services/NodeIKernelSearchService.ts b/src/core/src/services/NodeIKernelSearchService.ts deleted file mode 100644 index 3f91a0e3..00000000 --- a/src/core/src/services/NodeIKernelSearchService.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { ChatType } from "../entities"; - -export interface NodeIKernelSearchService { - addKernelSearchListener(...args: any[]): unknown;// needs 1 arguments - - removeKernelSearchListener(...args: any[]): unknown;// needs 1 arguments - - searchStranger(...args: any[]): unknown;// needs 3 arguments - - searchGroup(...args: any[]): unknown;// needs 1 arguments - - searchLocalInfo(keywords: string, unknown: number/*4*/): unknown; - - cancelSearchLocalInfo(...args: any[]): unknown;// needs 3 arguments - - searchBuddyChatInfo(...args: any[]): unknown;// needs 2 arguments - - searchMoreBuddyChatInfo(...args: any[]): unknown;// needs 1 arguments - - cancelSearchBuddyChatInfo(...args: any[]): unknown;// needs 3 arguments - - searchContact(...args: any[]): unknown;// needs 2 arguments - - searchMoreContact(...args: any[]): unknown;// needs 1 arguments - - cancelSearchContact(...args: any[]): unknown;// needs 3 arguments - - searchGroupChatInfo(...args: any[]): unknown;// needs 3 arguments - - resetSearchGroupChatInfoSortType(...args: any[]): unknown;// needs 3 arguments - - resetSearchGroupChatInfoFilterMembers(...args: any[]): unknown;// needs 3 arguments - - searchMoreGroupChatInfo(...args: any[]): unknown;// needs 1 arguments - - cancelSearchGroupChatInfo(...args: any[]): unknown;// needs 3 arguments - - searchChatsWithKeywords(...args: any[]): unknown;// needs 3 arguments - - searchMoreChatsWithKeywords(...args: any[]): unknown;// needs 1 arguments - - cancelSearchChatsWithKeywords(...args: any[]): unknown;// needs 3 arguments - - searchChatMsgs(...args: any[]): unknown;// needs 2 arguments - - searchMoreChatMsgs(...args: any[]): unknown;// needs 1 arguments - - cancelSearchChatMsgs(...args: any[]): unknown;// needs 3 arguments - - searchMsgWithKeywords(...args: any[]): unknown;// needs 2 arguments - - searchMoreMsgWithKeywords(...args: any[]): unknown;// needs 1 arguments - - cancelSearchMsgWithKeywords(...args: any[]): unknown;// needs 3 arguments - - searchFileWithKeywords(keywords: string[], source: number): Promise;// needs 2 arguments - - searchMoreFileWithKeywords(...args: any[]): unknown;// needs 1 arguments - - cancelSearchFileWithKeywords(...args: any[]): unknown;// needs 3 arguments - - searchAtMeChats(...args: any[]): unknown;// needs 3 arguments - - searchMoreAtMeChats(...args: any[]): unknown;// needs 1 arguments - - cancelSearchAtMeChats(...args: any[]): unknown;// needs 3 arguments - - searchChatAtMeMsgs(...args: any[]): unknown;// needs 1 arguments - - searchMoreChatAtMeMsgs(...args: any[]): unknown;// needs 1 arguments - - cancelSearchChatAtMeMsgs(...args: any[]): unknown;// needs 3 arguments - - addSearchHistory(param: { - type: number,//4 - contactList: [], - id: number,//-1 - groupInfos: [], - msgs: [], - fileInfos: [ - { - chatType: ChatType, - buddyChatInfo: Array<{ category_name: string, peerUid: string, peerUin: string, remark: string }>, - discussChatInfo: [], - groupChatInfo: Array< - { - groupCode: string, - isConf: boolean, - hasModifyConfGroupFace: boolean, - hasModifyConfGroupName: boolean, - groupName: string, - remark: string - }> - , - dataLineChatInfo: [], - tmpChatInfo: [], - msgId: string, - msgSeq: string, - msgTime: string, - senderUid: string, - senderNick: string, - senderRemark: string, - senderCard: string, - elemId: string, - elemType: string,//3 - fileSize: string, - filePath: string, - fileName: string, - hits: Array< - { - start: 12, - end: 14 - } - > - } - ] - - }): Promise<{ - result: number, - errMsg: string, - id?: number - }>; - - removeSearchHistory(...args: any[]): unknown;// needs 1 arguments - - searchCache(...args: any[]): unknown;// needs 3 arguments - - clearSearchCache(...args: any[]): unknown;// needs 1 arguments -} diff --git a/src/core/src/services/NodeIKernelStorageCleanService.ts b/src/core/src/services/NodeIKernelStorageCleanService.ts deleted file mode 100644 index 34c26714..00000000 --- a/src/core/src/services/NodeIKernelStorageCleanService.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { NodeIKernelStorageCleanListener } from "@/core/listeners"; -import { GeneralCallResult } from "./common"; - -export interface NodeIKernelStorageCleanService { - - addKernelStorageCleanListener(Listener: NodeIKernelStorageCleanListener): number; - - removeKernelStorageCleanListener(ListenerId: number): void; - - addCacheScanedPaths(arg: unknown): unknown; - - addFilesScanedPaths(arg: unknown): unknown; - - scanCache(): Promise; - - addReportData(arg: unknown): unknown; - - reportData(): unknown; - - getChatCacheInfo(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown): unknown; - - getFileCacheInfo(arg1: unknown, arg2: unknown, arg3: unknown, arg44: unknown, args5: unknown): unknown; - - clearChatCacheInfo(arg1: unknown, arg2: unknown): unknown; - - clearCacheDataByKeys(arg: unknown): unknown; - - setSilentScan(arg: unknown): unknown; - - closeCleanWindow(): unknown; - - clearAllChatCacheInfo(): unknown; - - endScan(arg: unknown): unknown; - - addNewDownloadOrUploadFile(arg: unknown): unknown; - - isNull(): boolean; -} diff --git a/src/core/src/services/NodeIKernelTianShuService.ts b/src/core/src/services/NodeIKernelTianShuService.ts deleted file mode 100644 index 48622c7e..00000000 --- a/src/core/src/services/NodeIKernelTianShuService.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface NodeIKernelTianShuService { - addKernelTianShuListener(...args: any[]): unknown;// needs 1 arguments - - removeKernelTianShuListener(...args: any[]): unknown;// needs 1 arguments - - requesTianShuNumeralRe(...args: any[]): unknown;//d needs 1 arguments - - reportTianShuNumeralRed(...args: any[]): unknown;// needs 1 arguments - -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelTicketService.ts b/src/core/src/services/NodeIKernelTicketService.ts deleted file mode 100644 index 0178f755..00000000 --- a/src/core/src/services/NodeIKernelTicketService.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { forceFetchClientKeyRetType } from "./common"; - -export interface NodeIKernelTicketService { - - addKernelTicketListener(listener: unknown): void; - - removeKernelTicketListener(listenerId: unknown): void; - - forceFetchClientKey(arg: string): Promise; - - isNull(): boolean; -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelTipOffService.ts b/src/core/src/services/NodeIKernelTipOffService.ts deleted file mode 100644 index 7071f893..00000000 --- a/src/core/src/services/NodeIKernelTipOffService.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { GeneralCallResult } from "./common"; - -export interface NodeIKernelTipOffService { - - addKernelTipOffListener(listener: unknown): void; - - removeKernelTipOffListener(listenerId: unknown): void; - - tipOffSendJsData(args: unknown[]): Promise;//2 - - getPskey(domainList: string[], nocache: boolean): Promise }>;//2 - - tipOffSendJsData(args: unknown[]): Promise;//2 - - tipOffMsgs(args: unknown[]): Promise;//1 - - encodeUinAesInfo(args: unknown[]): Promise;//2 - - isNull(): boolean; -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelUixConvertService.ts b/src/core/src/services/NodeIKernelUixConvertService.ts deleted file mode 100644 index b203c481..00000000 --- a/src/core/src/services/NodeIKernelUixConvertService.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface NodeIKernelUixConvertService { - getUin(uid: string[]): Promise<{ uinInfo: Map }>; - - getUid(uin: string[]): Promise<{ uidInfo: Map }>; -} \ No newline at end of file diff --git a/src/core/src/services/NodeIKernelUnitedConfigService.ts b/src/core/src/services/NodeIKernelUnitedConfigService.ts deleted file mode 100644 index f96a4f0e..00000000 --- a/src/core/src/services/NodeIKernelUnitedConfigService.ts +++ /dev/null @@ -1,15 +0,0 @@ -export interface NodeIKernelUnitedConfigService{ - addKernelUnitedConfigListener(...args: any[]): unknown;// needs 1 arguments - - removeKernelUnitedConfigListener(...args: any[]): unknown;// needs 1 arguments - - fetchUnitedCommendConfig(...args: any[]): unknown;// needs 1 arguments - - fetchUnitedSwitchConfig(...args: any[]): unknown;// needs 1 arguments - - loadUnitedConfig(...args: any[]): unknown;// needs 1 arguments - - isUnitedConfigSwitchOn(...args: any[]): unknown;// needs 1 arguments - - registerUnitedConfigPushGroupList(...args: any[]): unknown;// needs 1 arguments -} diff --git a/src/core/src/services/NodeIYellowFaceService.ts b/src/core/src/services/NodeIYellowFaceService.ts deleted file mode 100644 index 31ef0ff6..00000000 --- a/src/core/src/services/NodeIYellowFaceService.ts +++ /dev/null @@ -1,5 +0,0 @@ -// public interface IYellowFaceForManagerService extends QRouteApi { -// void download(@NotNull String resourceConfigJson, @NotNull String resourceDir, @NotNull String cacheDir, boolean force, @NotNull IKernelYellowFaceDownloadCallback callback); - -// void setHistory(@NotNull String fullMd5, @NotNull IOperateCallback callback); -// } \ No newline at end of file diff --git a/src/core/src/services/NodeIkernelTestPerformanceService.ts b/src/core/src/services/NodeIkernelTestPerformanceService.ts deleted file mode 100644 index ae774898..00000000 --- a/src/core/src/services/NodeIkernelTestPerformanceService.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { MessageElement, Peer } from "../entities"; - -export interface NodeIkernelTestPerformanceService { - insertMsg(MsgParam: { - peer: Peer - msgTime: string - msgId: string - msgSeq: string - batchNums: number - timesPerBatch: number - numPerTime: number - }, msg: Array): Promise; - -} \ No newline at end of file diff --git a/src/core/src/services/common.ts b/src/core/src/services/common.ts deleted file mode 100644 index acd1e6f1..00000000 --- a/src/core/src/services/common.ts +++ /dev/null @@ -1,15 +0,0 @@ - -export enum GeneralCallResultStatus { - OK = 0, - // ERROR = 1, -} -export interface GeneralCallResult{ - result: GeneralCallResultStatus, - errMsg: string -} -export interface forceFetchClientKeyRetType extends GeneralCallResult { - url: string; - keyIndex: string; - clientKey: string; - expireTime: string; - } \ No newline at end of file diff --git a/src/core/src/services/index.ts b/src/core/src/services/index.ts deleted file mode 100644 index efab2edd..00000000 --- a/src/core/src/services/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export * from './common'; -export * from './NodeIKernelAvatarService'; -export * from './NodeIKernelBuddyService'; -export * from './NodeIKernelFileAssistantService'; -export * from './NodeIKernelGroupService'; -export * from './NodeIKernelLoginService'; -export * from './NodeIKernelMsgService'; -export * from './NodeIKernelOnlineStatusService'; -export * from './NodeIKernelProfileLikeService'; -export * from './NodeIKernelProfileService'; -export * from './NodeIKernelTicketService'; -export * from './NodeIKernelStorageCleanService'; -export * from './NodeIKernelRobotService'; -export * from './NodeIKernelRichMediaService'; -export * from './NodeIKernelDbToolsService'; -export * from './NodeIKernelTipOffService' \ No newline at end of file diff --git a/src/core/src/sessionConfig.ts b/src/core/src/sessionConfig.ts deleted file mode 100644 index 4fb5d28a..00000000 --- a/src/core/src/sessionConfig.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { getFullQQVesion, QQVersionAppid } from '@/common/utils/QQBasicInfo'; -import { hostname, systemName, systemVersion } from '@/common/utils/system'; -import path from 'node:path'; -import fs from 'node:fs'; -import { getMachineId } from '@/common/utils/system'; -// 补充 -export enum PlatformType { - KUNKNOWN, - KANDROID, - KIOS, - KWINDOWS, - KMAC -} -export enum DeviceType { - KUNKNOWN, - KPHONE, - KPAD, - KCOMPUTER -} -//推送类型 -export enum VendorType { - KNOSETONIOS = 0, - KSUPPORTGOOGLEPUSH = 99, - KSUPPORTHMS = 3, - KSUPPORTOPPOPUSH = 4, - KSUPPORTTPNS = 2, - KSUPPORTVIVOPUSH = 5, - KUNSUPPORTANDROIDPUSH = 1 -} -export interface WrapperSessionInitConfig { - selfUin: string - selfUid: string - desktopPathConfig: { - account_path: string // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取 - } - clientVer: string // 9.9.8-22355 - a2: string, - d2: string, - d2Key: string, - machineId: string, - platform: PlatformType, // 3是Windows? - platVer: string, // 系统版本号, 应该可以固定 - appid: string, - rdeliveryConfig: { - appKey: string, - systemId: number, - appId: string, - logicEnvironment: string, - platform: PlatformType, - language: string, - sdkVersion: string, - userId: string, - appVersion: string, - osVersion: string, - bundleId: string, - serverUrl: string, - fixedAfterHitKeys: string[] - } - defaultFileDownloadPath: string, // 这个可以通过环境变量获取? - deviceInfo: { - guid: string, - buildVer: string, - localId: number, - devName: string, - devType: string, - vendorName: string, - osVer: string, - vendorOsName: string, - setMute: boolean, - vendorType: VendorType - }, - deviceConfig: '{"appearance":{"isSplitViewMode":true},"msg":{}}' -} - -export const sessionConfig: WrapperSessionInitConfig | any = {}; - -export async function genSessionConfig(selfUin: string, selfUid: string, account_path: string): Promise { - const downloadPath = path.join(account_path, 'NapCat', 'temp'); - fs.mkdirSync(downloadPath, { recursive: true }); - let guid: string = await getMachineId();//26702 支持JS获取guid值 在LoginService中获取 TODO mlikiow a - //console.log(guid); - // guid = '52afb776-82f6-4e59-9d38-44705b112d0a'; - //let guid: string = await getMachineId(); - const config: WrapperSessionInitConfig = { - selfUin, - selfUid, - desktopPathConfig: { - account_path // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取 - }, - clientVer: getFullQQVesion(), // 9.9.8-22355 - a2: '', - d2: '', - d2Key: '', - machineId: '', - platform: PlatformType.KWINDOWS, // 3是Windows? - platVer: systemVersion, // 系统版本号, 应该可以固定 - appid: QQVersionAppid, - rdeliveryConfig: { - appKey: '', - systemId: 0, - appId: '', - logicEnvironment: '', - platform: PlatformType.KWINDOWS, - language: '', - sdkVersion: '', - userId: '', - appVersion: '', - osVersion: '', - bundleId: '', - serverUrl: '', - fixedAfterHitKeys: [''] - }, - defaultFileDownloadPath: downloadPath, - deviceInfo: { - guid, - buildVer: getFullQQVesion(), - localId: 2052, - devName: hostname, - devType: systemName, - vendorName: '', - osVer: systemVersion, - vendorOsName: systemName, - setMute: false, - vendorType: VendorType.KNOSETONIOS - }, - deviceConfig: '{"appearance":{"isSplitViewMode":true},"msg":{}}' - }; - Object.assign(sessionConfig, config); - return config; -} diff --git a/src/core/src/utils/config.ts b/src/core/src/utils/config.ts deleted file mode 100644 index 5686e429..00000000 --- a/src/core/src/utils/config.ts +++ /dev/null @@ -1,28 +0,0 @@ -import path from 'node:path'; -import fs from 'node:fs'; -import { enableConsoleLog, enableFileLog, logDebug, logError, LogLevel, setLogLevel } from '@/common/utils/log'; -import { ConfigBase } from '@/common/utils/ConfigBase'; -import { selfInfo } from '@/core/data'; - - -export interface NapCatConfig { - fileLog: boolean, - consoleLog: boolean, - fileLogLevel: LogLevel, - consoleLogLevel: LogLevel, -} - -class Config extends ConfigBase implements NapCatConfig { - name: string = 'napcat' - fileLog = true; - consoleLog = true; - fileLogLevel = LogLevel.DEBUG; - consoleLogLevel = LogLevel.INFO; - - constructor() { - super(); - } -} - -export const napCatConfig = new Config(); - diff --git a/src/core/src/utils/rkey.ts b/src/core/src/utils/rkey.ts deleted file mode 100644 index d22daeb4..00000000 --- a/src/core/src/utils/rkey.ts +++ /dev/null @@ -1,42 +0,0 @@ -//远端rkey获取 -import { logError } from '@/common/utils/log'; -import { RequestUtil } from '@/common/utils/request'; - -interface ServerRkeyData { - group_rkey: string; - private_rkey: string; - expired_time: number; -} - -class RkeyManager { - serverUrl: string = ''; - private rkeyData: ServerRkeyData = { - group_rkey: '', - private_rkey: '', - expired_time: 0 - }; - constructor(serverUrl: string) { - this.serverUrl = serverUrl; - } - async getRkey() { - if (this.isExpired()) { - try { - await this.refreshRkey(); - } catch (e) { - logError('获取rkey失败', e); - } - } - return this.rkeyData; - } - - isExpired(): boolean { - const now = new Date().getTime() / 1000; - // console.log(`now: ${now}, expired_time: ${this.rkeyData.expired_time}`); - return now > this.rkeyData.expired_time; - } - async refreshRkey(): Promise { - //刷新rkey - this.rkeyData = await RequestUtil.HttpGetJson(this.serverUrl, 'GET'); - } -} -export const rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey'); diff --git a/src/core/src/wrapper.ts b/src/core/src/wrapper.ts deleted file mode 100644 index 62f17b87..00000000 --- a/src/core/src/wrapper.ts +++ /dev/null @@ -1,300 +0,0 @@ -import path from 'node:path'; -import fs from 'node:fs'; -import { WrapperSessionInitConfig } from './sessionConfig'; -import { - NodeIDependsAdapter, - NodeIDispatcherAdapter, - NodeIGlobalAdapter, -} from './adapters'; -import { - NodeIKernelSessionListener, - NodeIKernelMsgListener, - NodeIKernelLoginListener, - NodeIKernelBuddyListener, - NodeIKernelGroupListener, - NodeIKernelProfileListener, -} from './listeners'; -import { - NodeIKernelLoginService, - NodeIKernelMsgService, - NodeIKernelBuddyService, - NodeIKernelGroupService, - NodeIKernelProfileService, - NodeIKernelProfileLikeService, - NodeIKernelTicketService, - NodeIKernelTipOffService, - NodeIKernelRichMediaService, - NodeIKernelAvatarService, -} from './services'; -import { NodeIKernelStorageCleanService } from './services/NodeIKernelStorageCleanService'; -import { NodeIKernelRobotService } from './services/NodeIKernelRobotService'; -import { dirname } from "node:path" -import { fileURLToPath } from "node:url" -import { NodeIKernelNodeMiscService } from './services/NodeIKernelNodeMiscService'; -import { NodeIKernelUixConvertService } from './services/NodeIKernelUixConvertService'; -import { NodeIKernelMsgBackupService } from './services/NodeIKernelMsgBackupService'; -import { NodeIKernelAlbumService } from './services/NodeIKernelAlbumService'; -import { NodeIKernelTianShuService } from './services/NodeIKernelTianShuService'; -import { NodeIKernelUnitedConfigService } from './services/NodeIKernelUnitedConfigService'; -import { NodeIKernelSearchService } from './services/NodeIKernelSearchService'; -import { NodeIKernelCollectionService } from './services/NodeIKernelCollectionService'; -import { NodeIKernelRecentContactService } from './services/NodeIKernelRecentContactService'; -import { NodeIKernelMSFService } from './services/NodeIKernelMSFService'; -import { NodeIkernelTestPerformanceService } from './services/NodeIkernelTestPerformanceService'; -import { NodeIKernelECDHService } from './services/NodeIKernelECDHService'; -import { getFullQQVesion } from '@/common/utils/QQBasicInfo'; - - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -export interface NodeQQNTWrapperUtil { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(): NodeQQNTWrapperUtil - - getNTUserDataInfoConfig(): string - - emptyWorkingSet(n: number): void - - getSsoCmdOfOidbReq(arg1: number, arg2: number): unknown, - - getSsoBufferOfOidbReq(...args: unknown[]): unknown,//有点看不懂参数定义 待补充 好像是三个参数 - - getOidbRspInfo(arg: string): unknown,//可能是错的 - - getFileSize(path: string): Promise,//直接的猜测 - - genFileMd5Buf(arg: string): unknown,//可能是错的 - - genFileMd5Hex(path: string): unknown,//直接的猜测 - - genFileShaBuf(path: string): unknown,//直接的猜测 - - genFileCumulateSha1(path: string): unknown,//直接的猜测 - - genFileShaHex(path: string): unknown,//直接的猜测 - - fileIsExist(path: string): unknown, - - startTrace(path: string): unknown,//可能是错的 - - copyFile(src: string, dst: string): unknown, - - genFileShaAndMd5Hex(path: string, unknown: number): unknown,//可能是错的 - - setTraceInfo(unknown: Object): unknown, - - encodeOffLine(unknown: Object): unknown, - - decodeOffLine(arg: string): unknown,//可能是错的 传递hex - - DecoderRecentInfo(arg: string): unknown,//可能是错的 传递hex - - getPinyin(arg0: string, arg1: boolean): unknown, - - matchInPinyin(arg0: any[], arg1: string): unknown,//参数特复杂 arg0是个复杂数据类型 - - makeDirByPath(arg0: string): unknown, - - emptyWorkingSet(arg0: number): unknown,//参数是UINT32 - - runProcess(arg0: string, arg1: boolean): unknown, - - runProcessArgs(arg0: string, arg1: { [key: string]: string; }, arg2: boolean): unknown, - - calcThumbSize(arg0: number, arg1: number, arg2: Object): unknown, - - fullWordToHalfWord(arg0: string): unknown, - - getNTUserDataInfoConfig(): unknown, - - pathIsReadableAndWriteable(path: string): unknown,//直接的猜测 - - resetUserDataSavePathToDocument(): unknown, - - getSoBuildInfo(): any,//例如 0[0]_d491dc01e0a_0 - - registerCountInstruments(arg0: string, arg1: string[], arg2: number, arg3: number): unknown, - - registerValueInstruments(arg0: string, arg1: string[], arg2: number, arg3: number): unknown, - - registerValueInstrumentsWithBoundary(arg0: string, arg1: unknown, arg2: unknown, arg3: number, arg4: number): unknown, - - reportCountIndicators(arg0: string, arg1: Map, arg2: string, arg3: number, arg4: boolean): unknown, - - reportValueIndicators(arg0: string, arg1: Map, arg2: string, arg3: boolean, arg4: number): unknown, - - checkNewUserDataSaveDirAvailable(arg0: string): unknown, - - copyUserData(arg0: string, arg1: string): Promise, - - setUserDataSaveDirectory(arg0: string): Promise, - - hasOtherRunningQQProcess(): boolean, - - quitAllRunningQQProcess(arg: boolean): unknown, - - checkNvidiaConfig(): unknown, - - repairNvidiaConfig(): unknown, - - getNvidiaDriverVersion(): unknown, - - isNull(): unknown -} - -export interface NodeIQQNTWrapperSession { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(): NodeIQQNTWrapperSession; - - init( - wrapperSessionInitConfig: WrapperSessionInitConfig, - nodeIDependsAdapter: NodeIDependsAdapter, - nodeIDispatcherAdapter: NodeIDispatcherAdapter, - nodeIKernelSessionListener: NodeIKernelSessionListener - ): void; - - startNT(n: 0): void; - - startNT(): void; - - getBdhUploadService(): unknown; - - getECDHService(): NodeIKernelECDHService; - - getMsgService(): NodeIKernelMsgService; - - getProfileService(): NodeIKernelProfileService; - - getProfileLikeService(): NodeIKernelProfileLikeService; - - getGroupService(): NodeIKernelGroupService; - - getStorageCleanService(): NodeIKernelStorageCleanService; - - getBuddyService(): NodeIKernelBuddyService; - - getRobotService(): NodeIKernelRobotService; - - getTicketService(): NodeIKernelTicketService; - - getTipOffService(): NodeIKernelTipOffService; - - getNodeMiscService(): NodeIKernelNodeMiscService; - - getRichMediaService(): NodeIKernelRichMediaService; - - getMsgBackupService(): NodeIKernelMsgBackupService; - - getAlbumService(): NodeIKernelAlbumService; - - getTianShuService(): NodeIKernelTianShuService; - - getUnitedConfigService(): NodeIKernelUnitedConfigService; - - getSearchService(): NodeIKernelSearchService; - - getDirectSessionService(): unknown; - - getRDeliveryService(): unknown; - - getAvatarService(): NodeIKernelAvatarService; - - getFeedChannelService(): unknown; - - getYellowFaceService(): unknown; - - getCollectionService(): NodeIKernelCollectionService; - - getSettingService(): unknown; - - getQiDianService(): unknown; - - getFileAssistantService(): unknown; - - getGuildService(): unknown; - - getSkinService(): unknown; - - getTestPerformanceService(): NodeIkernelTestPerformanceService; - - getQQPlayService(): unknown; - - getDbToolsService(): unknown; - - getUixConvertService(): NodeIKernelUixConvertService; - - getOnlineStatusService(): unknown; - - getRemotingService(): unknown; - - getGroupTabService(): unknown; - - getGroupSchoolService(): unknown; - - getLiteBusinessService(): unknown; - - getGuildMsgService(): unknown; - - getLockService(): unknown; - - getMSFService(): NodeIKernelMSFService; - - getGuildHotUpdateService(): unknown; - - getAVSDKService(): unknown; - - getRecentContactService(): NodeIKernelRecentContactService; - - getConfigMgrService(): unknown; -} - -export interface EnginInitDesktopConfig { - base_path_prefix: string, - platform_type: 3, - app_type: 4, - app_version: string, - os_version: string, - use_xlog: true, - qua: string, - global_path_config: { - desktopGlobalPath: string, - }, - thumb_config: { maxSide: 324, minSide: 48, longLimit: 6, density: 2 } -} - -export interface NodeIQQNTWrapperEngine { - // eslint-disable-next-line @typescript-eslint/no-misused-new - new(): NodeIQQNTWrapperEngine; - - initWithDeskTopConfig(config: EnginInitDesktopConfig, nodeIGlobalAdapter: NodeIGlobalAdapter): void; -} - -export interface WrapperNodeApi { - [key: string]: any; - - NodeIKernelBuddyListener: NodeIKernelBuddyListener; - NodeIKernelGroupListener: NodeIKernelGroupListener; - NodeQQNTWrapperUtil: NodeQQNTWrapperUtil; - NodeIQQNTWrapperSession: NodeIQQNTWrapperSession; - NodeIKernelMsgListener: NodeIKernelMsgListener; - NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine; - NodeIGlobalAdapter: NodeIGlobalAdapter; - NodeIDependsAdapter: NodeIDependsAdapter; - NodeIDispatcherAdapter: NodeIDispatcherAdapter; - NodeIKernelSessionListener: NodeIKernelSessionListener; - NodeIKernelLoginService: NodeIKernelLoginService; - NodeIKernelLoginListener: NodeIKernelLoginListener; - - NodeIKernelProfileService: NodeIKernelProfileService; - NodeIKernelProfileListener: NodeIKernelProfileListener; -} - -let wrapperNodePath = path.resolve(path.dirname(process.execPath), './resources/app/wrapper.node'); -if (!fs.existsSync(wrapperNodePath)) { - wrapperNodePath = path.join(path.dirname(process.execPath), `resources/app/versions/${getFullQQVesion()}/wrapper.node`); -} -const nativemodule: any = { exports: {} }; -process.dlopen(nativemodule, wrapperNodePath); -const QQWrapper: WrapperNodeApi = nativemodule.exports; -export default QQWrapper; diff --git a/src/core/tsconfig.old.json b/src/core/tsconfig.old.json deleted file mode 100644 index a4f82106..00000000 --- a/src/core/tsconfig.old.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "outDir": "./dist", - "declaration": true, - "target": "ESNext", - "useDefineForClassFields": true, - "esModuleInterop": true, - "module": "ESNext", - "lib": [ - "ES2020", - "DOM", - "DOM.Iterable" - ], - "skipLibCheck": true, - "moduleResolution": "Node", - "experimentalDecorators": true, - "allowImportingTsExtensions": false, - "allowSyntheticDefaultImports": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": false, - "jsx": "preserve", - "strict": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noFallthroughCasesInSwitch": true, - "paths": { - "@/common/*": [ - "../common/*" - ], - "@/core": [ - "./src/index" - ], - "@/core/*": [ - "./src/*" - ] - } - }, - "include": [ - "./src/**/*.ts" - ] -} diff --git a/src/core/vite.config.old.ts b/src/core/vite.config.old.ts deleted file mode 100644 index 2c7b9ed9..00000000 --- a/src/core/vite.config.old.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { UserConfig, defineConfig } from 'vite'; -import { builtinModules } from 'module'; -import obfuscator from 'rollup-plugin-obfuscator'; -import { Plugin } from 'vite'; -import path from 'node:path'; -import dts from 'vite-plugin-dts'; -import cp from 'vite-plugin-cp'; -import babel from 'vite-plugin-babel'; - -const external: string[] = [ /* Empty */]; -const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat(); - -const baseConfig: UserConfig = { - build: { - target: 'modules', - outDir: './', - lib: { - name: '@napneko/core', - entry: 'src/index.ts', - formats: ['es'], - fileName: () => 'index.js', - }, - rollupOptions: { - input: { - index: path.resolve(__dirname, 'src/index.ts'), - qqnt: path.resolve(__dirname, 'src/qqnt/index.ts'), - 'qqnt/apis': path.resolve(__dirname, 'src/qqnt/apis/index.ts'), - 'qqnt/listeners': path.resolve(__dirname, 'src/qqnt/listeners/index.ts'), - 'qqnt/entities': path.resolve(__dirname, 'src/qqnt/entities/index.ts'), - 'qqnt/adapters': path.resolve(__dirname, 'src/qqnt/adapters/index.ts'), - 'qqnt/services': path.resolve(__dirname, 'src/qqnt/services/index.ts'), - service: path.resolve(__dirname, 'src/service/index.ts') - }, - output: { - // 输出设置为系统模块格式,确保目录结构被保持 - format: 'esm', - dir: path.resolve(__dirname, './dist/core/src'), - entryFileNames: '[name]/index.js', - chunkFileNames: '[name]/[hash]/index.js', - // preserveModules: true, // 保持模块结构 - // preserveModulesRoot: 'src' - }, - external: [...nodeModules, ...external], - }, - }, - resolve: { - alias: { - '@/common': path.resolve(__dirname, '../common'), - '@/core': path.resolve(__dirname, './src'), - './lib-cov/fluent-ffmpeg': './lib/fluent-ffmpeg', - } - }, -}; - -const commonPlugins: Plugin[] = [ - babel({ - filter: /.*\.(ts)$/, - babelConfig: { - babelrc: false, - configFile: false, - presets: ["@babel/preset-typescript"], - plugins: [ - ['@babel/plugin-proposal-decorators', { legacy: true }], - '@babel/plugin-proposal-class-properties', - ], - }, - }), - dts({ - outDir: './dist', - staticImport: true, - rollupTypes: false, - include: 'src/**/*.ts', - }), - cp({ - targets: [ - // ...external.map(genCpModule), - { src: './pub-package.json', dest: '../core.lib', rename: 'package.json' }, - ] - }) -]; -export default defineConfig(({ mode }) => { - const result: UserConfig = { ...baseConfig }; - if (mode === 'production') { - result.build!.minify = 'esbuild'; - result.plugins = [ - obfuscator({ - options: { - compact: true, - controlFlowFlattening: true, - controlFlowFlatteningThreshold: 0.75, - deadCodeInjection: true, - deadCodeInjectionThreshold: 0.4, - debugProtection: false, - disableConsoleOutput: false, - identifierNamesGenerator: 'hexadecimal', - log: false, - renameGlobals: false, - rotateStringArray: true, - selfDefending: true, - stringArray: true, - stringArrayEncoding: ['base64'], - stringArrayThreshold: 0.75, - transformObjectKeys: true, - unicodeEscapeSequence: false - }, - include: ['src/**/*.js', 'src/**/*.ts'], - }), - ...commonPlugins - ]; - } else { - result.build!.minify = false; - result.plugins = [...commonPlugins]; - } - - return result; -}); diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 8bd18fde..00000000 --- a/src/index.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { napCatCore } from '@/core'; -import { program } from 'commander'; -import qrcode from 'qrcode-terminal'; -import fs from 'fs/promises'; -import fsSync from 'fs'; -import path from 'node:path'; -import { checkVersion } from '@/common/utils/version'; -import { log, logDebug, logError, LogLevel, logWarn, setLogLevel } from '@/common/utils/log'; -import { NapCatOnebot11 } from '@/onebot11/main'; -import { InitWebUi } from './webui/index'; -import { WebUiDataRuntime } from './webui/src/helper/Data'; -import { deleteOldFiles, UpdateConfig } from './common/utils/helper'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import chalk from 'chalk'; -import { randomInt } from 'crypto'; -import { MessageUnique } from './common/utils/MessageUnique'; - - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); -const tagColor = chalk.cyan; -program - .option('-q, --qq [type]', 'QQ号') - .parse(process.argv); - -//deleteOldFiles(path.join(__dirname, 'logs'), 3).then().catch(); -// UpdateConfig().catch(logError); 移除支持 -// 启动WebUi -InitWebUi(); -const cmdOptions = program.opts(); -// console.log(process.argv); -checkVersion().then(async (remoteVersion: string) => { - const localVersion = JSON.parse(fsSync.readFileSync(path.join(__dirname, 'package.json')).toString()).version; - const localVersionList = localVersion.split('.'); - const remoteVersionList = remoteVersion.split('.'); - log(tagColor('[NapCat]'), '当前版本:', localVersion); - for (const k of [0, 1, 2]) { - if (parseInt(remoteVersionList[k]) > parseInt(localVersionList[k])) { - logWarn(tagColor('[NapCat]'), `检测到更新,请前往 https://github.com/NapNeko/NapCatQQ 下载 NapCatQQ V ${remoteVersion}`); - return; - } else if (parseInt(remoteVersionList[k]) < parseInt(localVersionList[k])) { - break; - } - } - logDebug(tagColor('[NapCat]'), '当前已是最新版本'); - return; -}).catch((e) => { - logError(tagColor('[NapCat]'), '检测更新失败', e); -}); -// 不是很好待优化 -const NapCat_OneBot11 = new NapCatOnebot11(); - -WebUiDataRuntime.setOB11ConfigCall(NapCat_OneBot11.SetConfig); - -napCatCore.onLoginSuccess((uin, uid) => { - log('登录成功!'); - WebUiDataRuntime.setQQLoginStatus(true); - WebUiDataRuntime.setQQLoginUin(uin.toString()); -}); -const showQRCode = async (url: string, base64: string, buffer: Buffer) => { - await WebUiDataRuntime.setQQLoginQrcodeURL(url); - logWarn('请扫描下面的二维码,然后在手Q上授权登录:'); - const qrcodePath = path.join(__dirname, 'qrcode.png'); - qrcode.generate(url, { small: true }, (res) => { - logWarn(`\n${res}\n二维码解码URL: ${url}\n如果控制台二维码无法扫码,可以复制解码url到二维码生成网站生成二维码再扫码,也可以打开下方的二维码路径图片进行扫码`); - fs.writeFile(qrcodePath, buffer).then(() => { - logWarn('二维码已保存到', qrcodePath); - }); - }); -}; - -let quickLoginQQ = cmdOptions.qq; // undefine、true、string -const QuickLoginList = await napCatCore.getQuickLoginList(); -if (quickLoginQQ == true) { - if (QuickLoginList.LocalLoginInfoList.length > 0) { - quickLoginQQ = QuickLoginList.LocalLoginInfoList[0].uin; - log('-q 指令指定使用最近的QQ进行快速登录'); - } else { - quickLoginQQ = ''; - } -} - -// napCatCore.on('system.login.error', (result) => { -// console.error('登录失败', result); -// napCatCore.qrLogin().then().catch(console.error); -// }); -napCatCore.getQuickLoginList().then((res) => { - // 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList - WebUiDataRuntime.setQQQuickLoginList(res.LocalLoginInfoList.filter((item) => item.isQuickLogin).map((item) => item.uin.toString())); -}); - -WebUiDataRuntime.setQQQuickLoginCall(async (uin: string) => { - const QuickLogin: Promise<{ result: boolean, message: string }> = new Promise((resolve, reject) => { - if (uin) { - log('正在快速登录 ', uin); - napCatCore.quickLogin(uin).then(res => { - if (res.loginErrorInfo.errMsg) { - resolve({ result: false, message: res.loginErrorInfo.errMsg }); - } - resolve({ result: true, message: '' }); - }).catch((e) => { - logError(e); - resolve({ result: false, message: '快速登录发生错误' }); - }); - } else { - resolve({ result: false, message: '快速登录失败' }); - } - }); - const result = await QuickLogin; - return result; -}); - -if (quickLoginQQ) { - log('正在快速登录 ', quickLoginQQ); - napCatCore.quickLogin(quickLoginQQ).then(res => { - if (res.loginErrorInfo.errMsg) { - logError('快速登录错误:', res.loginErrorInfo.errMsg); - } - }).catch((e) => { - logError('快速登录错误:', e); - napCatCore.qrLogin(showQRCode); - }); -} else { - log('没有 -q 指令指定快速登录,将使用二维码登录方式'); - if (QuickLoginList.LocalLoginInfoList.length > 0) { - log(`可用于快速登录的QQ:${QuickLoginList.LocalLoginInfoList.map((u, index) => `\n${index}: ${u.uin} ${u.nickName}`)}`); - } - napCatCore.qrLogin(showQRCode); -} - -// napCatCore.login.service.getLoginList().then((res) => { -// const quickLoginUinList = res.LocalLoginInfoList.filter((item) => item.isQuickLogin).map((item) => item.uin); -// if (quickLoginUinList.length !== 0) { -// const askQuickLoginUin = readline.createInterface({ -// input: process.stdin, -// output: process.stdout -// }); -// const prompt = `选择快速登录的账号\n\n ${quickLoginUinList.map((u, index) => `${index}: ${u}\n`)}\n输入对应序号按回车确定: `; -// askQuickLoginUin.question(prompt, (uinIndex) => { -// console.log('你选择的是:', uinIndex); -// const uin = quickLoginUinList[parseInt(uinIndex)]; -// if (!uin) { -// console.error('请输入正确的序号'); -// return; -// } -// console.log('开始登录', uin); -// napCatCore.login.quick(uin).then().catch((e) => { -// console.error(e); -// }); -// }); -// } -// } -// ); -//napCatCore.passwordLogin("", "").then(console.log).catch((e) => { -// console.log(e) -//}) diff --git a/src/liteloader/napcat.cjs b/src/liteloader/napcat.cjs new file mode 100644 index 00000000..3efed94f --- /dev/null +++ b/src/liteloader/napcat.cjs @@ -0,0 +1 @@ +//NapCat Main \ No newline at end of file diff --git a/src/napcat.json b/src/napcat.json deleted file mode 100644 index 9412e77a..00000000 --- a/src/napcat.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "fileLog": true, - "consoleLog": true, - "fileLogLevel": "debug", - "consoleLogLevel": "info" -} \ No newline at end of file diff --git a/src/onebot11/action/BaseAction.ts b/src/onebot11/action/BaseAction.ts deleted file mode 100644 index c108fdb7..00000000 --- a/src/onebot11/action/BaseAction.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { ActionName, BaseCheckResult } from './types'; -import { OB11Response } from './OB11Response'; -import { OB11Return } from '../types'; -import { log, logError } from '../../common/utils/log'; -import Ajv, { ErrorObject, ValidateFunction } from 'ajv'; - -class BaseAction { - actionName!: ActionName; - private validate: undefined | ValidateFunction = undefined; - PayloadSchema: any = undefined; - protected async check(payload: PayloadType): Promise { - if (this.PayloadSchema) { - this.validate = new Ajv({ allowUnionTypes: true }).compile(this.PayloadSchema); - } - if (this.validate && !this.validate(payload)) { - const errors = this.validate.errors as ErrorObject[]; - const errorMessages: string[] = errors.map((e) => { - return `Key: ${e.instancePath.split('/').slice(1).join('.')}, Message: ${e.message}`; - }); - return { - valid: false, - message: errorMessages.join('\n') as string || '未知错误' - }; - } - return { - valid: true - }; - } - - public async handle(payload: PayloadType): Promise> { - const result = await this.check(payload); - if (!result.valid) { - return OB11Response.error(result.message, 400); - } - try { - const resData = await this._handle(payload); - return OB11Response.ok(resData); - } catch (e: any) { - logError('发生错误', e); - return OB11Response.error(e?.toString() || e?.stack?.toString() || '未知错误,可能操作超时', 200); - } - } - - public async websocketHandle(payload: PayloadType, echo: any): Promise> { - const result = await this.check(payload); - if (!result.valid) { - return OB11Response.error(result.message, 1400); - } - try { - const resData = await this._handle(payload); - return OB11Response.ok(resData, echo); - } catch (e: any) { - logError('发生错误', e); - return OB11Response.error(e.stack?.toString() || e.toString(), 1200, echo); - } - } - - protected async _handle(payload: PayloadType): Promise { - throw `pleas override ${this.actionName} _handle`; - } -} - -export default BaseAction; diff --git a/src/onebot11/action/OB11Response.ts b/src/onebot11/action/OB11Response.ts deleted file mode 100644 index ddc9d72b..00000000 --- a/src/onebot11/action/OB11Response.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { OB11Return } from '../types'; - -import { isNull } from '../../common/utils/helper'; - -export class OB11Response { - static res(data: T, status: string, retcode: number, message: string = ''): OB11Return { - return { - status: status, - retcode: retcode, - data: data, - message: message, - wording: message, - echo: null - }; - } - - static ok(data: T, echo: any = null) { - const res = OB11Response.res(data, 'ok', 0); - if (!isNull(echo)) { - res.echo = echo; - } - return res; - } - - static error(err: string, retcode: number, echo: any = null) { - const res = OB11Response.res(null, 'failed', retcode, err); - if (!isNull(echo)) { - res.echo = echo; - } - return res; - } -} diff --git a/src/onebot11/action/extends/Config.ts b/src/onebot11/action/extends/Config.ts deleted file mode 100644 index a847ae27..00000000 --- a/src/onebot11/action/extends/Config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import BaseAction from '../BaseAction'; -import { OB11Config, ob11Config } from '@/onebot11/config'; -import { ActionName } from '../types'; - - -export class GetConfigAction extends BaseAction { - actionName = ActionName.GetConfig; - - protected async _handle(payload: null): Promise { - return ob11Config; - } -} - -export class SetConfigAction extends BaseAction { - actionName = ActionName.SetConfig; - - protected async _handle(payload: OB11Config): Promise { - ob11Config.save(payload, true); - } -} diff --git a/src/onebot11/action/extends/CreateCollection.ts b/src/onebot11/action/extends/CreateCollection.ts deleted file mode 100644 index df4245a6..00000000 --- a/src/onebot11/action/extends/CreateCollection.ts +++ /dev/null @@ -1,26 +0,0 @@ - -import { NTQQCollectionApi } from '@/core/apis/collection'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { selfInfo } from '@/core/data'; - -const SchemaData = { - type: 'object', - properties: { - rawData: { type: 'string' }, - brief: { type: 'string' } - }, - required: ['brief', 'rawData'], -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class CreateCollection extends BaseAction { - actionName = ActionName.CreateCollection; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - return await NTQQCollectionApi.createCollection(selfInfo.uin, selfInfo.uid, selfInfo.nick, payload.brief, payload.rawData); - } -} diff --git a/src/onebot11/action/extends/Debug.ts b/src/onebot11/action/extends/Debug.ts deleted file mode 100644 index 6f73ae5d..00000000 --- a/src/onebot11/action/extends/Debug.ts +++ /dev/null @@ -1,43 +0,0 @@ -import BaseAction from '../BaseAction'; -// import * as ntqqApi from "../../../ntqqapi/api"; -import { - NTQQMsgApi, - NTQQFriendApi, - NTQQGroupApi, - NTQQUserApi, - NTQQFileApi, - // NTQQFileCacheApi, -} from '@/core'; -import { ActionName } from '../types'; -import { log, logDebug } from '@/common/utils/log'; - -interface Payload { - method: string, - args: any[], -} - -export default class Debug extends BaseAction { - actionName = ActionName.Debug; - - protected async _handle(payload: Payload): Promise { - //logDebug('debug call ntqq api', payload); - const ntqqApi = [NTQQMsgApi, NTQQFriendApi, NTQQGroupApi, NTQQUserApi, NTQQFileApi, - // NTQQFileCacheApi, - ]; - for (const ntqqApiClass of ntqqApi) { - // logDebug('ntqqApiClass', ntqqApiClass); - const method = (ntqqApiClass)[payload.method]; - if (method) { - const result = method(...payload.args); - if (method.constructor.name === 'AsyncFunction') { - return await result; - } - return result; - } - } - throw `${payload.method}方法 不存在`; - - // const info = await NTQQApi.getUserDetailInfo(friends[0].uid); - // return info - } -} diff --git a/src/onebot11/action/extends/FetchCustomFace.ts b/src/onebot11/action/extends/FetchCustomFace.ts deleted file mode 100644 index dee0cc08..00000000 --- a/src/onebot11/action/extends/FetchCustomFace.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQMsgApi } from '@/core/apis'; -const SchemaData = { - type: 'object', - properties: { - count: { type: 'number' }, - } -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class FetchCustomFace extends BaseAction { - actionName = ActionName.FetchCustomFace; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - //48 可能正好是QQ需要的一个页面的数量 Tagged Mlikiowa - const ret = await NTQQMsgApi.fetchFavEmojiList(payload.count || 48); - return ret.emojiInfoList.map(e => e.url); - } -} diff --git a/src/onebot11/action/extends/FetchEmojioLike.ts b/src/onebot11/action/extends/FetchEmojioLike.ts deleted file mode 100644 index baf43dc4..00000000 --- a/src/onebot11/action/extends/FetchEmojioLike.ts +++ /dev/null @@ -1,32 +0,0 @@ -//getMsgEmojiLikesList -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQMsgApi } from '@/core/apis'; -import { MessageUnique } from '@/common/utils/MessageUnique'; -const SchemaData = { - type: 'object', - properties: { - user_id: { type: 'string' }, - group_id: { type: 'string' }, - emojiId: { type: 'string' }, - emojiType: { type: 'string' }, - message_id: { type: ['string', 'number'] }, - count: { type: 'number' } - }, - required: ['emojiId', 'emojiType', 'message_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class FetchEmojioLike extends BaseAction { - actionName = ActionName.FetchEmojioLike; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); - if(!msgIdPeer) throw new Error('消息不存在'); - const msg = (await NTQQMsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0]; - const ret = await NTQQMsgApi.getMsgEmojiLikesList(msgIdPeer.Peer,msg.msgSeq,payload.emojiId,payload.emojiType,payload.count); - return ret; - } -} diff --git a/src/onebot11/action/extends/GetCollectionList.ts b/src/onebot11/action/extends/GetCollectionList.ts deleted file mode 100644 index b768d555..00000000 --- a/src/onebot11/action/extends/GetCollectionList.ts +++ /dev/null @@ -1,26 +0,0 @@ - -import { NTQQCollectionApi } from '@/core/apis/collection'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { selfInfo } from '@/core/data'; - -const SchemaData = { - type: 'object', - properties: { - category: { type: 'number' }, - count: { type: 'number' } - }, - required: ['category', 'count'], -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class GetCollectionList extends BaseAction { - actionName = ActionName.GetCollectionList; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - return await NTQQCollectionApi.getAllCollection(payload.category, payload.count); - } -} diff --git a/src/onebot11/action/extends/GetFriendWithCategory.ts b/src/onebot11/action/extends/GetFriendWithCategory.ts deleted file mode 100644 index 9f3dae9c..00000000 --- a/src/onebot11/action/extends/GetFriendWithCategory.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { BuddyCategoryType } from '@/core/entities/'; -import { NTQQFriendApi } from '@/core'; -import { OB11Constructor } from '@/onebot11/constructor'; - -export class GetFriendWithCategory extends BaseAction { - actionName = ActionName.GetFriendsWithCategory; - - protected async _handle(payload: void) { - if (requireMinNTQQBuild('26702')) { - //全新逻辑 - return OB11Constructor.friendsV2(await NTQQFriendApi.getBuddyV2ExWithCate(true)); - } else { - throw new Error('this ntqq version not support, must be 26702 or later'); - } - } -} diff --git a/src/onebot11/action/extends/GetGroupAddRequest.ts b/src/onebot11/action/extends/GetGroupAddRequest.ts deleted file mode 100644 index 1d6ebe08..00000000 --- a/src/onebot11/action/extends/GetGroupAddRequest.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { GroupNotify, GroupNotifyStatus } from '@/core/entities'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis/user'; -import { NTQQGroupApi } from '@/core/apis/group'; - -interface OB11GroupRequestNotify { - group_id: number, - user_id: number, - flag: string -} - -export default class GetGroupAddRequest extends BaseAction { - actionName = ActionName.GetGroupIgnoreAddRequest; - - protected async _handle(payload: null): Promise { - const data = await NTQQGroupApi.getGroupIgnoreNotifies(); - // log(data); - // const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE); - // const returnData: OB11GroupRequestNotify[] = []; - // for (const notify of notifies) { - // const uin = || (await NTQQUserApi.getUserDetailInfo(notify.user1.uid))?.uin; - // returnData.push({ - // group_id: parseInt(notify.group.groupCode), - // user_id: parseInt(uin), - // flag: notify.seq - // }); - // } - return null; - } -} diff --git a/src/onebot11/action/extends/GetProfileLike.ts b/src/onebot11/action/extends/GetProfileLike.ts deleted file mode 100644 index 80690adc..00000000 --- a/src/onebot11/action/extends/GetProfileLike.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { selfInfo } from '@/core/data'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis'; - -export class GetProfileLike extends BaseAction { - actionName = ActionName.GetProfileLike; - protected async _handle(payload: void) { - const ret = await NTQQUserApi.getProfileLike(selfInfo.uid); - const listdata: any[] = ret.info.userLikeInfos[0].favoriteInfo.userInfos; - for (let i = 0; i < listdata.length; i++) { - listdata[i].uin = parseInt((await NTQQUserApi.getUinByUid(listdata[i].uid)) || ''); - } - return listdata; - } -} diff --git a/src/onebot11/action/extends/GetRobotUinRange.ts b/src/onebot11/action/extends/GetRobotUinRange.ts deleted file mode 100644 index d5b85aba..00000000 --- a/src/onebot11/action/extends/GetRobotUinRange.ts +++ /dev/null @@ -1,11 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis'; -export class GetRobotUinRange extends BaseAction> { - actionName = ActionName.GetRobotUinRange; - - protected async _handle(payload: void) { - // console.log(await NTQQUserApi.getRobotUinRange()); - return await NTQQUserApi.getRobotUinRange(); - } -} diff --git a/src/onebot11/action/extends/OCRImage.ts b/src/onebot11/action/extends/OCRImage.ts deleted file mode 100644 index 8128fe4e..00000000 --- a/src/onebot11/action/extends/OCRImage.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { DeviceList } from '@/onebot11/main'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { checkFileReceived, uri2local } from '@/common/utils/file'; -import { NTQQSystemApi } from '@/core'; -import fs from 'fs'; - -const SchemaData = { - type: 'object', - properties: { - image: { type: 'string' }, - }, - required: ['image'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class OCRImage extends BaseAction { - actionName = ActionName.OCRImage; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const { path, isLocal, errMsg,success } = (await uri2local(payload.image)); - if (!success) { - throw `OCR ${payload.image}失败,image字段可能格式不正确`; - } - if (path) { - await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断 - const ret = await NTQQSystemApi.ORCImage(path); - if (!isLocal) { - fs.unlink(path, () => { }); - } - if (!ret) { - throw `OCR ${payload.file}失败`; - } - return ret.result; - } - if (!isLocal) { - fs.unlink(path, () => { }); - } - throw `OCR ${payload.file}失败,文件可能不存在`; - } -} -export class IOCRImage extends OCRImage { - actionName = ActionName.IOCRImage; -} diff --git a/src/onebot11/action/extends/SetGroupHeader.ts b/src/onebot11/action/extends/SetGroupHeader.ts deleted file mode 100644 index 1998301b..00000000 --- a/src/onebot11/action/extends/SetGroupHeader.ts +++ /dev/null @@ -1,57 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName, BaseCheckResult } from '../types'; -import * as fs from 'node:fs'; -import { NTQQUserApi } from '@/core/apis/user'; -import { checkFileReceived, uri2local } from '@/common/utils/file'; -import { NTQQGroupApi } from '@/core'; -// import { log } from "../../../common/utils"; - -interface Payload { - file: string, - groupCode: string -} - -export default class SetGroupHeader extends BaseAction { - actionName = ActionName.SetGroupHeader; - // 用不着复杂检测 - protected async check(payload: Payload): Promise { - if (!payload.file || typeof payload.file != 'string' || !payload.groupCode || typeof payload.groupCode != 'string') { - return { - valid: false, - message: 'file和groupCode字段不能为空或者类型错误', - }; - } - return { - valid: true, - }; - } - protected async _handle(payload: Payload): Promise { - const { path, isLocal, errMsg,success } = (await uri2local(payload.file)); - if (!success) { - throw `头像${payload.file}设置失败,file字段可能格式不正确`; - } - if (path) { - await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断 - const ret = await NTQQGroupApi.setGroupAvatar(payload.groupCode,path); - if (!isLocal) { - fs.unlink(path, () => { }); - } - if (!ret) { - throw `头像${payload.file}设置失败,api无返回`; - } - // log(`头像设置返回:${JSON.stringify(ret)}`) - // if (ret['result'] == 1004022) { - // throw `头像${payload.file}设置失败,文件可能不是图片格式`; - // } else if (ret['result'] != 0) { - // throw `头像${payload.file}设置失败,未知的错误,${ret['result']}:${ret['errMsg']}`; - // } - return ret; - } else { - if (!isLocal) { - fs.unlink(path, () => { }); - } - throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`; - } - return null; - } -} diff --git a/src/onebot11/action/extends/SetLongNick.ts b/src/onebot11/action/extends/SetLongNick.ts deleted file mode 100644 index 2f1f8c5d..00000000 --- a/src/onebot11/action/extends/SetLongNick.ts +++ /dev/null @@ -1,24 +0,0 @@ - -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - longNick: { type: 'string' }, - }, - required: [ 'longNick'], -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class SetLongNick extends BaseAction { - actionName = ActionName.SetLongNick; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const ret = await NTQQUserApi.setLongNick(payload.longNick); - return ret; - } -} diff --git a/src/onebot11/action/extends/SetOnlineStatus.ts b/src/onebot11/action/extends/SetOnlineStatus.ts deleted file mode 100644 index c06a2292..00000000 --- a/src/onebot11/action/extends/SetOnlineStatus.ts +++ /dev/null @@ -1,35 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName, BaseCheckResult } from '../types'; -import { NTQQUserApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -// 设置在线状态 - -const SchemaData = { - type: 'object', - properties: { - status: { type: 'number' }, - extStatus: { type: 'number' }, - batteryStatus: { type: 'number' } - }, - required: ['status', 'extStatus', 'batteryStatus'], -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class SetOnlineStatus extends BaseAction { - actionName = ActionName.SetOnlineStatus; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - // 可设置状态 - // { status: 10, extStatus: 1027, batteryStatus: 0 } - // { status: 30, extStatus: 0, batteryStatus: 0 } - // { status: 50, extStatus: 0, batteryStatus: 0 } - // { status: 60, extStatus: 0, batteryStatus: 0 } - // { status: 70, extStatus: 0, batteryStatus: 0 } - const ret = await NTQQUserApi.setSelfOnlineStatus(payload.status, payload.extStatus, payload.batteryStatus); - if (ret.result !== 0) { - throw new Error('设置在线状态失败'); - } - return null; - } -} diff --git a/src/onebot11/action/extends/SetQQAvatar.ts b/src/onebot11/action/extends/SetQQAvatar.ts deleted file mode 100644 index f8006344..00000000 --- a/src/onebot11/action/extends/SetQQAvatar.ts +++ /dev/null @@ -1,54 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName, BaseCheckResult } from '../types'; -import * as fs from 'node:fs'; -import { NTQQUserApi } from '@/core/apis/user'; -import { checkFileReceived, uri2local } from '@/common/utils/file'; -// import { log } from "../../../common/utils"; - -interface Payload { - file: string -} - -export default class SetAvatar extends BaseAction { - actionName = ActionName.SetQQAvatar; - // 用不着复杂检测 - protected async check(payload: Payload): Promise { - if (!payload.file || typeof payload.file != 'string') { - return { - valid: false, - message: 'file字段不能为空或者类型错误', - }; - } - return { - valid: true, - }; - } - protected async _handle(payload: Payload): Promise { - const { path, isLocal, errMsg,success } = (await uri2local(payload.file)); - if (!success) { - throw `头像${payload.file}设置失败,file字段可能格式不正确`; - } - if (path) { - await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断 - const ret = await NTQQUserApi.setQQAvatar(path); - if (!isLocal) { - fs.unlink(path, () => { }); - } - if (!ret) { - throw `头像${payload.file}设置失败,api无返回`; - } - // log(`头像设置返回:${JSON.stringify(ret)}`) - if (ret['result'] == 1004022) { - throw `头像${payload.file}设置失败,文件可能不是图片格式`; - } else if (ret['result'] != 0) { - throw `头像${payload.file}设置失败,未知的错误,${ret['result']}:${ret['errMsg']}`; - } - } else { - if (!isLocal) { - fs.unlink(path, () => { }); - } - throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`; - } - return null; - } -} diff --git a/src/onebot11/action/extends/SetSelfProfile.ts b/src/onebot11/action/extends/SetSelfProfile.ts deleted file mode 100644 index 5c85e9eb..00000000 --- a/src/onebot11/action/extends/SetSelfProfile.ts +++ /dev/null @@ -1,32 +0,0 @@ - -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - nick: { type: 'string' }, - longNick: { type: 'string' }, - sex: { type: 'number' }//传Sex值?建议传0 - }, - required: ['nick', 'longNick', 'sex'], -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class SetSelfProfile extends BaseAction { - actionName = ActionName.SetSelfProfile; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const ret = await NTQQUserApi.modifySelfProfile({ - nick: payload.nick, - longNick: payload.longNick, - sex: payload.sex, - birthday: { birthday_year: '', birthday_month: '', birthday_day: '' }, - location: undefined - }); - return ret; - } -} diff --git a/src/onebot11/action/extends/TestApi01.ts b/src/onebot11/action/extends/TestApi01.ts deleted file mode 100644 index 566d63d2..00000000 --- a/src/onebot11/action/extends/TestApi01.ts +++ /dev/null @@ -1,28 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName, BaseCheckResult } from '../types'; -import { napCatCore, NTQQGroupApi } from '@/core'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - cmd: { type: 'string' }, - param: { type: 'string' } - }, - required: ['cmd', 'param'], -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class TestApi01 extends BaseAction { - actionName = ActionName.TestApi01; - // 用不着复杂检测 - protected async check(payload: Payload): Promise { - return { - valid: true, - }; - } - protected async _handle(payload: Payload): Promise { - return await napCatCore.session.getMsgService().sendSsoCmdReqByContend(payload.cmd, payload.param); - } -} diff --git a/src/onebot11/action/extends/TranslateEnWordToZn.ts b/src/onebot11/action/extends/TranslateEnWordToZn.ts deleted file mode 100644 index 8088ab6d..00000000 --- a/src/onebot11/action/extends/TranslateEnWordToZn.ts +++ /dev/null @@ -1,32 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName, BaseCheckResult } from '../types'; -import { NTQQSystemApi, NTQQUserApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import Ajv from 'ajv'; -// 设置在线状态 - -const SchemaData = { - type: 'object', - properties: { - words: { - type: 'array', - items: { type: 'string' } - } - }, - required: ['words'], -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class TranslateEnWordToZn extends BaseAction | null> { - actionName = ActionName.TranslateEnWordToZn; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - - const ret = await NTQQSystemApi.translateEnWordToZn(payload.words); - if (ret.result !== 0) { - throw new Error('翻译失败'); - } - return ret.words; - } -} diff --git a/src/onebot11/action/extends/sharePeer.ts b/src/onebot11/action/extends/sharePeer.ts deleted file mode 100644 index abb63bff..00000000 --- a/src/onebot11/action/extends/sharePeer.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { NTQQGroupApi, NTQQUserApi } from '@/core'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { BuddyCategoryType } from '@/core/entities/'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - user_id: { type: 'string' }, - group_id: { type: 'string' }, - phoneNumber: { type: 'string' }, - }, -} as const satisfies JSONSchema; - -type Payload = FromSchema; - - -export class sharePeer extends BaseAction { - actionName = ActionName.SharePeer; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - if (payload.group_id) { - return await NTQQGroupApi.getGroupRecommendContactArkJson(payload.group_id); - } else if (payload.user_id) { - return await NTQQUserApi.getBuddyRecommendContactArkJson(payload.user_id, payload.phoneNumber || ''); - } - } -} -const SchemaDataGroupEx = { - type: 'object', - properties: { - group_id: { type: 'string' }, - }, - required: ['group_id'] -} as const satisfies JSONSchema; - -type PayloadGroupEx = FromSchema; -export class shareGroupEx extends BaseAction { - actionName = ActionName.ShareGroupEx; - PayloadSchema = SchemaDataGroupEx; - protected async _handle(payload: PayloadGroupEx) { - return await NTQQGroupApi.getArkJsonGroupShare(payload.group_id); - } -} \ No newline at end of file diff --git a/src/onebot11/action/file/DelGroupFile.ts b/src/onebot11/action/file/DelGroupFile.ts deleted file mode 100644 index 498cfe13..00000000 --- a/src/onebot11/action/file/DelGroupFile.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['string', 'number'] }, - file_id: { type: 'string' }, - }, - required: ['group_id', 'file_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class DelGroupFile extends BaseAction { - actionName = ActionName.DelGroupFile; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - return await NTQQGroupApi.DelGroupFile(payload.group_id.toString(), [payload.file_id]); - } -} diff --git a/src/onebot11/action/file/DelGroupFileFolder.ts b/src/onebot11/action/file/DelGroupFileFolder.ts deleted file mode 100644 index 31907558..00000000 --- a/src/onebot11/action/file/DelGroupFileFolder.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['string', 'number'] }, - folder_id: { type: 'string' }, - }, - required: ['group_id', 'folder_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class DelGroupFileFolder extends BaseAction { - actionName = ActionName.DelGroupFileFolder; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - return (await NTQQGroupApi.DelGroupFileFolder(payload.group_id.toString(), payload.folder_id)).groupFileCommonResult; - } -} diff --git a/src/onebot11/action/file/GetFile.ts b/src/onebot11/action/file/GetFile.ts deleted file mode 100644 index 85672682..00000000 --- a/src/onebot11/action/file/GetFile.ts +++ /dev/null @@ -1,227 +0,0 @@ -import BaseAction from '../BaseAction'; -import fs from 'fs/promises'; -import { ob11Config } from '@/onebot11/config'; -import { UUIDConverter } from '@/common/utils/helper'; -import { ActionName, BaseCheckResult } from '../types'; -import { ChatType, ElementType, FileElement, Peer, RawMessage, VideoElement } from '@/core/entities'; -import { NTQQFileApi, NTQQFriendApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { getGroup } from '@/core/data'; - -export interface GetFilePayload { - file: string; // 文件名或者fileUuid -} - -export interface GetFileResponse { - file?: string; // path - url?: string; - file_size?: string; - file_name?: string; - base64?: string; -} -const GetFileBase_PayloadSchema = { - type: 'object', - properties: { - file: { type: 'string' } - }, - required: ['file'] -} as const satisfies JSONSchema; - -export class GetFileBase extends BaseAction { - PayloadSchema: any = GetFileBase_PayloadSchema; - private getElement(msg: RawMessage): { id: string, element: VideoElement | FileElement } { - let element = msg.elements.find(e => e.fileElement); - if (!element) { - element = msg.elements.find(e => e.videoElement); - if (element) { - return { id: element.elementId, element: element.videoElement }; - } else { - throw new Error('找不到文件'); - } - } - return { id: element.elementId, element: element.fileElement }; - } - protected async _handle(payload: GetFilePayload): Promise { - const { enableLocalFile2Url } = ob11Config; - let UuidData: { - high: string; - low: string; - } | undefined; - try { - UuidData = UUIDConverter.decode(payload.file); - if (UuidData) { - const peerUin = UuidData.high; - const msgId = UuidData.low; - const isGroup = await getGroup(peerUin); - let peer: Peer | undefined; - //识别Peer - if (isGroup) { - peer = { chatType: ChatType.group, peerUid: peerUin }; - } - const PeerUid = await NTQQUserApi.getUidByUin(peerUin); - if (PeerUid) { - const isBuddy = await NTQQFriendApi.isBuddy(PeerUid); - if (isBuddy) { - peer = { chatType: ChatType.friend, peerUid: PeerUid }; - } else { - peer = { chatType: ChatType.temp, peerUid: PeerUid }; - } - } - if (!peer) { - throw new Error('chattype not support'); - } - const msgList = await NTQQMsgApi.getMsgsByMsgId(peer, [msgId]); - if (msgList.msgList.length == 0) { - throw new Error('msg not found'); - } - const msg = msgList.msgList[0]; - const findEle = msg.elements.find(e => e.elementType == ElementType.VIDEO || e.elementType == ElementType.FILE || e.elementType == ElementType.PTT); - if (!findEle) { - throw new Error('element not found'); - } - const downloadPath = await NTQQFileApi.downloadMedia(msgId, msg.chatType, msg.peerUid, findEle.elementId, '', ''); - const fileSize = findEle?.videoElement?.fileSize || findEle?.fileElement?.fileSize || findEle?.pttElement?.fileSize || '0'; - const fileName = findEle?.videoElement?.fileName || findEle?.fileElement?.fileName || findEle?.pttElement?.fileName || ''; - const res: GetFileResponse = { - file: downloadPath, - url: downloadPath, - file_size: fileSize, - file_name: fileName - }; - if (enableLocalFile2Url) { - try { - res.base64 = await fs.readFile(downloadPath, 'base64'); - } catch (e) { - throw new Error('文件下载失败. ' + e); - } - } - //不手动删除?文件持久化了 - return res; - } - } catch { - - } - - const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems; - if (NTSearchNameResult.length !== 0) { - const MsgId = NTSearchNameResult[0].msgId; - let peer: Peer | undefined = undefined; - if (NTSearchNameResult[0].chatType == ChatType.group) { - peer = { chatType: ChatType.group, peerUid: NTSearchNameResult[0].groupChatInfo[0].groupCode }; - } - if (!peer) { - throw new Error('chattype not support'); - } - const msgList: RawMessage[] = (await NTQQMsgApi.getMsgsByMsgId(peer, [MsgId]))?.msgList; - if (!msgList || msgList.length == 0) { - throw new Error('msg not found'); - } - const msg = msgList[0]; - const file = msg.elements.filter(e => e.elementType == NTSearchNameResult[0].elemType); - if (file.length == 0) { - throw new Error('file not found'); - } - const downloadPath = await NTQQFileApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid, file[0].elementId, '', ''); - const res: GetFileResponse = { - file: downloadPath, - url: downloadPath, - file_size: NTSearchNameResult[0].fileSize.toString(), - file_name: NTSearchNameResult[0].fileName - }; - if (enableLocalFile2Url) { - try { - res.base64 = await fs.readFile(downloadPath, 'base64'); - } catch (e) { - throw new Error('文件下载失败. ' + e); - } - } - //不手动删除?文件持久化了 - return res; - } - throw new Error('file not found'); - // let cache = await dbUtil.getFileCacheByName(payload.file); - // if (!cache) { - // cache = await dbUtil.getFileCacheByUuid(payload.file); - // } - // if (!cache) { - // throw new Error('file not found'); - // } - // const { enableLocalFile2Url } = ob11Config; - // try { - // await fs.access(cache.path, fs.constants.F_OK); - // } catch (e) { - // logDebug('local file not found, start download...'); - // // if (cache.url) { - // // const downloadResult = await uri2local(cache.url); - // // if (downloadResult.success) { - // // cache.path = downloadResult.path; - // // dbUtil.updateFileCache(cache).then(); - // // } else { - // // throw new Error('file download failed. ' + downloadResult.errMsg); - // // } - // // } else { - // // // 没有url的可能是私聊文件或者群文件,需要自己下载 - // // log('需要调用 NTQQ 下载文件api'); - // let peer = MessageUnique.getPeerByMsgId(cache.msgId); - // let msg = await NTQQMsgApi.getMsgsByMsgId(peer?.Peer!,cache.msgId); - // // log('文件 msg', msg); - // if (msg) { - // // 构建下载函数 - // const downloadPath = await NTQQFileApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid, - // cache.elementId, '', ''); - // // await sleep(1000); - - // // log('download result', downloadPath); - // let peer = MessageUnique.getPeerByMsgId(cache.msgId); - // msg = await NTQQMsgApi.getMsgsByMsgId(peer?.Peer!,cache.msgId); - // // log('下载完成后的msg', msg); - // cache.path = downloadPath!; - // dbUtil.updateFileCache(cache).then(); - // // log('下载完成后的msg', msg); - // // } - // } - - // } - // // log('file found', cache); - // const res: GetFileResponse = { - // file: cache.path, - // url: cache.url, - // file_size: cache.size.toString(), - // file_name: cache.name - // }; - // if (enableLocalFile2Url) { - // if (!cache.url) { - // try { - // res.base64 = await fs.readFile(cache.path, 'base64'); - // } catch (e) { - // throw new Error('文件下载失败. ' + e); - // } - // } - // } - //return res; - } -} - -const GetFile_PayloadSchema = { - type: 'object', - properties: { - file_id: { type: 'string' }, - file: { type: 'string' } - }, - required: ['file_id'] -} as const satisfies JSONSchema; - -type GetFile_Payload_Internal = FromSchema; - -interface GetFile_Payload extends GetFile_Payload_Internal { - file: string -} - -export default class GetFile extends GetFileBase { - actionName = ActionName.GetFile; - PayloadSchema = GetFile_PayloadSchema; - protected async _handle(payload: GetFile_Payload): Promise { - payload.file = payload.file_id; - return super._handle(payload); - } -} diff --git a/src/onebot11/action/file/GetGroupFileCount.ts b/src/onebot11/action/file/GetGroupFileCount.ts deleted file mode 100644 index 2b84a2b6..00000000 --- a/src/onebot11/action/file/GetGroupFileCount.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi, NTQQUserApi } from '@/core/apis'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['string', 'number'] }, - }, - required: ['group_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class GetGroupFileCount extends BaseAction { - actionName = ActionName.GetGroupFileCount; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const ret = await NTQQGroupApi.GetGroupFileCount([payload.group_id?.toString()]); - return { count: ret.groupFileCounts[0] }; - } -} diff --git a/src/onebot11/action/file/GetGroupFileList.ts b/src/onebot11/action/file/GetGroupFileList.ts deleted file mode 100644 index 0d5a48e7..00000000 --- a/src/onebot11/action/file/GetGroupFileList.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['string', 'number'] }, - start_index: { type: 'number' }, - file_count: { type: 'number' }, - }, - required: ['group_id', 'start_index', 'file_count'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class GetGroupFileList extends BaseAction }> { - actionName = ActionName.GetGroupFileList; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const ret = await NTQQMsgApi.getGroupFileList(payload.group_id.toString(), { - sortType: 1, - fileCount: payload.file_count, - startIndex: payload.start_index, - sortOrder: 2, - showOnlinedocFolder: 0 - }).catch((e) => { return []; }); - return { FileList: ret }; - } -} diff --git a/src/onebot11/action/file/GetImage.ts b/src/onebot11/action/file/GetImage.ts deleted file mode 100644 index 457ccb29..00000000 --- a/src/onebot11/action/file/GetImage.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { GetFileBase } from './GetFile'; -import { ActionName } from '../types'; - - -export default class GetImage extends GetFileBase { - actionName = ActionName.GetImage; -} \ No newline at end of file diff --git a/src/onebot11/action/file/GetRecord.ts b/src/onebot11/action/file/GetRecord.ts deleted file mode 100644 index 25435974..00000000 --- a/src/onebot11/action/file/GetRecord.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { GetFileBase, GetFilePayload, GetFileResponse } from './GetFile'; -import { ActionName } from '../types'; - -interface Payload extends GetFilePayload { - out_format: 'mp3' | 'amr' | 'wma' | 'm4a' | 'spx' | 'ogg' | 'wav' | 'flac' -} - -export default class GetRecord extends GetFileBase { - actionName = ActionName.GetRecord; - - protected async _handle(payload: Payload): Promise { - const res = super._handle(payload); - return res; - } -} \ No newline at end of file diff --git a/src/onebot11/action/file/SetGroupFileFolder.ts b/src/onebot11/action/file/SetGroupFileFolder.ts deleted file mode 100644 index 856a2ba5..00000000 --- a/src/onebot11/action/file/SetGroupFileFolder.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['string', 'number'] }, - folder_name: { type: 'string' }, - }, - required: ['group_id', 'folder_name'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class SetGroupFileFolder extends BaseAction { - actionName = ActionName.SetGroupFileFolder; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - return (await NTQQGroupApi.CreatGroupFileFolder(payload.group_id.toString(), payload.folder_name)).resultWithGroupItem; - } -} diff --git a/src/onebot11/action/go-cqhttp/DownloadFile.ts b/src/onebot11/action/go-cqhttp/DownloadFile.ts deleted file mode 100644 index 19fc9446..00000000 --- a/src/onebot11/action/go-cqhttp/DownloadFile.ts +++ /dev/null @@ -1,82 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import fs from 'fs'; -import { join as joinPath } from 'node:path'; -import { calculateFileMD5, getTempDir, httpDownload } from '@/common/utils/file'; -import { randomUUID } from 'crypto'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -interface FileResponse { - file: string; -} -const SchemaData = { - type: 'object', - properties: { - thread_count: { type: 'number' }, - url: { type: 'string' }, - base64: { type: 'string' }, - name: { type: 'string' }, - headers: { - type: ['string', 'array'], - items: { - type: 'string' - } - } - }, -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class GoCQHTTPDownloadFile extends BaseAction { - actionName = ActionName.GoCQHTTP_DownloadFile; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const isRandomName = !payload.name; - const name = payload.name || randomUUID(); - const filePath = joinPath(getTempDir(), name); - - if (payload.base64) { - fs.writeFileSync(filePath, payload.base64, 'base64'); - } else if (payload.url) { - const headers = this.getHeaders(payload.headers); - const buffer = await httpDownload({ url: payload.url, headers: headers }); - fs.writeFileSync(filePath, Buffer.from(buffer), 'binary'); - } else { - throw new Error('不存在任何文件, 无法下载'); - } - if (fs.existsSync(filePath)) { - - if (isRandomName) { - // 默认实现要名称未填写时文件名为文件 md5 - const md5 = await calculateFileMD5(filePath); - const newPath = joinPath(getTempDir(), md5); - fs.renameSync(filePath, newPath); - return { file: newPath }; - } - return { file: filePath }; - } else { - throw new Error('文件写入失败, 检查权限'); - } - } - - getHeaders(headersIn?: string | string[]): Record { - const headers: Record = {}; - if (typeof headersIn == 'string') { - headersIn = headersIn.split('[\\r\\n]'); - } - if (Array.isArray(headersIn)) { - for (const headerItem of headersIn) { - const spilt = headerItem.indexOf('='); - if (spilt < 0) { - headers[headerItem] = ''; - } else { - const key = headerItem.substring(0, spilt); - headers[key] = headerItem.substring(0, spilt + 1); - } - } - } - if (!headers['Content-Type']) { - headers['Content-Type'] = 'application/octet-stream'; - } - return headers; - } -} diff --git a/src/onebot11/action/go-cqhttp/GetForwardMsg.ts b/src/onebot11/action/go-cqhttp/GetForwardMsg.ts deleted file mode 100644 index 375aefd1..00000000 --- a/src/onebot11/action/go-cqhttp/GetForwardMsg.ts +++ /dev/null @@ -1,52 +0,0 @@ -import BaseAction from '../BaseAction'; -import { OB11ForwardMessage, OB11Message, OB11MessageData } from '../../types'; -import { NTQQMsgApi } from '@/core/apis'; -import { OB11Constructor } from '../../constructor'; -import { ActionName, BaseCheckResult } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { MessageUnique } from '@/common/utils/MessageUnique'; - -const SchemaData = { - type: 'object', - properties: { - message_id: { type: 'string' }, - id: { type: 'string' } - }, -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -interface Response { - messages: (OB11Message & { content: OB11MessageData })[]; -} - -export class GoCQHTTPGetForwardMsgAction extends BaseAction { - actionName = ActionName.GoCQHTTP_GetForwardMsg; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const msgId = payload.message_id || payload.id; - if (!msgId) { - throw Error('message_id is required'); - } - const rootMsgId = MessageUnique.getShortIdByMsgId(msgId); - const rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || parseInt(msgId)); - if (!rootMsg) { - throw Error('msg not found'); - } - const data = await NTQQMsgApi.getMultiMsg(rootMsg.Peer, rootMsg.MsgId, rootMsg.MsgId); - if (!data || data.result !== 0) { - throw Error('找不到相关的聊天记录' + data?.errMsg); - } - const msgList = data.msgList; - const messages = await Promise.all(msgList.map(async msg => { - const resMsg = await OB11Constructor.message(msg); - resMsg.message_id = await MessageUnique.createMsg({ guildId:'',chatType:msg.chatType,peerUid:msg.peerUid },msg.msgId)!; - return resMsg; - })); - messages.map(msg => { - (msg).content = msg.message; - delete (msg).message; - }); - return { messages }; - } -} diff --git a/src/onebot11/action/go-cqhttp/GetFriendMsgHistory.ts b/src/onebot11/action/go-cqhttp/GetFriendMsgHistory.ts deleted file mode 100644 index 3ca15764..00000000 --- a/src/onebot11/action/go-cqhttp/GetFriendMsgHistory.ts +++ /dev/null @@ -1,57 +0,0 @@ -import BaseAction from '../BaseAction'; -import { OB11Message, OB11User } from '../../types'; -import { ActionName } from '../types'; -import { ChatType, RawMessage } from '@/core/entities'; -import { NTQQMsgApi } from '@/core/apis/msg'; -import { OB11Constructor } from '../../constructor'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { NTQQFriendApi, NTQQUserApi } from '@/core'; -import { MessageUnique } from '@/common/utils/MessageUnique'; - -interface Response { - messages: OB11Message[]; -} - -const SchemaData = { - type: 'object', - properties: { - user_id: { type: ['number', 'string'] }, - message_seq: { type: 'number' }, - count: { type: 'number' }, - reverseOrder: { type: 'boolean' } - }, - required: ['user_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class GetFriendMsgHistory extends BaseAction { - actionName = ActionName.GetFriendMsgHistory; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - //处理参数 - const uid = await NTQQUserApi.getUidByUin(payload.user_id.toString()); - const MsgCount = payload.count || 20; - const isReverseOrder = payload.reverseOrder || true; - if (!uid) throw `记录${payload.user_id}不存在`; - const friend = await NTQQFriendApi.isBuddy(uid); - const peer = { chatType: friend ? ChatType.friend : ChatType.temp, peerUid: uid }; - - //拉取消息 - let msgList: RawMessage[]; - if (!payload.message_seq || payload.message_seq == 0) { - msgList = (await NTQQMsgApi.getLastestMsgByUids(peer, MsgCount)).msgList; - } else { - const startMsgId = MessageUnique.getMsgIdAndPeerByShortId(payload.message_seq)?.MsgId; - if (!startMsgId) throw `消息${payload.message_seq}不存在`; - msgList = (await NTQQMsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList; - } - if(isReverseOrder) msgList.reverse(); - await Promise.all(msgList.map(async msg => { - msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId); - })); - //转换消息 - const ob11MsgList = await Promise.all(msgList.map(msg => OB11Constructor.message(msg))); - return { 'messages': ob11MsgList }; - } -} diff --git a/src/onebot11/action/go-cqhttp/GetGroupHonorInfo.ts b/src/onebot11/action/go-cqhttp/GetGroupHonorInfo.ts deleted file mode 100644 index 2d84f476..00000000 --- a/src/onebot11/action/go-cqhttp/GetGroupHonorInfo.ts +++ /dev/null @@ -1,26 +0,0 @@ - -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { WebApi, WebHonorType } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - type: { enum: [WebHonorType.ALL, WebHonorType.EMOTION, WebHonorType.LEGEND, WebHonorType.PERFROMER, WebHonorType.STORONGE_NEWBI, WebHonorType.TALKACTIVE] } - }, - required: ['group_id'] -} as const satisfies JSONSchema; -// enum是不是有点抽象 -type Payload = FromSchema; - -export class GetGroupHonorInfo extends BaseAction> { - actionName = ActionName.GetGroupHonorInfo; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - if (!payload.type) { - payload.type = WebHonorType.ALL; - } - return await WebApi.getGroupHonorInfo(payload.group_id.toString(), payload.type); - } -} diff --git a/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts b/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts deleted file mode 100644 index de518621..00000000 --- a/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts +++ /dev/null @@ -1,56 +0,0 @@ -import BaseAction from '../BaseAction'; -import { OB11Message, OB11User } from '../../types'; -import { getGroup, groups } from '@/core/data'; -import { ActionName } from '../types'; -import { ChatType, Peer, RawMessage } from '@/core/entities'; -import { NTQQMsgApi } from '@/core/apis/msg'; -import { OB11Constructor } from '../../constructor'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { MessageUnique } from '@/common/utils/MessageUnique'; -interface Response { - messages: OB11Message[]; -} - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['number', 'string'] }, - message_seq: { type: 'number' }, - count: { type: 'number' }, - reverseOrder: { type: 'boolean' } - }, - required: ['group_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class GoCQHTTPGetGroupMsgHistory extends BaseAction { - actionName = ActionName.GoCQHTTP_GetGroupMsgHistory; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - //处理参数 - const group = await getGroup(payload.group_id.toString()); - const isReverseOrder = payload.reverseOrder || true; - const MsgCount = payload.count || 20; - const peer: Peer = { chatType: ChatType.group, peerUid: payload.group_id.toString() }; - if (!group) throw `群${payload.group_id}不存在`; - - //拉取消息 - let msgList: RawMessage[]; - if (!payload.message_seq || payload.message_seq == 0) { - msgList = (await NTQQMsgApi.getLastestMsgByUids(peer, MsgCount)).msgList; - } else { - const startMsgId = MessageUnique.getMsgIdAndPeerByShortId(payload.message_seq)?.MsgId; - if (!startMsgId) throw `消息${payload.message_seq}不存在`; - msgList = (await NTQQMsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList; - } - if(isReverseOrder) msgList.reverse(); - await Promise.all(msgList.map(async msg => { - msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId); - })); - - //转换消息 - const ob11MsgList = await Promise.all(msgList.map(msg => OB11Constructor.message(msg))); - return { 'messages': ob11MsgList }; - } -} diff --git a/src/onebot11/action/go-cqhttp/GetOnlineClient.ts b/src/onebot11/action/go-cqhttp/GetOnlineClient.ts deleted file mode 100644 index 22937d15..00000000 --- a/src/onebot11/action/go-cqhttp/GetOnlineClient.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { DeviceList } from '@/onebot11/main'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { JSONSchema } from 'json-schema-to-ts'; -import { NTQQSystemApi } from '@/core'; -import { sleep } from '@/common/utils/helper'; - -const SchemaData = { - type: 'object', - properties: { - no_cache: { type: 'boolean' }, - } -} as const satisfies JSONSchema; - -export class GetOnlineClient extends BaseAction> { - actionName = ActionName.GetOnlineClient; - - protected async _handle(payload: void) { - NTQQSystemApi.getOnlineDev(); - await sleep(500); - return DeviceList; - } -} diff --git a/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts b/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts deleted file mode 100644 index b7f1c223..00000000 --- a/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts +++ /dev/null @@ -1,66 +0,0 @@ -import BaseAction from '../BaseAction'; -import { OB11User, OB11UserSex } from '../../types'; -import { OB11Constructor } from '../../constructor'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis/user'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { calcQQLevel } from '@/common/utils/qqlevel'; -import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo'; - -const SchemaData = { - type: 'object', - properties: { - user_id: { type: ['number', 'string'] }, - }, - required: ['user_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class GoCQHTTPGetStrangerInfo extends BaseAction { - actionName = ActionName.GoCQHTTP_GetStrangerInfo; - - protected async _handle(payload: Payload): Promise { - if (!requireMinNTQQBuild('26702')) { - const user_id = payload.user_id.toString(); - const extendData = await NTQQUserApi.getUserDetailInfoByUin(user_id); - const uid = (await NTQQUserApi.getUidByUin(user_id))!; - if (!uid || uid.indexOf('*') != -1) { - const ret = { - ...extendData, - user_id: parseInt(extendData.info.uin) || 0, - nickname: extendData.info.nick, - sex: OB11UserSex.unknown, - age: (extendData.info.birthday_year == 0) ? 0 : new Date().getFullYear() - extendData.info.birthday_year, - qid: extendData.info.qid, - level: extendData.info.qqLevel && calcQQLevel(extendData.info.qqLevel) || 0, - login_days: 0, - uid: '' - }; - return ret; - } - const data = { ...extendData, ...(await NTQQUserApi.getUserDetailInfo(uid)) }; - return OB11Constructor.stranger(data); - } else { - const user_id = payload.user_id.toString(); - const extendData = await NTQQUserApi.getUserDetailInfoByUinV2(user_id); - //console.log(extendData); - const uid = (await NTQQUserApi.getUidByUin(user_id))!; - if (!uid || uid.indexOf('*') != -1) { - const ret = { - ...extendData, - user_id: parseInt(extendData.detail.uin) || 0, - nickname: extendData.detail.simpleInfo.coreInfo.nick, - sex: OB11UserSex.unknown, - age: 0, - level: extendData.detail.commonExt.qqLevel && calcQQLevel(extendData.detail.commonExt.qqLevel) || 0, - login_days: 0, - uid: '' - }; - return ret; - } - const data = { ...extendData, ...(await NTQQUserApi.getUserDetailInfo(uid)) }; - return OB11Constructor.stranger(data); - } - } -} diff --git a/src/onebot11/action/go-cqhttp/QuickAction.ts b/src/onebot11/action/go-cqhttp/QuickAction.ts deleted file mode 100644 index cf1926cc..00000000 --- a/src/onebot11/action/go-cqhttp/QuickAction.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { log } from '@/common/utils/log'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { QuickAction, QuickActionEvent, handleQuickOperation } from '@/onebot11/server/postOB11Event'; - -interface Payload{ - context: QuickActionEvent, - operation: QuickAction -} - -export class GoCQHTTPHandleQuickAction extends BaseAction{ - actionName = ActionName.GoCQHTTP_HandleQuickAction; - protected async _handle(payload: Payload): Promise { - handleQuickOperation(payload.context, payload.operation).then().catch(log); - return null; - } -} \ No newline at end of file diff --git a/src/onebot11/action/go-cqhttp/SendForwardMsg.ts b/src/onebot11/action/go-cqhttp/SendForwardMsg.ts deleted file mode 100644 index fab6d218..00000000 --- a/src/onebot11/action/go-cqhttp/SendForwardMsg.ts +++ /dev/null @@ -1,20 +0,0 @@ -import SendMsg, { normalize } from '../msg/SendMsg'; -import { OB11PostSendMsg } from '../../types'; -import { ActionName } from '../types'; -// 未验证 -export class GoCQHTTPSendForwardMsg extends SendMsg { - actionName = ActionName.GoCQHTTP_SendForwardMsg; - - protected async check(payload: OB11PostSendMsg) { - if (payload.messages) payload.message = normalize(payload.messages); - return super.check(payload); - } -} - -export class GoCQHTTPSendPrivateForwardMsg extends GoCQHTTPSendForwardMsg { - actionName = ActionName.GoCQHTTP_SendPrivateForwardMsg; -} - -export class GoCQHTTPSendGroupForwardMsg extends GoCQHTTPSendForwardMsg { - actionName = ActionName.GoCQHTTP_SendGroupForwardMsg; -} diff --git a/src/onebot11/action/go-cqhttp/SendGroupNotice.ts b/src/onebot11/action/go-cqhttp/SendGroupNotice.ts deleted file mode 100644 index 4be85a83..00000000 --- a/src/onebot11/action/go-cqhttp/SendGroupNotice.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { checkFileReceived, uri2local } from '@/common/utils/file'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi, WebApi } from '@/core/apis'; -import { unlink } from 'node:fs'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['number', 'string'] }, - content: { type: 'string' }, - image: { type: 'string' }, - pinned: { type: 'number' }, - confirmRequired: { type: 'number' } - }, - required: ['group_id', 'content'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class SendGroupNotice extends BaseAction { - actionName = ActionName.GoCQHTTP_SendGroupNotice; - protected async _handle(payload: Payload) { - let UploadImage: { id: string, width: number, height: number } | undefined = undefined; - if (payload.image) { - //公告图逻辑 - const { errMsg, path, isLocal, success } = (await uri2local(payload.image)); - if (!success) { - throw `群公告${payload.image}设置失败,image字段可能格式不正确`; - } - if (!path) { - throw `群公告${payload.image}设置失败,获取资源失败`; - } - await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断 - const ImageUploadResult = await NTQQGroupApi.uploadGroupBulletinPic(payload.group_id.toString(), path); - if (ImageUploadResult.errCode != 0) { - throw `群公告${payload.image}设置失败,图片上传失败`; - } - if (!isLocal) { - unlink(path, () => { }); - } - UploadImage = ImageUploadResult.picInfo; - } - let Notice_Pinned = 0; - let Notice_confirmRequired = 0; - if (!payload.pinned) { - Notice_Pinned = 0; - } - if (!payload.confirmRequired) { - Notice_confirmRequired = 0; - } - const PublishGroupBulletinResult = await NTQQGroupApi.publishGroupBulletin(payload.group_id.toString(), payload.content, UploadImage, Notice_Pinned, Notice_confirmRequired); - - if (PublishGroupBulletinResult.result != 0) { - throw `设置群公告失败,错误信息:${PublishGroupBulletinResult.errMsg}`; - } - // 下面实现扬了 - //await WebApi.setGroupNotice(payload.group_id, payload.content) ; - return null; - } -} diff --git a/src/onebot11/action/go-cqhttp/UploadGroupFile.ts b/src/onebot11/action/go-cqhttp/UploadGroupFile.ts deleted file mode 100644 index d00895db..00000000 --- a/src/onebot11/action/go-cqhttp/UploadGroupFile.ts +++ /dev/null @@ -1,44 +0,0 @@ -import BaseAction from '../BaseAction'; -import { getGroup } from '@/core/data'; -import { ActionName } from '../types'; -import { SendMsgElementConstructor } from '@/core/entities/constructor'; -import { ChatType, SendFileElement } from '@/core/entities'; -import fs from 'fs'; -import { SendMsg, sendMsg } from '@/onebot11/action/msg/SendMsg'; -import { uri2local } from '@/common/utils/file'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['number', 'string'] }, - file: { type: 'string' }, - name: { type: 'string' }, - folder: { type: 'string' }, - folder_id: { type: 'string' }//临时扩展 - }, - required: ['group_id', 'file', 'name'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class GoCQHTTPUploadGroupFile extends BaseAction { - actionName = ActionName.GoCQHTTP_UploadGroupFile; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const group = await getGroup(payload.group_id.toString()); - if (!group) { - throw new Error(`群组${payload.group_id}不存在`); - } - let file = payload.file; - if (fs.existsSync(file)) { - file = `file://${file}`; - } - const downloadResult = await uri2local(file); - if (!downloadResult.success) { - throw new Error(downloadResult.errMsg); - } - const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(downloadResult.path, payload.name, payload.folder_id); - await sendMsg({ chatType: ChatType.group, peerUid: group.groupCode }, [sendFileEle], [], true); - return null; - } -} diff --git a/src/onebot11/action/go-cqhttp/UploadPrivareFile.ts b/src/onebot11/action/go-cqhttp/UploadPrivareFile.ts deleted file mode 100644 index 853ca721..00000000 --- a/src/onebot11/action/go-cqhttp/UploadPrivareFile.ts +++ /dev/null @@ -1,51 +0,0 @@ -import BaseAction from '../BaseAction'; -import { getGroup } from '@/core/data'; -import { ActionName } from '../types'; -import { SendMsgElementConstructor } from '@/core/entities/constructor'; -import { ChatType, Peer, SendFileElement } from '@/core/entities'; -import fs from 'fs'; -import { SendMsg, sendMsg } from '@/onebot11/action/msg/SendMsg'; -import { uri2local } from '@/common/utils/file'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { NTQQFriendApi, NTQQUserApi } from '@/core'; -const SchemaData = { - type: 'object', - properties: { - user_id: { type: ['number', 'string'] }, - file: { type: 'string' }, - name: { type: 'string' } - }, - required: ['user_id', 'file', 'name'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class GoCQHTTPUploadPrivateFile extends BaseAction { - actionName = ActionName.GOCQHTTP_UploadPrivateFile; - PayloadSchema = SchemaData; - async getPeer(payload: Payload): Promise { - if (payload.user_id) { - const peerUid = await NTQQUserApi.getUidByUin(payload.user_id.toString()); - if (!peerUid) { - throw `私聊${payload.user_id}不存在`; - } - const isBuddy = await NTQQFriendApi.isBuddy(peerUid); - return { chatType: isBuddy ? ChatType.friend : ChatType.temp, peerUid }; - } - throw '缺少参数 user_id'; - } - protected async _handle(payload: Payload): Promise { - const peer = await this.getPeer(payload); - let file = payload.file; - if (fs.existsSync(file)) { - file = `file://${file}`; - } - const downloadResult = await uri2local(file); - if (!downloadResult.success) { - throw new Error(downloadResult.errMsg); - } - const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(downloadResult.path, payload.name); - await sendMsg(peer, [sendFileEle], [], true); - return null; - } -} diff --git a/src/onebot11/action/group/DelEssenceMsg.ts b/src/onebot11/action/group/DelEssenceMsg.ts deleted file mode 100644 index 03b422be..00000000 --- a/src/onebot11/action/group/DelEssenceMsg.ts +++ /dev/null @@ -1,31 +0,0 @@ - -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { NTQQGroupApi } from '@/core'; -import { MessageUnique } from '@/common/utils/MessageUnique'; - -const SchemaData = { - type: 'object', - properties: { - message_id: { type: ['number', 'string'] } - }, - required: ['message_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class DelEssenceMsg extends BaseAction { - actionName = ActionName.DelEssenceMsg; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const msg = await MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); - if (!msg) { - throw new Error('msg not found'); - } - return await NTQQGroupApi.removeGroupEssence( - msg.Peer.peerUid, - msg.MsgId - ); - } -} diff --git a/src/onebot11/action/group/GetGroupEssence.ts b/src/onebot11/action/group/GetGroupEssence.ts deleted file mode 100644 index 7e90d6fc..00000000 --- a/src/onebot11/action/group/GetGroupEssence.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { getGroup } from '@/core/data'; -import { OB11Group } from '../../types'; -import { OB11Constructor } from '../../constructor'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQMsgApi } from '@/core/apis/msg'; -import { GroupEssenceMsgRet, WebApi } from '@/core/apis/webapi'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - pages: { type: 'number' }, - }, - required: ['group_id', 'pages'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class GetGroupEssence extends BaseAction { - actionName = ActionName.GoCQHTTP_GetEssenceMsg; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const ret = await WebApi.getGroupEssenceMsg(payload.group_id.toString(), payload.pages.toString()); - if (!ret) { - throw new Error('获取失败'); - } - return ret; - } -} diff --git a/src/onebot11/action/group/GetGroupInfo.ts b/src/onebot11/action/group/GetGroupInfo.ts deleted file mode 100644 index 1a460017..00000000 --- a/src/onebot11/action/group/GetGroupInfo.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { getGroup } from '@/core/data'; -import { OB11Group } from '../../types'; -import { OB11Constructor } from '../../constructor'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - }, - required: ['group_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -class GetGroupInfo extends BaseAction { - actionName = ActionName.GetGroupInfo; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const group = await getGroup(payload.group_id.toString()); - if (group) { - return OB11Constructor.group(group); - } else { - throw `群${payload.group_id}不存在`; - } - } -} - -export default GetGroupInfo; diff --git a/src/onebot11/action/group/GetGroupList.ts b/src/onebot11/action/group/GetGroupList.ts deleted file mode 100644 index 396649ff..00000000 --- a/src/onebot11/action/group/GetGroupList.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { OB11Group } from '../../types'; -import { OB11Constructor } from '../../constructor'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core/apis'; -import { Group } from '@/core/entities'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -// no_cache get时传字符串 -const SchemaData = { - type: 'object', - properties: { - no_cache: { type: ['boolean', 'string'] }, - } -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -class GetGroupList extends BaseAction { - actionName = ActionName.GetGroupList; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const groupList: Group[] = await NTQQGroupApi.getGroups(payload?.no_cache === true || payload.no_cache === 'true'); - return OB11Constructor.groups(groupList); - } -} - -export default GetGroupList; diff --git a/src/onebot11/action/group/GetGroupMemberInfo.ts b/src/onebot11/action/group/GetGroupMemberInfo.ts deleted file mode 100644 index 06b2c3f0..00000000 --- a/src/onebot11/action/group/GetGroupMemberInfo.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { OB11GroupMember } from '../../types'; -import { OB11Constructor } from '../../constructor'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis/user'; -import { logDebug } from '@/common/utils/log'; -import { WebApi } from '@/core/apis/webapi'; -import { NTQQGroupApi } from '@/core'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { getGroupMember, selfInfo } from '@/core/data'; -import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo'; -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['number', 'string'] }, - user_id: { type: ['number', 'string'] }, - no_cache: { type: ['boolean', 'string'] }, - }, - required: ['group_id', 'user_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -class GetGroupMemberInfo extends BaseAction { - actionName = ActionName.GetGroupMemberInfo; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const isNocache = payload.no_cache == true || payload.no_cache === 'true'; - const uid = await NTQQUserApi.getUidByUin(payload.user_id.toString()); - if (!uid) { - throw (`Uin2Uid Error ${payload.user_id}不存在`); - } - const member = await NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache); - if (!member) { - throw (`群(${payload.group_id})成员${payload.user_id}不存在`); - } - try { - const info = (await NTQQUserApi.getUserDetailInfo(member.uid)); - logDebug('群成员详细信息结果', info); - Object.assign(member, info); - } catch (e) { - logDebug('获取群成员详细信息失败, 只能返回基础信息', e); - } - const date = Math.round(Date.now() / 1000); - const retMember = OB11Constructor.groupMember(payload.group_id.toString(), member); - if (!requireMinNTQQBuild('26702')) { - const SelfInfoInGroup = await NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), selfInfo.uid, isNocache); - let isPrivilege = false; - if (SelfInfoInGroup) { - isPrivilege = SelfInfoInGroup.role === 3 || SelfInfoInGroup.role === 4; - } - if (isPrivilege) { - const webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString()); - for (let i = 0, len = webGroupMembers.length; i < len; i++) { - if (webGroupMembers[i]?.uin && webGroupMembers[i].uin === retMember.user_id) { - retMember.join_time = webGroupMembers[i]?.join_time; - retMember.last_sent_time = webGroupMembers[i]?.last_speak_time; - retMember.qage = webGroupMembers[i]?.qage; - retMember.level = webGroupMembers[i]?.lv.level.toString(); - } - } - } else { - const LastestMsgList = await NTQQGroupApi.getLastestMsg(payload.group_id.toString(), [payload.user_id.toString()]); - if (LastestMsgList?.msgList?.length && LastestMsgList?.msgList?.length > 0) { - const last_send_time = LastestMsgList.msgList[0].msgTime; - if (last_send_time && last_send_time != '0' && last_send_time != '') { - retMember.last_sent_time = parseInt(last_send_time); - retMember.join_time = Math.round(Date.now() / 1000);//兜底数据 防止群管乱杀 - } - } - } - } else { - retMember.last_sent_time = parseInt((await getGroupMember(payload.group_id.toString(), retMember.user_id))?.lastSpeakTime || date.toString()); - retMember.join_time = parseInt((await getGroupMember(payload.group_id.toString(), retMember.user_id))?.joinTime || date.toString()); - } - return retMember; - } -} -export default GetGroupMemberInfo; \ No newline at end of file diff --git a/src/onebot11/action/group/GetGroupMemberInfoOld.ts b/src/onebot11/action/group/GetGroupMemberInfoOld.ts deleted file mode 100644 index 7d9708ce..00000000 --- a/src/onebot11/action/group/GetGroupMemberInfoOld.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { OB11GroupMember } from '../../types'; -import { getGroup, getGroupMember, groupMembers, selfInfo } from '@/core/data'; -import { OB11Constructor } from '../../constructor'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi } from '@/core/apis/user'; -import { logDebug } from '@/common/utils/log'; -import { WebApi } from '@/core/apis/webapi'; -import { NTQQGroupApi } from '@/core'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo'; - -// no_cache get时传字符串 -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['number', 'string'] }, - user_id: { type: ['number', 'string'] }, - no_cache: { type: ['boolean', 'string'] }, - }, - required: ['group_id', 'user_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -class GetGroupMemberInfo extends BaseAction { - actionName = ActionName.GetGroupMemberInfo; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - if (requireMinNTQQBuild('26702')) { - const V2Data = await NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), payload.user_id.toString(), payload.no_cache == true || payload.no_cache === 'true'); - if (V2Data) { - return OB11Constructor.groupMember(payload.group_id.toString(), V2Data); - } else { - throw (`群(${payload.group_id})成员${payload.user_id}不存在`); - } - } - const group = await getGroup(payload.group_id.toString()); - const role = (await getGroupMember(payload.group_id, selfInfo.uin))?.role; - const isPrivilege = role === 3 || role === 4; - if (!group) { - throw (`群(${payload.group_id})不存在`); - } - if (payload.no_cache == true || payload.no_cache === 'true') { - groupMembers.set(group.groupCode, await NTQQGroupApi.getGroupMembers(payload.group_id.toString())); - } - const member = await getGroupMember(payload.group_id.toString(), payload.user_id.toString()); - //早返回 - if (!member) { - throw (`群(${payload.group_id})成员${payload.user_id}不存在`); - } - //console.log('GetGroupMemberInfo', JSON.stringify(await NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), member.uid, true), null, 4)); - try { - const info = (await NTQQUserApi.getUserDetailInfo(member.uid)); - logDebug('群成员详细信息结果', info); - Object.assign(member, info); - } catch (e) { - logDebug('获取群成员详细信息失败, 只能返回基础信息', e); - } - const retMember = OB11Constructor.groupMember(payload.group_id.toString(), member); - if (isPrivilege) { - const webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString()); - for (let i = 0, len = webGroupMembers.length; i < len; i++) { - if (webGroupMembers[i]?.uin && webGroupMembers[i].uin === retMember.user_id) { - retMember.join_time = webGroupMembers[i]?.join_time; - retMember.last_sent_time = webGroupMembers[i]?.last_speak_time; - retMember.qage = webGroupMembers[i]?.qage; - retMember.level = webGroupMembers[i]?.lv.level.toString(); - } - } - } else { - const LastestMsgList = await NTQQGroupApi.getLastestMsg(payload.group_id.toString(), [payload.user_id.toString()]); - if (LastestMsgList?.msgList?.length && LastestMsgList?.msgList?.length > 0) { - const last_send_time = LastestMsgList.msgList[0].msgTime; - if (last_send_time && last_send_time != '0' && last_send_time != '') { - retMember.last_sent_time = parseInt(last_send_time); - retMember.join_time = Math.round(Date.now() / 1000);//兜底数据 防止群管乱杀 - } - } - } - return retMember; - } -} -export default GetGroupMemberInfo; \ No newline at end of file diff --git a/src/onebot11/action/group/GetGroupMemberList.ts b/src/onebot11/action/group/GetGroupMemberList.ts deleted file mode 100644 index ba1d6e4a..00000000 --- a/src/onebot11/action/group/GetGroupMemberList.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { getGroup, getGroupMember, selfInfo } from '@/core/data'; -import { OB11GroupMember } from '../../types'; -import { OB11Constructor } from '../../constructor'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core'; -import { WebApi } from '@/core/apis/webapi'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['number', 'string'] }, - no_cache: { type: ['boolean', 'string'] }, - }, - required: ['group_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -class GetGroupMemberList extends BaseAction { - actionName = ActionName.GetGroupMemberList; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const isNocache = payload.no_cache == true || payload.no_cache === 'true'; - - const GroupList = await NTQQGroupApi.getGroups(isNocache); - const group = GroupList.find(item => item.groupCode == payload.group_id); - if (!group) { - throw (`群${payload.group_id}不存在`); - } - const groupMembers = await NTQQGroupApi.getGroupMembers(payload.group_id.toString()); - let _groupMembers = Array.from(groupMembers.values()) - .map(item => { return OB11Constructor.groupMember(group.groupCode, item); }); - - const MemberMap: Map = new Map(); - // 转为Map 方便索引 - const date = Math.round(Date.now() / 1000); - for (let i = 0, len = _groupMembers.length; i < len; i++) { - // 保证基础数据有这个 同时避免群管插件过于依赖这个杀了 - _groupMembers[i].join_time = date; - _groupMembers[i].last_sent_time = date; - MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]); - } - - if (!requireMinNTQQBuild('26702')) { - const selfRole = groupMembers.get(selfInfo.uid)?.role; - const isPrivilege = selfRole === 3 || selfRole === 4; - - if (isPrivilege) { - const webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString()); - for (let i = 0, len = webGroupMembers.length; i < len; i++) { - if (!webGroupMembers[i]?.uin) { - continue; - } - const MemberData = MemberMap.get(webGroupMembers[i]?.uin); - if (MemberData) { - MemberData.join_time = webGroupMembers[i]?.join_time; - MemberData.last_sent_time = webGroupMembers[i]?.last_speak_time; - MemberData.qage = webGroupMembers[i]?.qage; - MemberData.level = webGroupMembers[i]?.lv.level.toString(); - MemberMap.set(webGroupMembers[i]?.uin, MemberData); - } - } - } else { - if (isNocache) { - const DateMap = await NTQQGroupApi.getGroupMemberLastestSendTimeCache(payload.group_id.toString());//开始从本地拉取 - for (const DateUin of DateMap.keys()) { - const MemberData = MemberMap.get(parseInt(DateUin)); - if (MemberData) { - MemberData.last_sent_time = parseInt(DateMap.get(DateUin)!); - //join_time 有基础数据兜底 - } - } - } else { - _groupMembers.forEach(item => { - item.last_sent_time = date; - item.join_time = date; - }); - } - } - } else { - _groupMembers.forEach(async item => { - item.last_sent_time = parseInt((await getGroupMember(payload.group_id.toString(), item.user_id))?.lastSpeakTime || date.toString()); - item.join_time = parseInt((await getGroupMember(payload.group_id.toString(), item.user_id))?.joinTime || date.toString()); - }); - } - // 还原索引到Array 一同返回 - - // let retData: any[] = []; - // for (let retMem of MemberMap.values()) { - // retMem.level = TypeConvert.toString(retMem.level) as any; - // retData.push(retMem) - // } - - // _groupMembers = Array.from(retData); - - _groupMembers = Array.from(MemberMap.values()); - return _groupMembers; - } -} - -export default GetGroupMemberList; diff --git a/src/onebot11/action/group/GetGroupNotice.ts b/src/onebot11/action/group/GetGroupNotice.ts deleted file mode 100644 index cd61e25f..00000000 --- a/src/onebot11/action/group/GetGroupNotice.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { WebApi, WebApiGroupNoticeFeed, WebApiGroupNoticeRet } from '@/core/apis/webapi'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -interface GroupNotice { - sender_id: number - publish_time: number - message: { - text: string - image: Array<{ - height: string - width: string - id: string - }> - } -} - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - }, - required: ['group_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -type ApiGroupNotice = GroupNotice & WebApiGroupNoticeFeed; -export class GetGroupNotice extends BaseAction { - actionName = ActionName.GoCQHTTP_GetGroupNotice; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const group = payload.group_id.toString(); - const ret = await WebApi.getGrouptNotice(group); - if (!ret) { - throw new Error('获取公告失败'); - } - const retNotices: GroupNotice[] = new Array(); - for (const key in ret.feeds) { - const retApiNotice: WebApiGroupNoticeFeed = ret.feeds[key]; - const retNotice: GroupNotice = { - // ...ret.feeds[key], - sender_id: retApiNotice.u, - publish_time: retApiNotice.pubt, - message: { - text: retApiNotice.msg.text, - image: retApiNotice.msg.pics?.map((pic) => { - return { id: pic.id, height: pic.h, width: pic.w }; - }) || [] - } - }; - retNotices.push(retNotice); - } - - return retNotices; - } -} diff --git a/src/onebot11/action/group/GetGroupSystemMsg.ts b/src/onebot11/action/group/GetGroupSystemMsg.ts deleted file mode 100644 index cb6f4bb7..00000000 --- a/src/onebot11/action/group/GetGroupSystemMsg.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { NTQQGroupApi, NTQQUserApi } from '@/core'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['number', 'string'] } - }, -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class GetGroupSystemMsg extends BaseAction { - actionName = ActionName.GetGroupSystemMsg; - protected async _handle(payload: void) { - // 默认10条 该api未完整实现 包括响应数据规范化 类型规范化 - const SingleScreenNotifies = await NTQQGroupApi.getSingleScreenNotifies(10); - const retData: any = { InvitedRequest: [], join_requests: [] }; - for (const SSNotify of SingleScreenNotifies) { - if (SSNotify.type == 1) { - retData.InvitedRequest.push({ - request_id: SSNotify.seq, - invitor_uin: await NTQQUserApi.getUinByUid(SSNotify.user1?.uid), - invitor_nick: SSNotify.user1?.nickName, - group_id: SSNotify.group?.groupCode, - group_name: SSNotify.group?.groupName, - checked: SSNotify.status === 1 ? false : true, - actor: await NTQQUserApi.getUinByUid(SSNotify.user2?.uid) || 0, - }); - } else if (SSNotify.type == 7) { - retData.join_requests.push({ - request_id: SSNotify.seq, - requester_uin: await NTQQUserApi.getUinByUid(SSNotify.user1?.uid), - requester_nick: SSNotify.user1?.nickName, - group_id: SSNotify.group?.groupCode, - group_name: SSNotify.group?.groupName, - checked: SSNotify.status === 1 ? false : true, - actor: await NTQQUserApi.getUinByUid(SSNotify.user2?.uid) || 0, - }); - } - } - - return retData; - } -} diff --git a/src/onebot11/action/group/GetGuildList.ts b/src/onebot11/action/group/GetGuildList.ts deleted file mode 100644 index ea36304b..00000000 --- a/src/onebot11/action/group/GetGuildList.ts +++ /dev/null @@ -1,10 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; - -export default class GetGuildList extends BaseAction { - actionName = ActionName.GetGuildList; - - protected async _handle(payload: null): Promise { - return null; - } -} \ No newline at end of file diff --git a/src/onebot11/action/group/SendGroupMsg.ts b/src/onebot11/action/group/SendGroupMsg.ts deleted file mode 100644 index 22c06831..00000000 --- a/src/onebot11/action/group/SendGroupMsg.ts +++ /dev/null @@ -1,17 +0,0 @@ -import SendMsg, { ContextMode } from '../msg/SendMsg'; -import { ActionName, BaseCheckResult } from '../types'; -import { OB11PostSendMsg } from '../../types'; - -// 未检测参数 -class SendGroupMsg extends SendMsg { - actionName = ActionName.SendGroupMsg; - contextMode: ContextMode = ContextMode.Group; - - protected async check(payload: OB11PostSendMsg): Promise { - delete payload.user_id; - payload.message_type = 'group'; - return super.check(payload); - } -} - -export default SendGroupMsg; diff --git a/src/onebot11/action/group/SetEssenceMsg.ts b/src/onebot11/action/group/SetEssenceMsg.ts deleted file mode 100644 index b8cb2f45..00000000 --- a/src/onebot11/action/group/SetEssenceMsg.ts +++ /dev/null @@ -1,30 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { NTQQGroupApi, NTQQMsgApi } from '@/core'; -import { MessageUnique } from '@/common/utils/MessageUnique'; - -const SchemaData = { - type: 'object', - properties: { - message_id: { type: ['number', 'string'] } - }, - required: ['message_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class SetEssenceMsg extends BaseAction { - actionName = ActionName.SetEssenceMsg; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const msg = await MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); - if (!msg) { - throw new Error('msg not found'); - } - return await NTQQGroupApi.addGroupEssence( - msg.Peer.peerUid, - msg.MsgId - ); - } -} diff --git a/src/onebot11/action/group/SetGroupAddRequest.ts b/src/onebot11/action/group/SetGroupAddRequest.ts deleted file mode 100644 index 3f079ff1..00000000 --- a/src/onebot11/action/group/SetGroupAddRequest.ts +++ /dev/null @@ -1,31 +0,0 @@ -import BaseAction from '../BaseAction'; -import { GroupRequestOperateTypes } from '@/core/entities'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core/apis/group'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - flag: { type: 'string' }, - approve: { type: ['string', 'boolean'] }, - reason: { type: 'string', nullable: true, } - }, - required: ['flag'], -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class SetGroupAddRequest extends BaseAction { - actionName = ActionName.SetGroupAddRequest; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const flag = payload.flag.toString(); - const approve = payload.approve?.toString() !== 'false'; - await NTQQGroupApi.handleGroupRequest(flag, - approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject, - payload.reason - ); - return null; - } -} diff --git a/src/onebot11/action/group/SetGroupAdmin.ts b/src/onebot11/action/group/SetGroupAdmin.ts deleted file mode 100644 index 42701b62..00000000 --- a/src/onebot11/action/group/SetGroupAdmin.ts +++ /dev/null @@ -1,33 +0,0 @@ -import BaseAction from '../BaseAction'; -import { getGroupMember } from '@/core/data'; -import { GroupMemberRole } from '@/core/entities'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core/apis/group'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - user_id: { type: [ 'number' , 'string' ] }, - enable: { type: 'boolean' } - }, - required: ['group_id', 'user_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class SetGroupAdmin extends BaseAction { - actionName = ActionName.SetGroupAdmin; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const member = await getGroupMember(payload.group_id, payload.user_id); - // 已经前置验证类型 - const enable = payload.enable?.toString() !== 'false'; - if (!member) { - throw `群成员${payload.user_id}不存在`; - } - await NTQQGroupApi.setMemberRole(payload.group_id.toString(), member.uid, enable ? GroupMemberRole.admin : GroupMemberRole.normal); - return null; - } -} diff --git a/src/onebot11/action/group/SetGroupBan.ts b/src/onebot11/action/group/SetGroupBan.ts deleted file mode 100644 index 27155b46..00000000 --- a/src/onebot11/action/group/SetGroupBan.ts +++ /dev/null @@ -1,31 +0,0 @@ -import BaseAction from '../BaseAction'; -import { getGroupMember } from '@/core/data'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core/apis/group'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: ['number', 'string'] }, - user_id: { type: ['number', 'string'] }, - duration: { type: ['number', 'string'] } - }, - required: ['group_id', 'user_id', 'duration'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class SetGroupBan extends BaseAction { - actionName = ActionName.SetGroupBan; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const member = await getGroupMember(payload.group_id, payload.user_id); - if (!member) { - throw `群成员${payload.user_id}不存在`; - } - await NTQQGroupApi.banMember(payload.group_id.toString(), - [{ uid: member.uid, timeStamp: parseInt(payload.duration.toString()) }]); - return null; - } -} diff --git a/src/onebot11/action/group/SetGroupCard.ts b/src/onebot11/action/group/SetGroupCard.ts deleted file mode 100644 index aef7274c..00000000 --- a/src/onebot11/action/group/SetGroupCard.ts +++ /dev/null @@ -1,30 +0,0 @@ -import BaseAction from '../BaseAction'; -import { getGroupMember } from '@/core/data'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core/apis/group'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - user_id: { type: [ 'number' , 'string' ] }, - card: { type: 'string' } - }, - required: ['group_id', 'user_id', 'card'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class SetGroupCard extends BaseAction { - actionName = ActionName.SetGroupCard; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const member = await getGroupMember(payload.group_id, payload.user_id); - if (!member) { - throw `群成员${payload.user_id}不存在`; - } - await NTQQGroupApi.setMemberCard(payload.group_id.toString(), member.uid, payload.card || ''); - return null; - } -} diff --git a/src/onebot11/action/group/SetGroupKick.ts b/src/onebot11/action/group/SetGroupKick.ts deleted file mode 100644 index 2af20234..00000000 --- a/src/onebot11/action/group/SetGroupKick.ts +++ /dev/null @@ -1,32 +0,0 @@ -import BaseAction from '../BaseAction'; -import { getGroupMember } from '@/core/data'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core/apis/group'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - user_id: { type: [ 'number' , 'string' ] }, - reject_add_request: { type: [ 'boolean' , 'string' ] } - }, - required: ['group_id', 'user_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class SetGroupKick extends BaseAction { - actionName = ActionName.SetGroupKick; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const member = await getGroupMember(payload.group_id, payload.user_id); - if (!member) { - throw `群成员${payload.user_id}不存在`; - } - const rejectReq = payload.reject_add_request?.toString() == 'true'; - await NTQQGroupApi.kickMember(payload.group_id.toString(), [member.uid], rejectReq); - return null; - } -} diff --git a/src/onebot11/action/group/SetGroupLeave.ts b/src/onebot11/action/group/SetGroupLeave.ts deleted file mode 100644 index fed7d67c..00000000 --- a/src/onebot11/action/group/SetGroupLeave.ts +++ /dev/null @@ -1,29 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core/apis/group'; -import { log, logError } from '@/common/utils/log'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { deleteGroup } from '@/core/data'; -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - is_dismiss: { type: 'boolean' } - }, - required: ['group_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; -export default class SetGroupLeave extends BaseAction { - actionName = ActionName.SetGroupLeave; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - try { - await NTQQGroupApi.quitGroup(payload.group_id.toString()); - deleteGroup(payload.group_id.toString()); - } catch (e) { - logError('退群失败', e); - throw e; - } - } -} diff --git a/src/onebot11/action/group/SetGroupName.ts b/src/onebot11/action/group/SetGroupName.ts deleted file mode 100644 index d65383cb..00000000 --- a/src/onebot11/action/group/SetGroupName.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core/apis/group'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - group_name: { type: 'string' } - }, - required: ['group_id', 'group_name'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; -export default class SetGroupName extends BaseAction { - actionName = ActionName.SetGroupName; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - - await NTQQGroupApi.setGroupName(payload.group_id.toString(), payload.group_name); - return null; - } -} diff --git a/src/onebot11/action/group/SetGroupWholeBan.ts b/src/onebot11/action/group/SetGroupWholeBan.ts deleted file mode 100644 index 38b4ffc7..00000000 --- a/src/onebot11/action/group/SetGroupWholeBan.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQGroupApi } from '@/core/apis/group'; - -const SchemaData = { - type: 'object', - properties: { - group_id: { type: [ 'number' , 'string' ] }, - enable: { type: ['boolean','string'] } - }, - required: ['group_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class SetGroupWholeBan extends BaseAction { - actionName = ActionName.SetGroupWholeBan; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const enable = payload.enable?.toString() !== 'false'; - await NTQQGroupApi.banGroup(payload.group_id.toString(), enable); - return null; - } -} diff --git a/src/onebot11/action/index.ts b/src/onebot11/action/index.ts deleted file mode 100644 index f4df4ea3..00000000 --- a/src/onebot11/action/index.ts +++ /dev/null @@ -1,180 +0,0 @@ -import GetMsg from './msg/GetMsg'; -import GetLoginInfo from './system/GetLoginInfo'; -import GetFriendList from './user/GetFriendList'; -import GetGroupList from './group/GetGroupList'; -import GetGroupInfo from './group/GetGroupInfo'; -import GetGroupMemberList from './group/GetGroupMemberList'; -import GetGroupMemberInfo from './group/GetGroupMemberInfo'; -import SendGroupMsg from './group/SendGroupMsg'; -import SendPrivateMsg from './msg/SendPrivateMsg'; -import SendMsg from './msg/SendMsg'; -import DeleteMsg from './msg/DeleteMsg'; -import BaseAction from './BaseAction'; -import GetVersionInfo from './system/GetVersionInfo'; -import CanSendRecord from './system/CanSendRecord'; -import CanSendImage from './system/CanSendImage'; -import GetStatus from './system/GetStatus'; -import { - GoCQHTTPSendForwardMsg, - GoCQHTTPSendGroupForwardMsg, - GoCQHTTPSendPrivateForwardMsg -} from './go-cqhttp/SendForwardMsg'; -import GoCQHTTPGetStrangerInfo from './go-cqhttp/GetStrangerInfo'; -import SendLike from './user/SendLike'; -import SetGroupAddRequest from './group/SetGroupAddRequest'; -import SetGroupLeave from './group/SetGroupLeave'; -import GetGuildList from './group/GetGuildList'; -import Debug from '@/onebot11/action/extends/Debug'; -import SetFriendAddRequest from './user/SetFriendAddRequest'; -import SetGroupWholeBan from './group/SetGroupWholeBan'; -import SetGroupName from './group/SetGroupName'; -import SetGroupBan from './group/SetGroupBan'; -import SetGroupKick from './group/SetGroupKick'; -import SetGroupAdmin from './group/SetGroupAdmin'; -import SetGroupCard from './group/SetGroupCard'; -import GetImage from './file/GetImage'; -import GetRecord from './file/GetRecord'; -import { GoCQHTTPMarkMsgAsRead, MarkAllMsgAsRead, MarkGroupMsgAsRead, MarkPrivateMsgAsRead } from './msg/MarkMsgAsRead'; -import CleanCache from './system/CleanCache'; -import GoCQHTTPUploadGroupFile from './go-cqhttp/UploadGroupFile'; -import { GetConfigAction, SetConfigAction } from '@/onebot11/action/extends/Config'; -import GetGroupAddRequest from '@/onebot11/action/extends/GetGroupAddRequest'; -import SetQQAvatar from '@/onebot11/action/extends/SetQQAvatar'; -import GoCQHTTPDownloadFile from './go-cqhttp/DownloadFile'; -import GoCQHTTPGetGroupMsgHistory from './go-cqhttp/GetGroupMsgHistory'; -import GetFile from './file/GetFile'; -import { GoCQHTTPGetForwardMsgAction } from './go-cqhttp/GetForwardMsg'; -import GetFriendMsgHistory from './go-cqhttp/GetFriendMsgHistory'; -import { GetCookies } from './user/GetCookies'; -import { SetMsgEmojiLike } from '@/onebot11/action/msg/SetMsgEmojiLike'; -import { GetRobotUinRange } from './extends/GetRobotUinRange'; -import { SetOnlineStatus } from './extends/SetOnlineStatus'; -import { GetGroupNotice } from './group/GetGroupNotice'; -import { GetGroupEssence } from './group/GetGroupEssence'; -import { ForwardFriendSingleMsg, ForwardGroupSingleMsg } from '@/onebot11/action/msg/ForwardSingleMsg'; -import { GetFriendWithCategory } from './extends/GetFriendWithCategory'; -import { SendGroupNotice } from './go-cqhttp/SendGroupNotice'; -import { Reboot, RebootNormal } from './system/Reboot'; -import { GetGroupHonorInfo } from './go-cqhttp/GetGroupHonorInfo'; -import { GoCQHTTPHandleQuickAction } from './go-cqhttp/QuickAction'; -import { GetGroupSystemMsg } from './group/GetGroupSystemMsg'; -import { GetOnlineClient } from './go-cqhttp/GetOnlineClient'; -import { IOCRImage, OCRImage } from './extends/OCRImage'; -import { GetGroupFileCount } from './file/GetGroupFileCount'; -import { GetGroupFileList } from './file/GetGroupFileList'; -import { TranslateEnWordToZn } from './extends/TranslateEnWordToZn'; -import { SetGroupFileFolder } from './file/SetGroupFileFolder'; -import { DelGroupFile } from './file/DelGroupFile'; -import { DelGroupFileFolder } from './file/DelGroupFileFolder'; -import { SetSelfProfile } from './extends/SetSelfProfile'; -import { shareGroupEx, sharePeer } from './extends/sharePeer'; -import { CreateCollection } from './extends/CreateCollection'; -import { SetLongNick } from './extends/SetLongNick'; -import DelEssenceMsg from './group/DelEssenceMsg'; -import SetEssenceMsg from './group/SetEssenceMsg'; -import GetRecentContact from './user/GetRecentContact'; -import { GetProfileLike } from './extends/GetProfileLike'; -import SetGroupHeader from './extends/SetGroupHeader'; -import { FetchCustomFace } from './extends/FetchCustomFace'; -import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivareFile'; -import TestApi01 from './extends/TestApi01'; -import { FetchEmojioLike } from './extends/FetchEmojioLike'; - -export const actionHandlers = [ - new FetchEmojioLike(), - new RebootNormal(), - new GetFile(), - new Debug(), - new Reboot(), - new SetSelfProfile(), - new shareGroupEx(), - new sharePeer(), - new CreateCollection(), - new SetLongNick(), - new ForwardFriendSingleMsg(), - new ForwardGroupSingleMsg(), - new MarkGroupMsgAsRead(), - new MarkPrivateMsgAsRead(), - new SetQQAvatar(), - new TranslateEnWordToZn(), - new GetGroupFileCount(), - new GetGroupFileList(), - new SetGroupFileFolder(), - new DelGroupFile(), - new DelGroupFileFolder(), - // onebot11 - new SendLike(), - new GetMsg(), - new GetLoginInfo(), - new GetFriendList(), - new GetGroupList(), - new GetGroupInfo(), - new GetGroupMemberList(), - new GetGroupMemberInfo(), - new SendGroupMsg(), - new SendPrivateMsg(), - new SendMsg(), - new DeleteMsg(), - new SetGroupAddRequest(), - new SetFriendAddRequest(), - new SetGroupLeave(), - new GetVersionInfo(), - new CanSendRecord(), - new CanSendImage(), - new GetStatus(), - new SetGroupWholeBan(), - new SetGroupBan(), - new SetGroupKick(), - new SetGroupAdmin(), - new SetGroupName(), - new SetGroupCard(), - new GetImage(), - new GetRecord(), - new SetMsgEmojiLike(), - new GetCookies(), - new SetOnlineStatus(), - new GetRobotUinRange(), - new GetFriendWithCategory(), - //以下为go-cqhttp api - new GetOnlineClient(), - new OCRImage(), - new IOCRImage(), - new GetGroupHonorInfo(), - new SendGroupNotice(), - new GetGroupNotice(), - new GetGroupEssence(), - new GoCQHTTPSendForwardMsg(), - new GoCQHTTPSendGroupForwardMsg(), - new GoCQHTTPSendPrivateForwardMsg(), - new GoCQHTTPGetStrangerInfo(), - new GoCQHTTPDownloadFile(), - new GetGuildList(), - new GoCQHTTPMarkMsgAsRead(), - new GoCQHTTPUploadGroupFile(), - new GoCQHTTPGetGroupMsgHistory(), - new GoCQHTTPGetForwardMsgAction(), - new GetFriendMsgHistory(), - new GoCQHTTPHandleQuickAction(), - new GetGroupSystemMsg(), - new DelEssenceMsg(), - new SetEssenceMsg(), - new GetRecentContact(), - new MarkAllMsgAsRead(), - new GetProfileLike(), - new SetGroupHeader(), - new FetchCustomFace(), - new GoCQHTTPUploadPrivateFile(), - new TestApi01() -]; -function initActionMap() { - const actionMap = new Map>(); - for (const action of actionHandlers) { - actionMap.set(action.actionName, action); - actionMap.set(action.actionName + '_async', action); - actionMap.set(action.actionName + '_rate_limited', action); - } - - return actionMap; -} - -export const actionMap = initActionMap(); diff --git a/src/onebot11/action/msg/DeleteMsg.ts b/src/onebot11/action/msg/DeleteMsg.ts deleted file mode 100644 index f180329c..00000000 --- a/src/onebot11/action/msg/DeleteMsg.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { NTQQMsgApi } from '@/core/apis'; -import { ActionName } from '../types'; -import BaseAction from '../BaseAction'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { MessageUnique } from '@/common/utils/MessageUnique'; -import { sleep } from '@/common/utils/helper'; -import { NTEventDispatch } from '@/common/utils/EventTask'; -import { NodeIKernelMsgListener } from '@/core'; - -const SchemaData = { - type: 'object', - properties: { - message_id: { - oneOf: [ - { type: 'number' }, - { type: 'string' } - ] - } - }, - required: ['message_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -class DeleteMsg extends BaseAction { - actionName = ActionName.DeleteMsg; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const msg = MessageUnique.getMsgIdAndPeerByShortId(Number(payload.message_id)); - if (msg) { - let ret = NTEventDispatch.RegisterListen - ( - 'NodeIKernelMsgListener/onMsgInfoListUpdate', - 1, - 5000, - (msgs) => { - if (msgs.find(m => m.msgId === msg.MsgId && m.recallTime !== '0')) { - return true; - } - return false; - } - ).catch(e => new Promise((resolve, reject) => { resolve(undefined) })); - await NTQQMsgApi.recallMsg(msg.Peer, [msg.MsgId]); - let data = await ret; - if (!data) { - throw new Error('Recall failed'); - } - //await sleep(100); - //await NTQQMsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId]); - } - } -} - -export default DeleteMsg; diff --git a/src/onebot11/action/msg/ForwardSingleMsg.ts b/src/onebot11/action/msg/ForwardSingleMsg.ts deleted file mode 100644 index 1c200437..00000000 --- a/src/onebot11/action/msg/ForwardSingleMsg.ts +++ /dev/null @@ -1,57 +0,0 @@ -import BaseAction from '../BaseAction'; -import { NTQQMsgApi, NTQQUserApi } from '@/core/apis'; -import { ChatType, Peer } from '@/core/entities'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { MessageUnique } from '@/common/utils/MessageUnique'; - -const SchemaData = { - type: 'object', - properties: { - message_id: { type: 'number' }, - group_id: { type: ['number', 'string'] }, - user_id: { type: ['number', 'string'] } - }, - required: ['message_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -class ForwardSingleMsg extends BaseAction { - protected async getTargetPeer(payload: Payload): Promise { - if (payload.user_id) { - const peerUid = await NTQQUserApi.getUidByUin(payload.user_id.toString()); - if (!peerUid) { - throw new Error(`无法找到私聊对象${payload.user_id}`); - } - return { chatType: ChatType.friend, peerUid }; - } - return { chatType: ChatType.group, peerUid: payload.group_id!.toString() }; - } - - protected async _handle(payload: Payload): Promise { - const msg = await MessageUnique.getMsgIdAndPeerByShortId(payload.message_id); - if (!msg) { - throw new Error(`无法找到消息${payload.message_id}`); - } - const peer = await this.getTargetPeer(payload); - const ret = await NTQQMsgApi.forwardMsg(msg.Peer, - peer, - [msg.MsgId], - ); - if (ret.result !== 0) { - throw new Error(`转发消息失败 ${ret.errMsg}`); - } - return null; - } -} - -export class ForwardFriendSingleMsg extends ForwardSingleMsg { - PayloadSchema = SchemaData; - actionName = ActionName.ForwardFriendSingleMsg; -} - -export class ForwardGroupSingleMsg extends ForwardSingleMsg { - PayloadSchema = SchemaData; - actionName = ActionName.ForwardGroupSingleMsg; -} diff --git a/src/onebot11/action/msg/GetMsg.ts b/src/onebot11/action/msg/GetMsg.ts deleted file mode 100644 index 29edde9e..00000000 --- a/src/onebot11/action/msg/GetMsg.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { OB11Message } from '../../types'; -import { OB11Constructor } from '../../constructor'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { MessageUnique } from '@/common/utils/MessageUnique'; -import { NTQQMsgApi } from '@/core'; - - -export type ReturnDataType = OB11Message - -const SchemaData = { - type: 'object', - properties: { - message_id: { type: ['number', 'string'] }, - }, - required: ['message_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -class GetMsg extends BaseAction { - actionName = ActionName.GetMsg; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - // log("history msg ids", Object.keys(msgHistory)); - if (!payload.message_id) { - throw Error('参数message_id不能为空'); - } - const MsgShortId = await MessageUnique.getShortIdByMsgId(payload.message_id.toString()); - const msgIdWithPeer = await MessageUnique.getMsgIdAndPeerByShortId(MsgShortId || parseInt(payload.message_id.toString())); - if (!msgIdWithPeer) { - throw ('消息不存在'); - } - const peer = { guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType }; - const msg = await NTQQMsgApi.getMsgsByMsgId( - peer, - [msgIdWithPeer?.MsgId || payload.message_id.toString()]); - const retMsg = await OB11Constructor.message(msg.msgList[0]); - try { - retMsg.message_id = MessageUnique.createMsg(peer, msg.msgList[0].msgId)!; - retMsg.message_seq = retMsg.message_id; - retMsg.real_id = retMsg.message_id; - } catch (e) { - } - return retMsg; - } -} - -export default GetMsg; diff --git a/src/onebot11/action/msg/MarkMsgAsRead.ts b/src/onebot11/action/msg/MarkMsgAsRead.ts deleted file mode 100644 index 740be9cf..00000000 --- a/src/onebot11/action/msg/MarkMsgAsRead.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { ChatType, Peer } from '@/core/entities'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQFriendApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - user_id: { type: ['number', 'string'] }, - group_id: { type: ['number', 'string'] } - } -} as const satisfies JSONSchema; - -type PlayloadType = FromSchema; - -class MarkMsgAsRead extends BaseAction { - async getPeer(payload: PlayloadType): Promise { - if (payload.user_id) { - const peerUid = await NTQQUserApi.getUidByUin(payload.user_id.toString()); - if (!peerUid) { - throw `私聊${payload.user_id}不存在`; - } - const isBuddy = await NTQQFriendApi.isBuddy(peerUid); - return { chatType: isBuddy ? ChatType.friend : ChatType.temp, peerUid }; - } - if (!payload.group_id) { - throw '缺少参数 group_id 或 user_id'; - } - return { chatType: ChatType.group, peerUid: payload.group_id.toString() }; - } - protected async _handle(payload: PlayloadType): Promise { - // 调用API - const ret = await NTQQMsgApi.setMsgRead(await this.getPeer(payload)); - if (ret.result != 0) { - throw ('设置已读失败,' + ret.errMsg); - } - return null; - } -} -// 以下为非标准实现 -export class MarkPrivateMsgAsRead extends MarkMsgAsRead { - PayloadSchema = SchemaData; - actionName = ActionName.MarkPrivateMsgAsRead; -} -export class MarkGroupMsgAsRead extends MarkMsgAsRead { - PayloadSchema = SchemaData; - actionName = ActionName.MarkGroupMsgAsRead; -} - - -interface Payload { - message_id: number -} - -export class GoCQHTTPMarkMsgAsRead extends BaseAction { - actionName = ActionName.GoCQHTTP_MarkMsgAsRead; - - protected async _handle(payload: Payload): Promise { - return null; - } -} - -export class MarkAllMsgAsRead extends BaseAction { - actionName = ActionName._MarkAllMsgAsRead; - - protected async _handle(payload: Payload): Promise { - await NTQQMsgApi.markallMsgAsRead(); - return null; - } -} diff --git a/src/onebot11/action/msg/SendMsg/check-send-message.ts b/src/onebot11/action/msg/SendMsg/check-send-message.ts deleted file mode 100644 index 299f41dc..00000000 --- a/src/onebot11/action/msg/SendMsg/check-send-message.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { OB11MessageData } from '@/onebot11/types'; - -function checkSendMessage(sendMsgList: OB11MessageData[]) { - function checkUri(uri: string): boolean { - const pattern = /^(file:\/\/|http:\/\/|https:\/\/|base64:\/\/)/; - return pattern.test(uri); - } - - for (const msg of sendMsgList) { - if (msg['type'] && msg['data']) { - const type = msg['type']; - const data = msg['data']; - if (type === 'text' && !data['text']) { - return 400; - } else if (['image', 'voice', 'record'].includes(type)) { - if (!data['file']) { - return 400; - } else { - if (checkUri(data['file'])) { - return 200; - } else { - return 400; - } - } - - } else if (type === 'at' && !data['qq']) { - return 400; - } else if (type === 'reply' && !data['id']) { - return 400; - } - } else { - return 400; - } - } - return 200; -} diff --git a/src/onebot11/action/msg/SendMsg/create-send-elements.ts b/src/onebot11/action/msg/SendMsg/create-send-elements.ts deleted file mode 100644 index e23b0356..00000000 --- a/src/onebot11/action/msg/SendMsg/create-send-elements.ts +++ /dev/null @@ -1,248 +0,0 @@ -import { OB11MessageData, OB11MessageDataType, OB11MessageFileBase } from '@/onebot11/types'; -import { - AtType, - CustomMusicSignPostData, - Group, - IdMusicSignPostData, - NTQQFileApi, - NTQQMsgApi, - Peer, - SendArkElement, - SendMessageElement, - SendMsgElementConstructor, - SignMusicWrapper -} from '@/core'; -import { getGroupMember } from '@/core/data'; -import { logError, logWarn } from '@/common/utils/log'; -import { uri2local } from '@/common/utils/file'; -import { ob11Config } from '@/onebot11/config'; -import { RequestUtil } from '@/common/utils/request'; -import { MessageUnique } from '@/common/utils/MessageUnique'; -console.log(process.pid) -export type MessageContext = { - deleteAfterSentFiles: string[], - peer:Peer -} -async function handleOb11FileLikeMessage( - { data: inputdata }: OB11MessageFileBase, - { deleteAfterSentFiles }: MessageContext -) { - //有的奇怪的框架将url作为参数 而不是file 此时优先url 同时注意可能传入的是非file://开头的目录 By Mlikiowa - const { path, isLocal, fileName, errMsg,success } = (await uri2local(inputdata?.url || inputdata.file)); - - if (!success) { - logError('文件下载失败', errMsg); - throw Error('文件下载失败' + errMsg); - } - - if (!isLocal) { // 只删除http和base64转过来的文件 - deleteAfterSentFiles.push(path); - } - - return { path, fileName: inputdata.name || fileName }; -} - -const _handlers: { - [Key in OB11MessageDataType]: ( - sendMsg: Extract, - // This picks the correct message type out - // How great the type system of TypeScript is! - context: MessageContext - ) => Promise -} = { - [OB11MessageDataType.text]: async ({ data: { text } }) => SendMsgElementConstructor.text(text), - - [OB11MessageDataType.at]: async ({ data: { qq: atQQ } }, context) => { - if (!context.peer) return undefined; - - if (atQQ === 'all') return SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员'); - - // then the qq is a group member - const atMember = await getGroupMember(context.peer.peerUid, atQQ); - return atMember ? - SendMsgElementConstructor.at(atQQ, atMember.uid, AtType.atUser, atMember.cardName || atMember.nick) : - undefined; - }, - [OB11MessageDataType.reply]: async ({ data: { id } }) => { - const replyMsgM = MessageUnique.getMsgIdAndPeerByShortId(parseInt(id)); - if (!replyMsgM) { - logWarn('回复消息不存在', id); - return undefined; - } - const replyMsg = (await NTQQMsgApi.getMsgsByMsgId(replyMsgM?.Peer!, [replyMsgM?.MsgId!])).msgList[0]; - return replyMsg ? - SendMsgElementConstructor.reply(replyMsg.msgSeq, replyMsg.msgId, replyMsg.senderUin!, replyMsg.senderUin!) : - undefined; - }, - - [OB11MessageDataType.face]: async ({ data: { id } }) => SendMsgElementConstructor.face(parseInt(id)), - - [OB11MessageDataType.mface]: async ({ - data: { - emoji_package_id, - emoji_id, - key, - summary - } - }) => SendMsgElementConstructor.mface(emoji_package_id, emoji_id, key, summary), - - // File service - - [OB11MessageDataType.image]: async (sendMsg, context) => { - const PicEle = await SendMsgElementConstructor.pic( - (await handleOb11FileLikeMessage(sendMsg, context)).path, - sendMsg.data.summary || '', - sendMsg.data.subType || 0 - ); - context.deleteAfterSentFiles.push(PicEle.picElement.sourcePath); - return PicEle; - } - , // currently not supported - - [OB11MessageDataType.file]: async (sendMsg, context) => { - const { path, fileName } = await handleOb11FileLikeMessage(sendMsg, context); - //logDebug('发送文件', path, fileName); - const FileEle = await SendMsgElementConstructor.file(path, fileName); - // 清除Upload的应该 - // context.deleteAfterSentFiles.push(fileName || FileEle.fileElement.filePath); - return FileEle; - }, - - [OB11MessageDataType.video]: async (sendMsg, context) => { - const { path, fileName } = await handleOb11FileLikeMessage(sendMsg, context); - - //logDebug('发送视频', path, fileName); - let thumb = sendMsg.data.thumb; - if (thumb) { - const uri2LocalRes = await uri2local(thumb); - if (uri2LocalRes.success) thumb = uri2LocalRes.path; - } - const videoEle = await SendMsgElementConstructor.video(path, fileName, thumb); - //未测试 - context.deleteAfterSentFiles.push(videoEle.videoElement.filePath); - return videoEle; - }, - [OB11MessageDataType.miniapp]: async ({ data: any }) => SendMsgElementConstructor.miniapp(), - - [OB11MessageDataType.voice]: async (sendMsg, context) => - SendMsgElementConstructor.ptt((await handleOb11FileLikeMessage(sendMsg, context)).path), - - [OB11MessageDataType.json]: async ({ data: { data } }) => SendMsgElementConstructor.ark(data), - - [OB11MessageDataType.dice]: async ({ data: { result } }) => SendMsgElementConstructor.dice(result), - - [OB11MessageDataType.RPS]: async ({ data: { result } }) => SendMsgElementConstructor.rps(result), - - [OB11MessageDataType.markdown]: async ({ data: { content } }) => SendMsgElementConstructor.markdown(content), - - [OB11MessageDataType.music]: async ({ data }) => { - // 保留, 直到...找到更好的解决方案 - if (data.type === 'custom') { - if (!data.url) { - logError('自定义音卡缺少参数url'); - return undefined; - } - if (!data.audio) { - logError('自定义音卡缺少参数audio'); - return undefined; - } - if (!data.title) { - logError('自定义音卡缺少参数title'); - return undefined; - } - } else { - if (!['qq', '163'].includes(data.type)) { - logError('音乐卡片type错误, 只支持qq、163、custom,当前type:', data.type); - return undefined; - } - if (!data.id) { - logError('音乐卡片缺少参数id'); - return undefined; - } - } - - let postData: IdMusicSignPostData | CustomMusicSignPostData; - if (data.type === 'custom' && data.content) { - const { content, ...others } = data; - postData = { singer: content, ...others }; - } else { - postData = data; - } - - const signUrl = ob11Config.musicSignUrl; - if (!signUrl) { - if (data.type === 'qq') { - const musicJson = (await SignMusicWrapper(data.id.toString())).data.arkResult.slice(0, -1); - return SendMsgElementConstructor.ark(musicJson); - } - throw Error('音乐消息签名地址未配置'); - } - try { - const musicJson = await RequestUtil.HttpGetJson(signUrl, 'POST', postData); - return SendMsgElementConstructor.ark(musicJson); - } catch (e) { - logError('生成音乐消息失败', e); - } - }, - - [OB11MessageDataType.node]: async () => undefined, - - [OB11MessageDataType.forward]: async () => undefined, - - [OB11MessageDataType.xml]: async () => undefined, - - [OB11MessageDataType.poke]: async () => undefined, - - [OB11MessageDataType.Location]: async () => { - return SendMsgElementConstructor.location(); - } -}; - -const handlers = <{ - [Key in OB11MessageDataType]: ( - sendMsg: OB11MessageData, - context: MessageContext - ) => Promise -}>_handlers; - -export default async function createSendElements( - messageData: OB11MessageData[], - peer: Peer, - ignoreTypes: OB11MessageDataType[] = [] -) { - const deleteAfterSentFiles: string[] = []; - const callResultList: Array> = []; - for (const sendMsg of messageData) { - if (ignoreTypes.includes(sendMsg.type)) { - continue; - } - const callResult = handlers[sendMsg.type]( - sendMsg, - { peer, deleteAfterSentFiles } - )?.catch(undefined); - callResultList.push(callResult); - } - const ret = await Promise.all(callResultList); - const sendElements: SendMessageElement[] = ret.filter(ele => ele) as SendMessageElement[]; - return { sendElements, deleteAfterSentFiles }; -} - -export async function createSendElementsParallel( - messageData: OB11MessageData[], - peer: Peer, - ignoreTypes: OB11MessageDataType[] = [] -) { - const deleteAfterSentFiles: string[] = []; - const sendElements = ( - await Promise.all( - messageData.map(async sendMsg => ignoreTypes.includes(sendMsg.type) ? - undefined : - handlers[sendMsg.type](sendMsg, { peer, deleteAfterSentFiles })) - ).then( - results => results.filter( - element => element !== undefined - ) - ) - ); - return { sendElements, deleteAfterSentFiles }; -} diff --git a/src/onebot11/action/msg/SendMsg/handle-forward-node.ts b/src/onebot11/action/msg/SendMsg/handle-forward-node.ts deleted file mode 100644 index c01c26e0..00000000 --- a/src/onebot11/action/msg/SendMsg/handle-forward-node.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { ChatType, ElementType, Group, NTQQMsgApi, Peer, RawMessage, SendMessageElement } from '@/core'; -import { OB11MessageDataType, OB11MessageNode } from '@/onebot11/types'; -import { selfInfo } from '@/core/data'; -import createSendElements from '@/onebot11/action/msg/SendMsg/create-send-elements'; -import { logDebug, logError } from '@/common/utils/log'; -import { sleep } from '@/common/utils/helper'; -import { normalize, sendMsg } from '@/onebot11/action/msg/SendMsg/index'; -import { MessageUnique } from '@/common/utils/MessageUnique'; - -async function cloneMsg(msg: RawMessage): Promise { - const selfPeer = { - chatType: ChatType.friend, - peerUid: selfInfo.uid - }; - - //logDebug('克隆的目标消息', msg); - - const sendElements: SendMessageElement[] = []; - - for (const element of msg.elements) { - sendElements.push(element as SendMessageElement); - } - - if (sendElements.length === 0) { - logDebug('需要clone的消息无法解析,将会忽略掉', msg); - } - try { - const nodeMsg = await NTQQMsgApi.sendMsg(selfPeer, sendElements, true); - return nodeMsg; - } catch (e) { - logError(e, '克隆转发消息失败,将忽略本条消息', msg); - } -} - -export async function handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise { - const selfPeer = { - chatType: ChatType.friend, - peerUid: selfInfo.uid - }; - let nodeMsgIds: string[] = []; - for (const messageNode of messageNodes) { - const nodeId = messageNode.data.id; - if (nodeId) { - //对Mgsid和OB11ID混用情况兜底 - const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId); - if (!nodeMsg) { - logError('转发消息失败,未找到消息', nodeId); - continue; - } - nodeMsgIds.push(nodeMsg.MsgId); - } else { - // 自定义的消息 - try { - let OB11Data = normalize(messageNode.data.content); - //筛选node消息 - let isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息 - if (isNodeMsg !== 0) { - if (isNodeMsg !== OB11Data.length) { logError('子消息中包含非node消息 跳过不合法部分'); continue; } - const nodeMsg = await handleForwardNode(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node)); - if (nodeMsg) { nodeMsgIds.push(nodeMsg.msgId); MessageUnique.createMsg(selfPeer, nodeMsg.msgId) }; - //完成子卡片生成跳过后续 - continue; - } - const { sendElements } = await createSendElements(OB11Data, destPeer); - //拆分消息 - let MixElement = sendElements.filter(element => element.elementType !== ElementType.FILE && element.elementType !== ElementType.VIDEO); - let SingleElement = sendElements.filter(element => element.elementType === ElementType.FILE || element.elementType === ElementType.VIDEO).map(e => [e]); - let AllElement: SendMessageElement[][] = [MixElement, ...SingleElement].filter(e => e !== undefined && e.length !== 0); - const MsgNodeList: Promise[] = []; - for (const sendElementsSplitElement of AllElement) { - MsgNodeList.push(sendMsg(selfPeer, sendElementsSplitElement, [], true).catch(e => new Promise((resolve, reject) => { resolve(undefined) }))); - } - (await Promise.allSettled(MsgNodeList)).map((result) => { - if (result.status === 'fulfilled' && result.value) { - nodeMsgIds.push(result.value.msgId); - MessageUnique.createMsg(selfPeer, result.value.msgId); - } - }); - } catch (e) { - logDebug('生成转发消息节点失败', e); - } - } - } - const nodeMsgArray: Array = []; - let srcPeer: Peer | undefined = undefined; - let needSendSelf = false; - //检测是否处于同一个Peer 不在同一个peer则全部消息由自身发送 - for (let msgId of nodeMsgIds) { - const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId); - if (!nodeMsgPeer) { - logError('转发消息失败,未找到消息', msgId); - continue; - } - const nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0]; - srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid }; - if (srcPeer.peerUid !== nodeMsg.peerUid) { - needSendSelf = true; - } - nodeMsgArray.push(nodeMsg); - } - nodeMsgIds = nodeMsgArray.map(msg => msg.msgId); - let retMsgIds: string[] = []; - if (needSendSelf) { - for (const [index, msg] of nodeMsgArray.entries()) { - if (msg.peerUid === selfInfo.uid) continue; - const ClonedMsg = await cloneMsg(msg); - if (ClonedMsg) retMsgIds.push(ClonedMsg.msgId); - } - } else { - retMsgIds = nodeMsgIds; - } - if (nodeMsgIds.length === 0) throw Error('转发消息失败,生成节点为空'); - try { - logDebug('开发转发', srcPeer, destPeer, nodeMsgIds); - return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, nodeMsgIds); - } catch (e) { - logError('forward failed', e); - return null; - } -} diff --git a/src/onebot11/action/msg/SendMsg/index.ts b/src/onebot11/action/msg/SendMsg/index.ts deleted file mode 100644 index 94255d01..00000000 --- a/src/onebot11/action/msg/SendMsg/index.ts +++ /dev/null @@ -1,166 +0,0 @@ -import BaseAction from '@/onebot11/action/BaseAction'; -import { - OB11MessageData, - OB11MessageDataType, - OB11MessageMixType, - OB11MessageNode, - OB11PostSendMsg -} from '@/onebot11/types'; -import { ActionName, BaseCheckResult } from '@/onebot11/action/types'; -import { getGroup } from '@/core/data'; -import { ChatType, ElementType, Group, NTQQFileApi, NTQQFriendApi, NTQQMsgApi, NTQQUserApi, Peer, SendMessageElement, } from '@/core'; -import fs from 'node:fs'; -import fsPromise from 'node:fs/promises'; -import { logDebug, logError } from '@/common/utils/log'; -import { decodeCQCode } from '@/onebot11/cqcode'; -import createSendElements from './create-send-elements'; -import { handleForwardNode } from '@/onebot11/action/msg/SendMsg/handle-forward-node'; -import { MessageUnique } from '@/common/utils/MessageUnique'; - -export interface ReturnDataType { - message_id: number; -} -export enum ContextMode { - Normal = 0, - Private = 1, - Group = 2 -} -// Normalizes a mixed type (CQCode/a single segment/segment array) into a segment array. -export function normalize(message: OB11MessageMixType, autoEscape = false): OB11MessageData[] { - return typeof message === 'string' ? ( - autoEscape ? - [{ type: OB11MessageDataType.text, data: { text: message } }] : - decodeCQCode(message) - ) : Array.isArray(message) ? message : [message]; -} - -export { createSendElements }; - -export async function sendMsg(peer: Peer, sendElements: SendMessageElement[], deleteAfterSentFiles: string[], waitComplete = true) { - if (!sendElements.length) { - throw ('消息体无法解析, 请检查是否发送了不支持的消息类型'); - } - let totalSize = 0; - let timeout = 10000; - try { - for (const fileElement of sendElements) { - if (fileElement.elementType === ElementType.PTT) { - totalSize += fs.statSync(fileElement.pttElement.filePath).size; - } - if (fileElement.elementType === ElementType.FILE) { - totalSize += fs.statSync(fileElement.fileElement.filePath).size; - } - if (fileElement.elementType === ElementType.VIDEO) { - totalSize += fs.statSync(fileElement.videoElement.filePath).size; - } - if (fileElement.elementType === ElementType.PIC) { - totalSize += fs.statSync(fileElement.picElement.sourcePath).size; - } - } - //且 PredictTime ((totalSize / 1024 / 512) * 1000)不等于Nan - const PredictTime = totalSize / 1024 / 256 * 1000; - if (!Number.isNaN(PredictTime)) { - timeout += PredictTime;// 10S Basic Timeout + PredictTime( For File 512kb/s ) - } - } catch (e) { - logError('发送消息计算预计时间异常', e); - } - const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, timeout); - try { - returnMsg!.id = await MessageUnique.createMsg({ chatType: peer.chatType, guildId: '', peerUid: peer.peerUid }, returnMsg!.msgId); - } catch (e: any) { - logDebug('发送消息id获取失败', e); - returnMsg!.id = 0; - } - deleteAfterSentFiles.map((f) => { fsPromise.unlink(f).then().catch(e => logError('发送消息删除文件失败', e)); }); - return returnMsg; -} - -async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode): Promise { - // This function determines the type of message by the existence of user_id / group_id, - // not message_type. - // This redundant design of Ob11 here should be blamed. - - if ((contextMode === ContextMode.Group || contextMode === ContextMode.Normal) && payload.group_id) { - const group = (await getGroup(payload.group_id))!; // checked before - return { - chatType: ChatType.group, - peerUid: group.groupCode - }; - } - if ((contextMode === ContextMode.Private || contextMode === ContextMode.Normal) && payload.user_id) { - const Uid = await NTQQUserApi.getUidByUin(payload.user_id.toString()); - const isBuddy = await NTQQFriendApi.isBuddy(Uid!); - //console.log("[调试代码] UIN:", payload.user_id, " UID:", Uid, " IsBuddy:", isBuddy); - return { - chatType: isBuddy ? ChatType.friend : ChatType.temp, - peerUid: Uid! - }; - } - throw '请指定 group_id 或 user_id'; -} - -function getSpecialMsgNum(payload: OB11PostSendMsg, msgType: OB11MessageDataType): number { - if (Array.isArray(payload.message)) { - return payload.message.filter(msg => msg.type == msgType).length; - } - return 0; -} - -export class SendMsg extends BaseAction { - actionName = ActionName.SendMsg; - contextMode = ContextMode.Normal; - - protected async check(payload: OB11PostSendMsg): Promise { - const messages = normalize(payload.message); - const nodeElementLength = getSpecialMsgNum(payload, OB11MessageDataType.node); - if (nodeElementLength > 0 && nodeElementLength != messages.length) { - return { valid: false, message: '转发消息不能和普通消息混在一起发送,转发需要保证message只有type为node的元素' }; - } - if (payload.message_type !== 'private' && payload.group_id && !(await getGroup(payload.group_id))) { - return { valid: false, message: `群${payload.group_id}不存在` }; - } - if (payload.user_id && payload.message_type !== 'group') { - const uid = await NTQQUserApi.getUidByUin(payload.user_id.toString()); - const isBuddy = await NTQQFriendApi.isBuddy(uid!); - // 此处有问题 - if (!isBuddy) { - //return { valid: false, message: '异常消息' }; - } - } - return { valid: true }; - } - - protected async _handle(payload: OB11PostSendMsg): Promise<{ message_id: number }> { - const peer = await createContext(payload, this.contextMode); - - const messages = normalize( - payload.message, - payload.auto_escape === true || payload.auto_escape === 'true' - ); - - if (getSpecialMsgNum(payload, OB11MessageDataType.node)) { - const returnMsg = await handleForwardNode(peer, messages as OB11MessageNode[]); - if (returnMsg) { - const msgShortId = MessageUnique.createMsg({ guildId: '', peerUid: peer.peerUid, chatType: peer.chatType }, returnMsg!.msgId); - return { message_id: msgShortId! }; - } else { - throw Error('发送转发消息失败'); - } - } else { - // if (getSpecialMsgNum(payload, OB11MessageDataType.music)) { - // const music: OB11MessageCustomMusic = messages[0] as OB11MessageCustomMusic; - // if (music) { - // } - // } - } - // log("send msg:", peer, sendElements) - - const { sendElements, deleteAfterSentFiles } = await createSendElements(messages, peer); - //console.log(peer, JSON.stringify(sendElements,null,2)); - const returnMsg = await sendMsg(peer, sendElements, deleteAfterSentFiles); - return { message_id: returnMsg!.id! }; - } -} - -export default SendMsg; diff --git a/src/onebot11/action/msg/SendPrivateMsg.ts b/src/onebot11/action/msg/SendPrivateMsg.ts deleted file mode 100644 index 7c5cd7e3..00000000 --- a/src/onebot11/action/msg/SendPrivateMsg.ts +++ /dev/null @@ -1,15 +0,0 @@ -import SendMsg, { ContextMode } from './SendMsg'; -import { ActionName, BaseCheckResult } from '../types'; -import { OB11PostSendMsg } from '../../types'; -// 未检测参数 -class SendPrivateMsg extends SendMsg { - actionName = ActionName.SendPrivateMsg; - contextMode: ContextMode = ContextMode.Private; - - protected async check(payload: OB11PostSendMsg): Promise { - payload.message_type = 'private'; - return super.check(payload); - } -} - -export default SendPrivateMsg; diff --git a/src/onebot11/action/msg/SetMsgEmojiLike.ts b/src/onebot11/action/msg/SetMsgEmojiLike.ts deleted file mode 100644 index edb8edcc..00000000 --- a/src/onebot11/action/msg/SetMsgEmojiLike.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ActionName } from '../types'; -import BaseAction from '../BaseAction'; -import { NTQQMsgApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { MessageUnique } from '@/common/utils/MessageUnique'; - -const SchemaData = { - type: 'object', - properties: { - message_id: { type: ['string', 'number'] }, - emoji_id: { type: ['string', 'number'] } - }, - required: ['message_id', 'emoji_id'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class SetMsgEmojiLike extends BaseAction { - actionName = ActionName.SetMsgEmojiLike; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); - if (!msg) { - throw new Error('msg not found'); - } - if (!payload.emoji_id) { - throw new Error('emojiId not found'); - } - const msgData = (await NTQQMsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId])).msgList; - if (!msgData || msgData.length == 0 || !msgData[0].msgSeq) { - throw new Error('find msg by msgid error'); - } - return await NTQQMsgApi.setEmojiLike(msg.Peer, msgData[0].msgSeq, payload.emoji_id.toString(), true); - } -} diff --git a/src/onebot11/action/system/CanSendImage.ts b/src/onebot11/action/system/CanSendImage.ts deleted file mode 100644 index 459c3e66..00000000 --- a/src/onebot11/action/system/CanSendImage.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ActionName } from '../types'; -import CanSendRecord from './CanSendRecord'; - -interface ReturnType { - yes: boolean -} - -export default class CanSendImage extends CanSendRecord { - actionName = ActionName.CanSendImage; -} diff --git a/src/onebot11/action/system/CanSendRecord.ts b/src/onebot11/action/system/CanSendRecord.ts deleted file mode 100644 index 07741cfa..00000000 --- a/src/onebot11/action/system/CanSendRecord.ts +++ /dev/null @@ -1,16 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; - -interface ReturnType { - yes: boolean -} - -export default class CanSendRecord extends BaseAction { - actionName = ActionName.CanSendRecord; - - protected async _handle(_payload: void): Promise { - return { - yes: true - }; - } -} diff --git a/src/onebot11/action/system/CleanCache.ts b/src/onebot11/action/system/CleanCache.ts deleted file mode 100644 index 0e0cafc2..00000000 --- a/src/onebot11/action/system/CleanCache.ts +++ /dev/null @@ -1,93 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import fs from 'fs'; -import Path from 'path'; -import { - ChatType, - ChatCacheListItemBasic, - CacheFileType -} from '@/core/entities'; -import { NTQQFileApi, NTQQFileCacheApi } from '@/core/apis/file'; -import { logError } from '@/common/utils/log'; - -export default class CleanCache extends BaseAction { - actionName = ActionName.CleanCache; - - protected _handle(): Promise { - return new Promise(async (res, rej) => { - try { - // dbUtil.clearCache(); - const cacheFilePaths: string[] = []; - - await NTQQFileCacheApi.setCacheSilentScan(false); - - cacheFilePaths.push((await NTQQFileCacheApi.getHotUpdateCachePath())); - cacheFilePaths.push((await NTQQFileCacheApi.getDesktopTmpPath())); - (await NTQQFileCacheApi.getCacheSessionPathList()).forEach((e: { value: string; }) => cacheFilePaths.push(e.value)); - - // await NTQQApi.addCacheScannedPaths(); // XXX: 调用就崩溃,原因目前还未知 - const cacheScanResult = await NTQQFileCacheApi.scanCache(); - const cacheSize = parseInt(cacheScanResult.size[6]); - - if (cacheScanResult.result !== 0) { - throw('Something went wrong while scanning cache. Code: ' + cacheScanResult.result); - } - - await NTQQFileCacheApi.setCacheSilentScan(true); - if (cacheSize > 0 && cacheFilePaths.length > 2) { // 存在缓存文件且大小不为 0 时执行清理动作 - // await NTQQApi.clearCache([ 'tmp', 'hotUpdate', ...cacheScanResult ]) // XXX: 也是调用就崩溃,调用 fs 删除得了 - deleteCachePath(cacheFilePaths); - } - - // 获取聊天记录列表 - // NOTE: 以防有人不需要删除聊天记录,暂时先注释掉,日后加个开关 - // const privateChatCache = await getCacheList(ChatType.friend); // 私聊消息 - // const groupChatCache = await getCacheList(ChatType.group); // 群聊消息 - // const chatCacheList = [ ...privateChatCache, ...groupChatCache ]; - const chatCacheList: ChatCacheListItemBasic[] = []; - - // 获取聊天缓存文件列表 - const cacheFileList: string[] = []; - - for (const name in CacheFileType) { - if (!isNaN(parseInt(name))) continue; - - const fileTypeAny: any = CacheFileType[name]; - const fileType: CacheFileType = fileTypeAny; - - cacheFileList.push(...(await NTQQFileCacheApi.getFileCacheInfo(fileType)).infos.map((file: { fileKey: any; }) => file.fileKey)); - } - - // 一并清除 - await NTQQFileCacheApi.clearChatCache(chatCacheList, cacheFileList); - res(); - } catch(e) { - logError('清理缓存时发生了错误'); - rej(e); - } - }); - } -} - -function deleteCachePath(pathList: string[]) { - const emptyPath = (path: string) => { - if (!fs.existsSync(path)) return; - const files = fs.readdirSync(path); - files.forEach(file => { - const filePath = Path.resolve(path, file); - const stats = fs.statSync(filePath); - if (stats.isDirectory()) emptyPath(filePath); - else fs.unlinkSync(filePath); - }); - fs.rmdirSync(path); - }; - - for (const path of pathList) { - emptyPath(path); - } -} - -function getCacheList(type: ChatType) { // NOTE: 做这个方法主要是因为目前还不支持针对频道消息的清理 - return new Promise>((res, rej) => { - }); -} diff --git a/src/onebot11/action/system/GetLoginInfo.ts b/src/onebot11/action/system/GetLoginInfo.ts deleted file mode 100644 index 7d43d3b7..00000000 --- a/src/onebot11/action/system/GetLoginInfo.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { selfInfo } from '@/core/data'; -import { OB11User } from '../../types'; -import { OB11Constructor } from '../../constructor'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { napCatCore } from '@/core'; - - -class GetLoginInfo extends BaseAction { - actionName = ActionName.GetLoginInfo; - - protected async _handle(payload: null) { - return OB11Constructor.selfInfo(selfInfo); - } -} - -export default GetLoginInfo; diff --git a/src/onebot11/action/system/GetStatus.ts b/src/onebot11/action/system/GetStatus.ts deleted file mode 100644 index affbe13f..00000000 --- a/src/onebot11/action/system/GetStatus.ts +++ /dev/null @@ -1,17 +0,0 @@ -import BaseAction from '../BaseAction'; -import { OB11Status } from '../../types'; -import { ActionName } from '../types'; -import { selfInfo, stat } from '@/core/data'; - - -export default class GetStatus extends BaseAction { - actionName = ActionName.GetStatus; - - protected async _handle(payload: any): Promise { - return { - online: !!selfInfo.online, - good: true, - stat - }; - } -} diff --git a/src/onebot11/action/system/GetVersionInfo.ts b/src/onebot11/action/system/GetVersionInfo.ts deleted file mode 100644 index 330a1c59..00000000 --- a/src/onebot11/action/system/GetVersionInfo.ts +++ /dev/null @@ -1,16 +0,0 @@ -import BaseAction from '../BaseAction'; -import { OB11Version } from '../../types'; -import { ActionName } from '../types'; -import { version } from '@/onebot11/version'; - -export default class GetVersionInfo extends BaseAction { - actionName = ActionName.GetVersionInfo; - - protected async _handle(payload: any): Promise { - return { - app_name: 'NapCat.Onebot', - protocol_version: 'v11', - app_version: version - }; - } -} diff --git a/src/onebot11/action/system/Reboot.ts b/src/onebot11/action/system/Reboot.ts deleted file mode 100644 index 19d6ad9c..00000000 --- a/src/onebot11/action/system/Reboot.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { rebootWithNormolLogin, rebootWithQuickLogin } from '@/common/utils/reboot'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { selfInfo } from '@/core/data'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - delay: { type: 'number' } - } -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class Reboot extends BaseAction { - actionName = ActionName.Reboot; - - protected async _handle(payload: Payload): Promise { - if (payload.delay) { - setTimeout(() => { - rebootWithQuickLogin(selfInfo.uin); - }, payload.delay); - } else { - rebootWithQuickLogin(selfInfo.uin); - } - return null; - } -} -export class RebootNormal extends BaseAction { - actionName = ActionName.RebootNormal; - - protected async _handle(payload: Payload): Promise { - if (payload.delay) { - setTimeout(() => { - rebootWithNormolLogin(); - }, payload.delay); - } else { - rebootWithNormolLogin(); - } - return null; - } -} diff --git a/src/onebot11/action/types.ts b/src/onebot11/action/types.ts deleted file mode 100644 index 7925a944..00000000 --- a/src/onebot11/action/types.ts +++ /dev/null @@ -1,107 +0,0 @@ -export type BaseCheckResult = ValidCheckResult | InvalidCheckResult - -export interface ValidCheckResult { - valid: true - - [k: string | number]: any -} - -export interface InvalidCheckResult { - valid: false - message: string - - [k: string | number]: any -} - -export enum ActionName { - // 以下为扩展napcat扩展 - SharePeer = 'ArkShareGroup', - ShareGroupEx = 'ArkSharePeer', - RebootNormal = 'reboot_normal',//无快速登录重新启动 - GetRobotUinRange = 'get_robot_uin_range', - SetOnlineStatus = 'set_online_status', - GetFriendsWithCategory = 'get_friends_with_category', - GetGroupIgnoreAddRequest = 'get_group_ignore_add_request', - SetQQAvatar = 'set_qq_avatar', - GetConfig = 'get_config', - SetConfig = 'set_config', - Debug = 'debug', - GetFile = 'get_file', - ForwardFriendSingleMsg = 'forward_friend_single_msg', - ForwardGroupSingleMsg = 'forward_group_single_msg', - TranslateEnWordToZn = 'translate_en2zh', - GetGroupFileCount = 'get_group_file_count', - GetGroupFileList = 'get_group_file_list', - SetGroupFileFolder = 'set_group_file_folder', - DelGroupFile = 'del_group_file', - DelGroupFileFolder = 'del_group_file_folder', - // onebot 11 - Reboot = 'set_restart', - SendLike = 'send_like', - GetLoginInfo = 'get_login_info', - GetFriendList = 'get_friend_list', - GetGroupInfo = 'get_group_info', - GetGroupList = 'get_group_list', - GetGroupMemberInfo = 'get_group_member_info', - GetGroupMemberList = 'get_group_member_list', - GetMsg = 'get_msg', - SendMsg = 'send_msg', - SendGroupMsg = 'send_group_msg', - SendPrivateMsg = 'send_private_msg', - DeleteMsg = 'delete_msg', - SetMsgEmojiLike = 'set_msg_emoji_like', - SetGroupAddRequest = 'set_group_add_request', - SetFriendAddRequest = 'set_friend_add_request', - SetGroupLeave = 'set_group_leave', - GetVersionInfo = 'get_version_info', - GetStatus = 'get_status', - CanSendRecord = 'can_send_record', - CanSendImage = 'can_send_image', - SetGroupKick = 'set_group_kick', - SetGroupBan = 'set_group_ban', - SetGroupWholeBan = 'set_group_whole_ban', - SetGroupAdmin = 'set_group_admin', - SetGroupCard = 'set_group_card', - SetGroupName = 'set_group_name', - GetImage = 'get_image', - GetRecord = 'get_record', - CleanCache = 'clean_cache', - GetCookies = 'get_cookies', - // 以下为go-cqhttp api - GoCQHTTP_HandleQuickAction = '.handle_quick_operation', - GetGroupHonorInfo = 'get_group_honor_info', - GoCQHTTP_GetEssenceMsg = 'get_essence_msg_list', - GoCQHTTP_SendGroupNotice = '_send_group_notice', - GoCQHTTP_GetGroupNotice = '_get_group_notice', - GoCQHTTP_SendForwardMsg = 'send_forward_msg', - GoCQHTTP_SendGroupForwardMsg = 'send_group_forward_msg', - GoCQHTTP_SendPrivateForwardMsg = 'send_private_forward_msg', - GoCQHTTP_GetStrangerInfo = 'get_stranger_info', - GoCQHTTP_MarkMsgAsRead = 'mark_msg_as_read', - GetGuildList = 'get_guild_list', - MarkPrivateMsgAsRead = 'mark_private_msg_as_read', - MarkGroupMsgAsRead = 'mark_group_msg_as_read', - GoCQHTTP_UploadGroupFile = 'upload_group_file', - GoCQHTTP_DownloadFile = 'download_file', - GoCQHTTP_GetGroupMsgHistory = 'get_group_msg_history', - GoCQHTTP_GetForwardMsg = 'get_forward_msg', - GetFriendMsgHistory = 'get_friend_msg_history', - GetGroupSystemMsg = 'get_group_system_msg', - GetOnlineClient = 'get_online_clients', - OCRImage = 'ocr_image', - IOCRImage = '.ocr_image', - SetSelfProfile = 'set_self_profile', - CreateCollection = 'create_collection', - GetCollectionList = 'get_collection_list', - SetLongNick = 'set_self_longnick', - SetEssenceMsg = 'set_essence_msg', - DelEssenceMsg = 'delete_essence_msg', - GetRecentContact = 'get_recent_contact', - _MarkAllMsgAsRead = '_mark_all_as_read', - GetProfileLike = 'get_profile_like', - SetGroupHeader = 'set_group_head', - FetchCustomFace = 'fetch_custom_face', - GOCQHTTP_UploadPrivateFile = 'upload_private_file', - TestApi01 = 'test_api_01', - FetchEmojioLike = 'fetch_emoji_like' -} diff --git a/src/onebot11/action/user/GetCookies.ts b/src/onebot11/action/user/GetCookies.ts deleted file mode 100644 index cbd852f1..00000000 --- a/src/onebot11/action/user/GetCookies.ts +++ /dev/null @@ -1,69 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQUserApi, WebApi } from '@/core/apis'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -interface Response { - cookies: string, - bkn: string -} -const SchemaData = { - type: 'object', - properties: { - domain: { type: 'string' } - }, - required: ['domain'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class GetCookies extends BaseAction { - actionName = ActionName.GetCookies; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - // if (!payload.domain) { - // throw new Error('缺少参数 domain'); - // } - // if (payload.domain.endsWith('qzone.qq.com')) { - // // 兼容整个 *.qzone.qq.com - // const data = (await NTQQUserApi.getQzoneCookies()); - // const Bkn = WebApi.genBkn(data.p_skey); - // const CookieValue = 'p_skey=' + data.p_skey + '; skey=' + data.skey + '; p_uin=o' + selfInfo.uin + '; uin=o' + selfInfo.uin; - // return { cookies: CookieValue }; - // } - // // 取Skey - // // 先NodeIKernelTicketService.forceFetchClientKey('') - // // 返回值 - // // { - // // result: 0, - // // errMsg: '', - // // url: '', - // // keyIndex: '19', - // // clientKey: 'clientKey', - // // expireTime: '7200' - // // } - // // request https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=1627126029&clientkey=key - // // &u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=keyIndex - // const _PSkey = (await NTQQUserApi.getPSkey([payload.domain]))[payload.domain]; - // // 取Pskey - // // NodeIKernelTipOffService.getPskey([ 'qun.qq.com' ], true ) - // // { - // // domainPskeyMap: 0, - // // errMsg: 'success', - // // domainPskeyMap: Map(1) { - // // 'qun.qq.com' => 'pskey' - // // } - // // } - // if (!_PSkey || !_Skey) { - // throw new Error('获取Cookies失败'); - // } - // const cookies = `p_skey=${_PSkey}; skey=${_Skey}; p_uin=o${selfInfo.uin}; uin=o${selfInfo.uin}`; - // return { - // cookies - // }; - const cookiesObject = await NTQQUserApi.getCookies(payload.domain); - //把获取到的cookiesObject转换成 k=v; 格式字符串拼接在一起 - const cookies = Object.entries(cookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const bkn = WebApi.genBkn(cookiesObject.p_skey); - return { cookies, bkn }; - } -} diff --git a/src/onebot11/action/user/GetFriendList.ts b/src/onebot11/action/user/GetFriendList.ts deleted file mode 100644 index e72eaa31..00000000 --- a/src/onebot11/action/user/GetFriendList.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { OB11User } from '../../types'; -import { OB11Constructor } from '../../constructor'; -import { friends } from '@/core/data'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQFriendApi } from '@/core'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo'; - - -// no_cache get时传字符串 -const SchemaData = { - type: 'object', - properties: { - no_cache: { type: ['boolean', 'string'] }, - } -} as const satisfies JSONSchema; - -type Payload = FromSchema; -export default class GetFriendList extends BaseAction { - actionName = ActionName.GetFriendList; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - if (requireMinNTQQBuild('26702')) { - //全新逻辑 - return OB11Constructor.friendsV2(await NTQQFriendApi.getBuddyV2(payload?.no_cache === true || payload?.no_cache === 'true')); - } - if (friends.size === 0 || payload?.no_cache === true || payload?.no_cache === 'true') { - const _friends = await NTQQFriendApi.getFriends(true); - // log('强制刷新好友列表,结果: ', _friends) - if (_friends.length > 0) { - friends.clear(); - for (const friend of _friends) { - friends.set(friend.uid, friend); - } - } - } - return OB11Constructor.friends(Array.from(friends.values())); - } -} diff --git a/src/onebot11/action/user/GetRecentContact.ts b/src/onebot11/action/user/GetRecentContact.ts deleted file mode 100644 index 9132d244..00000000 --- a/src/onebot11/action/user/GetRecentContact.ts +++ /dev/null @@ -1,52 +0,0 @@ - -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQMsgApi, NTQQUserApi } from '@/core'; -import { OB11Constructor } from '@/onebot11/constructor'; - -const SchemaData = { - type: 'object', - properties: { - count: { type: ['number', 'string'] } - } -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class GetRecentContact extends BaseAction { - actionName = ActionName.GetRecentContact; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload) { - const ret = await NTQQUserApi.getRecentContactListSnapShot(parseInt((payload.count || 10).toString())); - const data = await Promise.all(ret.info.changedList.map(async (t) => { - const FastMsg = await NTQQMsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]); - if (FastMsg.msgList.length > 0) { - //扩展ret.info.changedList - const lastestMsg = await OB11Constructor.message(FastMsg.msgList[0]); - return { - lastestMsg: lastestMsg, - peerUin: t.peerUin, - remark: t.remark, - msgTime: t.msgTime, - chatType: t.chatType, - msgId: t.msgId, - sendNickName: t.sendNickName, - sendMemberName: t.sendMemberName, - peerName: t.peerName - }; - } - return { - peerUin: t.peerUin, - remark: t.remark, - msgTime: t.msgTime, - chatType: t.chatType, - msgId: t.msgId, - sendNickName: t.sendNickName, - sendMemberName: t.sendMemberName, - peerName: t.peerName - }; - })); - return data; - } -} diff --git a/src/onebot11/action/user/SendLike.ts b/src/onebot11/action/user/SendLike.ts deleted file mode 100644 index a3197523..00000000 --- a/src/onebot11/action/user/SendLike.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { NTQQUserApi } from '@/core/apis'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - user_id: { type: ['number', 'string'] }, - times: { type: ['number', 'string'] } - }, - required: ['user_id', 'times'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class SendLike extends BaseAction { - actionName = ActionName.SendLike; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - //logDebug('点赞参数', payload); - try { - const qq = payload.user_id.toString(); - const uid: string = await NTQQUserApi.getUidByUin(qq) || ''; - const result = await NTQQUserApi.like(uid, parseInt(payload.times?.toString()) || 1); - //logDebug('点赞结果', result); - if (result.result !== 0) { - throw Error(result.errMsg); - } - } catch (e) { - throw `点赞失败 ${e}`; - } - return null; - } -} diff --git a/src/onebot11/action/user/SetFriendAddRequest.ts b/src/onebot11/action/user/SetFriendAddRequest.ts deleted file mode 100644 index 1befb65a..00000000 --- a/src/onebot11/action/user/SetFriendAddRequest.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { NTQQFriendApi } from '@/core/apis/friend'; - -const SchemaData = { - type: 'object', - properties: { - flag: { type: 'string' }, - approve: { type: ['string', 'boolean'] }, - remark: { type: 'string' } - }, - required: ['flag'] -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export default class SetFriendAddRequest extends BaseAction { - actionName = ActionName.SetFriendAddRequest; - PayloadSchema = SchemaData; - protected async _handle(payload: Payload): Promise { - const approve = payload.approve?.toString() !== 'false'; - await NTQQFriendApi.handleFriendRequest(payload.flag, approve); - return null; - } -} diff --git a/src/onebot11/config.ts b/src/onebot11/config.ts deleted file mode 100644 index 9ff7b4e9..00000000 --- a/src/onebot11/config.ts +++ /dev/null @@ -1,81 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import { selfInfo } from '@/core/data'; -import { logDebug, logError } from '@/common/utils/log'; -import { ConfigBase } from '@/common/utils/ConfigBase'; -import { json } from 'stream/consumers'; - -export interface OB11Config { - http: { - enable: boolean; - host: string; - port: number; - secret: string; - enableHeart: boolean; - enablePost: boolean; - postUrls: string[]; - }; - ws: { - enable: boolean; - host: string; - port: number; - }; - reverseWs: { - enable: boolean; - urls: string[]; - }; - - debug: boolean; - heartInterval: number; - messagePostFormat: 'array' | 'string'; - enableLocalFile2Url: boolean; - musicSignUrl: string; - reportSelfMessage: boolean; - token: string; - GroupLocalTime: { - Record: boolean, - RecordList: Array - }, - read(): OB11Config; - - save(config: OB11Config): void; -} - -class Config extends ConfigBase implements OB11Config { - name: string = 'onebot11'; - http = { - enable: false, - host: '', - port: 3000, - secret: '', - enableHeart: false, - enablePost: false, - postUrls: [], - }; - ws = { - enable: false, - host: '', - port: 3001, - }; - reverseWs = { - enable: false, - urls: [], - }; - debug = false; - heartInterval = 30000; - messagePostFormat: 'array' | 'string' = 'array'; - enableLocalFile2Url = true; - musicSignUrl = ''; - reportSelfMessage = false; - token = ''; - GroupLocalTime = { - Record: false, - RecordList: [] as Array - }; - - protected getKeys(): string[] | null { - return null; - } -} - -export const ob11Config = new Config(); diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts deleted file mode 100644 index 1a2479df..00000000 --- a/src/onebot11/constructor.ts +++ /dev/null @@ -1,685 +0,0 @@ -import fastXmlParser, { XMLParser } from 'fast-xml-parser'; -import { - OB11Group, - OB11GroupMember, - OB11GroupMemberRole, - OB11Message, - OB11MessageData, - OB11MessageDataType, - OB11User, - OB11UserSex -} from './types'; -import { - AtType, - ChatType, - FaceIndex, - Friend, - FriendV2, - GrayTipElementSubType, - Group, - GroupMember, - mFaceCache, - Peer, - RawMessage, - SelfInfo, - Sex, - SimpleInfo, - TipGroupElementType, - User, - VideoElement -} from '@/core/entities'; -import { EventType } from './event/OB11BaseEvent'; -import { encodeCQCode } from './cqcode'; -import { OB11GroupIncreaseEvent } from './event/notice/OB11GroupIncreaseEvent'; -import { OB11GroupBanEvent } from './event/notice/OB11GroupBanEvent'; -import { OB11GroupUploadNoticeEvent } from './event/notice/OB11GroupUploadNoticeEvent'; -import { OB11GroupNoticeEvent } from './event/notice/OB11GroupNoticeEvent'; - -import { calcQQLevel } from '../common/utils/qqlevel'; -import { log, logDebug, logError, logWarn } from '../common/utils/log'; -import { sleep, UUIDConverter } from '../common/utils/helper'; -import { OB11GroupTitleEvent } from './event/notice/OB11GroupTitleEvent'; -import { OB11GroupCardEvent } from './event/notice/OB11GroupCardEvent'; -import { OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent'; -import { ob11Config } from '@/onebot11/config'; -import { deleteGroup, getGroupMember, groupMembers, selfInfo, tempGroupCodeMap } from '@/core/data'; -import { NTQQFileApi, NTQQGroupApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis'; -import { OB11GroupMsgEmojiLikeEvent } from '@/onebot11/event/notice/OB11MsgEmojiLikeEvent'; -import { OB11FriendPokeEvent, OB11GroupPokeEvent } from './event/notice/OB11PokeEvent'; -import { OB11FriendAddNoticeEvent } from './event/notice/OB11FriendAddNoticeEvent'; -import { OB11BaseNoticeEvent } from './event/notice/OB11BaseNoticeEvent'; -import { OB11GroupEssenceEvent } from './event/notice/OB11GroupEssenceEvent'; -import { MessageUnique } from '@/common/utils/MessageUnique'; - - -export class OB11Constructor { - static async message(msg: RawMessage): Promise { - const { messagePostFormat } = ob11Config; - const message_type = msg.chatType == ChatType.group ? 'group' : 'private'; - const resMsg: OB11Message = { - self_id: parseInt(selfInfo.uin), - user_id: parseInt(msg.senderUin!), - time: parseInt(msg.msgTime) || Date.now(), - message_id: msg.id!, - message_seq: msg.id!, - real_id: msg.id!, - message_type: msg.chatType == ChatType.group ? 'group' : 'private', - sender: { - user_id: parseInt(msg.senderUin || '0'), - nickname: msg.sendNickName, - card: msg.sendMemberName || '', - }, - raw_message: '', - font: 14, - sub_type: 'friend', - message: messagePostFormat === 'string' ? '' : [], - message_format: messagePostFormat === 'string' ? 'string' : 'array', - post_type: selfInfo.uin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE, - }; - if (msg.chatType == ChatType.group) { - resMsg.sub_type = 'normal'; // 这里go-cqhttp是group,而onebot11标准是normal, 蛋疼 - resMsg.group_id = parseInt(msg.peerUin); - let member = await getGroupMember(msg.peerUin, msg.senderUin!); - if (!member) { - //直接去QQNative取 - const memberList = await NTQQGroupApi.getGroupMembers(msg.peerUin); - member = memberList.get(msg.senderUin!); - } - if (member) { - resMsg.sender.role = OB11Constructor.groupMemberRole(member.role); - resMsg.sender.nickname = member.nick; - } - } - else if (msg.chatType == ChatType.friend) { - resMsg.sub_type = 'friend'; - resMsg.sender.nickname = (await NTQQUserApi.getUserDetailInfo(msg.senderUid)).nick; - //const user = await NTQQUserApi.getUserDetailInfoByUin(msg.senderUin!); - //resMsg.sender.nickname = user.info.nick; - } - else if (msg.chatType == ChatType.temp) { - resMsg.sub_type = 'group'; - const tempGroupCode = tempGroupCodeMap[msg.peerUin]; - if (tempGroupCode) { - resMsg.group_id = parseInt(tempGroupCode); - } - } - for (const element of msg.elements) { - let message_data: OB11MessageData = { - data: {} as any, - type: 'unknown' as any - }; - if (element.textElement && element.textElement?.atType !== AtType.notAt) { - let qq: `${number}` | 'all'; - let name: string | undefined; - if (element.textElement.atType == AtType.atAll) { - qq = 'all'; - } - else { - const { atNtUid, content } = element.textElement; - let atQQ = element.textElement.atUid; - if (!atQQ || atQQ === '0') { - const atMember = await getGroupMember(msg.peerUin, atNtUid); - if (atMember) { - atQQ = atMember.uin; - } - } - if (atQQ) { - qq = atQQ as `${number}`; - name = content.replace('@', ''); - } - } - message_data = { - type: OB11MessageDataType.at, - data: { - qq: qq!, - name - } - }; - } - else if (element.textElement) { - message_data['type'] = OB11MessageDataType.text; - - let text = element.textElement.content; - if (!text.trim()) { - continue; - } - // 兼容 9.7.x 换行符 - if (text.indexOf('\n') === -1 && text.indexOf('\r\n') === -1) { - text = text.replace(/\r/g, '\n'); - } - message_data['data']['text'] = text; - } - else if (element.replyElement) { - message_data['type'] = OB11MessageDataType.reply; - //log("收到回复消息", element.replyElement); - try { - const records = msg.records.find(msgRecord => msgRecord.msgId === element.replyElement.sourceMsgIdInRecords); - const peer = { - chatType: msg.chatType, - peerUid: msg.peerUid, - guildId: '', - }; - let replyMsg: RawMessage | undefined; - if (!records) throw new Error('找不到回复消息'); - replyMsg = (await NTQQMsgApi.getMsgsBySeqAndCount({ peerUid: msg.peerUid, guildId: '', chatType: msg.chatType }, element.replyElement.replayMsgSeq, 1, true, true)).msgList[0]; - if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) { - replyMsg = (await NTQQMsgApi.getSingleMsg(peer, element.replyElement.replayMsgSeq)).msgList[0]; - } - if (msg.peerUin == '284840486') { - //合并消息内侧 消息具体定位不到 - } - if ((!replyMsg || records.msgRandom !== replyMsg.msgRandom) && msg.peerUin !== '284840486') { - throw new Error('回复消息消息验证失败'); - } - message_data['data']['id'] = MessageUnique.createMsg({ peerUid: msg.peerUid, guildId: '', chatType: msg.chatType }, replyMsg.msgId)?.toString(); - //log("找到回复消息", message_data['data']['id'], replyMsg.msgList[0].msgId) - } catch (e: any) { - message_data['type'] = 'unknown' as any; - message_data['data'] = undefined; - logError('获取不到引用的消息', e.stack, element.replyElement.replayMsgSeq); - } - - } - else if (element.picElement) { - message_data['type'] = OB11MessageDataType.image; - // message_data["data"]["file"] = element.picElement.sourcePath - message_data['data']['file'] = element.picElement.fileName; - message_data['data']['subType'] = element.picElement.picSubType; - message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId); - // message_data["data"]["path"] = element.picElement.sourcePath - - try { - message_data['data']['url'] = await NTQQFileApi.getImageUrl(element.picElement); - } catch (e: any) { - logError('获取图片url失败', e.stack); - } - //console.log(message_data['data']['url']) - // message_data["data"]["file_id"] = element.picElement.fileUuid - message_data['data']['file_size'] = element.picElement.fileSize; - } - else if (element.fileElement) { - const FileElement = element.fileElement; - message_data['type'] = OB11MessageDataType.file; - message_data['data']['file'] = FileElement.fileName; - message_data['data']['path'] = FileElement.filePath; - message_data['data']['url'] = FileElement.filePath; - message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId); - message_data['data']['file_size'] = FileElement.fileSize; - await NTQQFileApi.addFileCache({ - peerUid: msg.peerUid, - chatType: msg.chatType, - guildId: '', - }, - msg.msgId, - msg.msgSeq, - msg.senderUid, - element.elementId, - element.elementType.toString(), - FileElement.fileSize, - FileElement.fileName - ); - } - else if (element.videoElement) { - const videoElement: VideoElement = element.videoElement; - //读取视频链接并兜底 - let videoUrl;//Array - if (msg.peerUin = '284840486') { - //合并消息内部 应该进行特殊处理 可能需要重写peer 待测试与研究 Mlikiowa Taged TODO - } - try { - - videoUrl = await NTQQFileApi.getVideoUrl({ - chatType: msg.chatType, - peerUid: msg.peerUid, - guildId: '0' - }, msg.msgId, element.elementId); - } catch (error) { - videoUrl = undefined; - } - //读取在线URL - let videoDownUrl = undefined; - - if (videoUrl) { - const videoDownUrlTemp = videoUrl.find((url) => { if (url.url) { return true; } return false; }); - if (videoDownUrlTemp) { - videoDownUrl = videoDownUrlTemp.url; - } - } - //开始兜底 - if (!videoDownUrl) { - videoDownUrl = videoElement.filePath; - } - message_data['type'] = OB11MessageDataType.video; - message_data['data']['file'] = videoElement.fileName; - message_data['data']['path'] = videoDownUrl; - message_data['data']['url'] = videoDownUrl; - message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId); - message_data['data']['file_size'] = videoElement.fileSize; - - await NTQQFileApi.addFileCache({ - peerUid: msg.peerUid, - chatType: msg.chatType, - guildId: '', - }, - msg.msgId, - msg.msgSeq, - msg.senderUid, - element.elementId, - element.elementType.toString(), - videoElement.fileSize || '0', - videoElement.fileName - ); - } - else if (element.pttElement) { - message_data['type'] = OB11MessageDataType.voice; - message_data['data']['file'] = element.pttElement.fileName; - message_data['data']['path'] = element.pttElement.filePath; - //message_data['data']['file_id'] = element.pttElement.fileUuid; - message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId); - message_data['data']['file_size'] = element.pttElement.fileSize; - await NTQQFileApi.addFileCache({ - peerUid: msg.peerUid, - chatType: msg.chatType, - guildId: '', - }, - msg.msgId, - msg.msgSeq, - msg.senderUid, - element.elementId, - element.elementType.toString(), - element.pttElement.fileSize || '0', - element.pttElement.fileUuid || '' - ); - //以uuid作为文件名 - } - else if (element.arkElement) { - message_data['type'] = OB11MessageDataType.json; - message_data['data']['data'] = element.arkElement.bytesData; - } - else if (element.faceElement) { - const faceId = element.faceElement.faceIndex; - if (faceId === FaceIndex.dice) { - message_data['type'] = OB11MessageDataType.dice; - message_data['data']['result'] = element.faceElement.resultId; - } - else if (faceId === FaceIndex.RPS) { - message_data['type'] = OB11MessageDataType.RPS; - message_data['data']['result'] = element.faceElement.resultId; - } - else { - message_data['type'] = OB11MessageDataType.face; - message_data['data']['id'] = element.faceElement.faceIndex.toString(); - } - } - else if (element.marketFaceElement) { - message_data['type'] = OB11MessageDataType.mface; - message_data['data']['summary'] = element.marketFaceElement.faceName; - const md5 = element.marketFaceElement.emojiId; - // 取md5的前两位 - const dir = md5.substring(0, 2); - // 获取组装url - // const url = `https://p.qpic.cn/CDN_STATIC/0/data/imgcache/htdocs/club/item/parcel/item/${dir}/${md5}/300x300.gif?max_age=31536000`; - const url = `https://gxh.vip.qq.com/club/item/parcel/item/${dir}/${md5}/raw300.gif`; - message_data['data']['url'] = url; - message_data['data']['emoji_id'] = element.marketFaceElement.emojiId; - message_data['data']['emoji_package_id'] = String(element.marketFaceElement.emojiPackageId); - message_data['data']['key'] = element.marketFaceElement.key; - mFaceCache.set(md5, element.marketFaceElement.faceName); - } - else if (element.markdownElement) { - message_data['type'] = OB11MessageDataType.markdown; - message_data['data']['data'] = element.markdownElement.content; - } - else if (element.multiForwardMsgElement) { - message_data['type'] = OB11MessageDataType.forward; - message_data['data']['id'] = msg.msgId; - const ParentMsgPeer = msg.parentMsgPeer ?? { chatType: msg.chatType, guildId: '', peerUid: msg.peerUid }; - //判断是否在合并消息内 - msg.parentMsgIdList = msg.parentMsgIdList ?? []; - //首次列表不存在则开始创建 - msg.parentMsgIdList.push(msg.msgId); - //let parentMsgId = msg.parentMsgIdList[msg.parentMsgIdList.length - 2 < 0 ? 0 : msg.parentMsgIdList.length - 2]; - //加入自身MsgId - let MultiMsgs = (await NTQQMsgApi.getMultiMsg(ParentMsgPeer, msg.parentMsgIdList[0], msg.msgId))?.msgList; - //拉取下级消息 - if (!MultiMsgs) continue; - //拉取失败则跳过 - message_data['data']['content'] = []; - for (let MultiMsg of MultiMsgs) { - //对每条拉取的消息传递ParentMsgPeer修正Peer - MultiMsg.parentMsgPeer = ParentMsgPeer; - MultiMsg.parentMsgIdList = msg.parentMsgIdList; - MultiMsg.id = MessageUnique.createMsg(ParentMsgPeer, MultiMsg.msgId);//该ID仅用查看 无法调用 - let msgList = await OB11Constructor.message(MultiMsg); - message_data['data']['content'].push(msgList); - //console.log("合并消息", msgList); - } - } - if ((message_data.type as string) !== 'unknown' && message_data.data) { - const cqCode = encodeCQCode(message_data); - - if (messagePostFormat === 'string') { - (resMsg.message as string) += cqCode; - } - else (resMsg.message as OB11MessageData[]).push(message_data); - resMsg.raw_message += cqCode; - } - - } - resMsg.raw_message = resMsg.raw_message.trim(); - return resMsg; - } - static async PrivateEvent(msg: RawMessage): Promise { - if (msg.chatType !== ChatType.friend) { - return; - } - for (const element of msg.elements) { - if (element.grayTipElement) { - if (element.grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) { - const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr); - - if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) { - //判断业务类型 - //Poke事件 - let pokedetail: any[] = json.items; - //筛选item带有uid的元素 - pokedetail = pokedetail.filter(item => item.uid); - //console.log("[NapCat] 群拍一拍 群:", pokedetail, parseInt(msg.peerUid), " ", await NTQQUserApi.getUinByUid(pokedetail[0].uid), "拍了拍", await NTQQUserApi.getUinByUid(pokedetail[1].uid)); - if (pokedetail.length == 2) { - return new OB11FriendPokeEvent(parseInt((await NTQQUserApi.getUinByUid(pokedetail[0].uid))!), parseInt((await NTQQUserApi.getUinByUid(pokedetail[1].uid))!), pokedetail); - } - } - //下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE - } - if (element.grayTipElement.subElementType == GrayTipElementSubType.INVITE_NEW_MEMBER) { - //好友添加成功事件 - if (element.grayTipElement.xmlElement.templId === '10229' && msg.peerUin !== '') { - return new OB11FriendAddNoticeEvent(parseInt(msg.peerUin)); - } - } - } - } - } - static async GroupEvent(msg: RawMessage): Promise { - if (msg.chatType !== ChatType.group) { - return; - } - //log("group msg", msg); - if (msg.senderUin && msg.senderUin !== '0') { - const member = await getGroupMember(msg.peerUid, msg.senderUin); - if (member && member.cardName !== msg.sendMemberName) { - const newCardName = msg.sendMemberName || ''; - const event = new OB11GroupCardEvent(parseInt(msg.peerUid), parseInt(msg.senderUin), newCardName, member.cardName); - member.cardName = newCardName; - return event; - } - } - - for (const element of msg.elements) { - const grayTipElement = element.grayTipElement; - const groupElement = grayTipElement?.groupElement; - if (groupElement) { - // log("收到群提示消息", groupElement) - if (groupElement.type == TipGroupElementType.memberIncrease) { - logDebug('收到群成员增加消息', groupElement); - await sleep(1000); - const member = await getGroupMember(msg.peerUid, groupElement.memberUid); - const memberUin = member?.uin; - // if (!memberUin) { - // memberUin = (await NTQQUserApi.getUserDetailInfo(groupElement.memberUid)).uin - // } - // log("获取新群成员QQ", memberUin) - const adminMember = await getGroupMember(msg.peerUid, groupElement.adminUid); - // log("获取同意新成员入群的管理员", adminMember) - if (memberUin) { - const operatorUin = adminMember?.uin || memberUin; - const event = new OB11GroupIncreaseEvent(parseInt(msg.peerUid), parseInt(memberUin), parseInt(operatorUin)); - // log("构造群增加事件", event) - return event; - } - } - else if (groupElement.type === TipGroupElementType.ban) { - logDebug('收到群群员禁言提示', groupElement); - const memberUid = groupElement.shutUp!.member.uid; - const adminUid = groupElement.shutUp!.admin.uid; - let memberUin: string = ''; - let duration = parseInt(groupElement.shutUp!.duration); - const sub_type: 'ban' | 'lift_ban' = duration > 0 ? 'ban' : 'lift_ban'; - // log('OB11被禁言事件', adminUid); - if (memberUid) { - memberUin = (await getGroupMember(msg.peerUid, memberUid))?.uin || ''; // || (await NTQQUserApi.getUserDetailInfo(memberUid))?.uin - } - else { - memberUin = '0'; // 0表示全员禁言 - if (duration > 0) { - duration = -1; - } - } - const adminUin = (await getGroupMember(msg.peerUid, adminUid))?.uin; // || (await NTQQUserApi.getUserDetailInfo(adminUid))?.uin - // log('OB11被禁言事件', memberUin, adminUin, duration, sub_type); - if (memberUin && adminUin) { - const event = new OB11GroupBanEvent(parseInt(msg.peerUid), parseInt(memberUin), parseInt(adminUin), duration, sub_type); - return event; - } - } - else if (groupElement.type == TipGroupElementType.kicked) { - logDebug(`收到我被踢出或退群提示, 群${msg.peerUid}`, groupElement); - deleteGroup(msg.peerUid); - NTQQGroupApi.quitGroup(msg.peerUid).then(); - try { - const adminUin = (await getGroupMember(msg.peerUid, groupElement.adminUid))?.uin || (await NTQQUserApi.getUidByUin(groupElement.adminUid)); - if (adminUin) { - return new OB11GroupDecreaseEvent(parseInt(msg.peerUid), parseInt(selfInfo.uin), parseInt(adminUin), 'kick_me'); - } - } catch (e) { - return new OB11GroupDecreaseEvent(parseInt(msg.peerUid), parseInt(selfInfo.uin), 0, 'leave'); - } - } - } - else if (element.fileElement) { - return new OB11GroupUploadNoticeEvent(parseInt(msg.peerUid), parseInt(msg.senderUin || ''), { - id: element.fileElement.fileUuid!, - name: element.fileElement.fileName, - size: parseInt(element.fileElement.fileSize), - busid: element.fileElement.fileBizId || 0 - }); - } - if (grayTipElement) { - //console.log('收到群提示消息', grayTipElement); - if (grayTipElement.xmlElement?.templId === '10382') { - const emojiLikeData = new fastXmlParser.XMLParser({ - ignoreAttributes: false, - attributeNamePrefix: '' - }).parse(grayTipElement.xmlElement.content); - logDebug('收到表情回应我的消息', emojiLikeData); - try { - const senderUin = emojiLikeData.gtip.qq.jp; - const msgSeq = emojiLikeData.gtip.url.msgseq; - const emojiId = emojiLikeData.gtip.face.id; - - const replyMsgList = (await NTQQMsgApi.getMsgsBySeqAndCount({ chatType: ChatType.group, guildId: '', peerUid: msg.peerUid }, msgSeq, 1, true, true)).msgList; - if (replyMsgList.length < 1) { - return; - } - console.log('表情回应消息', msgSeq, " 结算ID", replyMsgList[0].msgId); - const replyMsg = replyMsgList[0]; - return new OB11GroupMsgEmojiLikeEvent(parseInt(msg.peerUid), parseInt(senderUin), MessageUnique.getShortIdByMsgId(replyMsg?.msgId!)!, [{ - emoji_id: emojiId, - count: 1 - }]); - } catch (e: any) { - logError('解析表情回应消息失败', e.stack); - } - } - if (grayTipElement.subElementType == GrayTipElementSubType.INVITE_NEW_MEMBER) { - logDebug('收到新人被邀请进群消息', grayTipElement); - const xmlElement = grayTipElement.xmlElement; - if (xmlElement?.content) { - const regex = /jp="(\d+)"/g; - - const matches = []; - let match = null; - - while ((match = regex.exec(xmlElement.content)) !== null) { - matches.push(match[1]); - } - // log("新人进群匹配到的QQ号", matches) - if (matches.length === 2) { - const [inviter, invitee] = matches; - return new OB11GroupIncreaseEvent(parseInt(msg.peerUid), parseInt(invitee), parseInt(inviter), 'invite'); - } - } - } - //代码歧义 GrayTipElementSubType.MEMBER_NEW_TITLE - else if (grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) { - const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr); - if (grayTipElement.jsonGrayTipElement.busiId == 1061) { - //判断业务类型 - //Poke事件 - const pokedetail: any[] = json.items; - //筛选item带有uid的元素 - const poke_uid = pokedetail.filter(item => item.uid); - if (poke_uid.length == 2) { - return new OB11GroupPokeEvent(parseInt(msg.peerUid), parseInt((await NTQQUserApi.getUinByUid(poke_uid[0].uid))!), parseInt((await NTQQUserApi.getUinByUid(poke_uid[1].uid))!), pokedetail); - } - } - if (grayTipElement.jsonGrayTipElement.busiId == 2401) { - const searchParams = new URL(json.items[0].jp).searchParams; - const msgSeq = searchParams.get('msgSeq')!; - const Group = searchParams.get('groupCode'); - const Businessid = searchParams.get('businessid'); - const Peer: Peer = { - guildId: '', - chatType: ChatType.group, - peerUid: Group! - }; - const msgData = await NTQQMsgApi.getMsgsBySeqAndCount(Peer, msgSeq.toString(), 1, true, true); - return new OB11GroupEssenceEvent(parseInt(msg.peerUid), MessageUnique.getShortIdByMsgId(msgData.msgList[0].msgId)!, parseInt(msgData.msgList[0].senderUin)); - // 获取MsgSeq+Peer可获取具体消息 - } - if (grayTipElement.jsonGrayTipElement.busiId == 2407) { - //下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE - const memberUin = json.items[1].param[0]; - const title = json.items[3].txt; - logDebug('收到群成员新头衔消息', json); - return new OB11GroupTitleEvent(parseInt(msg.peerUid), parseInt(memberUin), title); - } - } - } - } - } - static friend(friend: User): OB11User { - return { - user_id: parseInt(friend.uin), - nickname: friend.nick, - remark: friend.remark, - sex: OB11Constructor.sex(friend.sex!), - level: friend.qqLevel && calcQQLevel(friend.qqLevel) || 0 - }; - } - - static selfInfo(selfInfo: SelfInfo): OB11User { - return { - user_id: parseInt(selfInfo.uin), - nickname: selfInfo.nick, - }; - } - static friendsV2(friends: FriendV2[]): OB11User[] { - const data: OB11User[] = []; - friends.forEach(friend => { - const sexValue = this.sex(friend.baseInfo.sex!); - data.push({ - ...friend.baseInfo, - ...friend.coreInfo, - user_id: parseInt(friend.coreInfo.uin), - nickname: friend.coreInfo.nick, - remark: friend.coreInfo.nick, - sex: sexValue, - level: 0, - categroyName: friend.categroyName, - categoryId: friend.categoryId - }); - }); - return data; - } - static friends(friends: Friend[]): OB11User[] { - const data: OB11User[] = []; - friends.forEach(friend => { - const sexValue = this.sex(friend.sex!); - data.push({ user_id: parseInt(friend.uin), nickname: friend.nick, remark: friend.remark, sex: sexValue, level: 0 }); - }); - return data; - } - - static groupMemberRole(role: number): OB11GroupMemberRole | undefined { - return { - 4: OB11GroupMemberRole.owner, - 3: OB11GroupMemberRole.admin, - 2: OB11GroupMemberRole.member - }[role]; - } - - static sex(sex: Sex): OB11UserSex { - const sexMap = { - [Sex.male]: OB11UserSex.male, - [Sex.female]: OB11UserSex.female, - [Sex.unknown]: OB11UserSex.unknown - }; - return sexMap[sex] || OB11UserSex.unknown; - } - - static groupMember(group_id: string, member: GroupMember): OB11GroupMember { - return { - group_id: parseInt(group_id), - user_id: parseInt(member.uin), - nickname: member.nick, - card: member.cardName, - sex: OB11Constructor.sex(member.sex!), - age: 0, - area: '', - level: '0', - qq_level: member.qqLevel && calcQQLevel(member.qqLevel) || 0, - join_time: 0, // 暂时没法获取 - last_sent_time: 0, // 暂时没法获取 - title_expire_time: 0, - unfriendly: false, - card_changeable: true, - is_robot: member.isRobot, - shut_up_timestamp: member.shutUpTime, - role: OB11Constructor.groupMemberRole(member.role), - title: member.memberSpecialTitle || '', - }; - } - - static stranger(user: User): OB11User { - //logDebug('construct ob11 stranger', user); - return { - ...user, - user_id: parseInt(user.uin), - nickname: user.nick, - sex: OB11Constructor.sex(user.sex!), - age: 0, - qid: user.qid, - login_days: 0, - level: user.qqLevel && calcQQLevel(user.qqLevel) || 0, - }; - } - - static groupMembers(group: Group): OB11GroupMember[] { - //logDebug('construct ob11 group members', group); - return Array.from(groupMembers.get(group.groupCode)?.values() || []).map(m => OB11Constructor.groupMember(group.groupCode, m)); - } - - static group(group: Group): OB11Group { - return { - group_id: parseInt(group.groupCode), - group_name: group.groupName, - member_count: group.memberCount, - max_member_count: group.maxMember - }; - } - - static groups(groups: Group[]): OB11Group[] { - return groups.map(OB11Constructor.group); - } -} diff --git a/src/onebot11/cqcode.ts b/src/onebot11/cqcode.ts deleted file mode 100644 index c5a837d5..00000000 --- a/src/onebot11/cqcode.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { OB11MessageData } from './types'; - -const pattern = /\[CQ:(\w+)((,\w+=[^,\]]*)*)\]/; - -function unescape(source: string) { - return String(source) - .replace(/[/g, '[') - .replace(/]/g, ']') - .replace(/,/g, ',') - .replace(/&/g, '&'); -} - -function from(source: string) { - const capture = pattern.exec(source); - if (!capture) return null; - const [, type, attrs] = capture; - const data: Record = {}; - attrs && attrs.slice(1).split(',').forEach((str) => { - const index = str.indexOf('='); - data[str.slice(0, index)] = unescape(str.slice(index + 1)); - }); - return { type, data, capture }; -} - -function h(type: string, data: any) { - return { - type, - data, - }; -} - -export function decodeCQCode(source: string): OB11MessageData[] { - const elements: any[] = []; - let result: ReturnType; - 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; -} - - -export function encodeCQCode(data: OB11MessageData) { - const CQCodeEscapeText = (text: string) => { - return text.replace(/&/g, '&') - .replace(/\[/g, '[') - .replace(/\]/g, ']'); - - }; - - const CQCodeEscape = (text: string) => { - return text.replace(/&/g, '&') - .replace(/\[/g, '[') - .replace(/\]/g, ']') - .replace(/,/g, ','); - }; - - if (data.type === 'text') { - return CQCodeEscapeText(data.data.text); - } - - let result = '[CQ:' + data.type; - for (const name in data.data) { - const value = data.data[name]; - if (value === undefined) { - continue; - } - try { - const text = value.toString(); - result += `,${name}=${CQCodeEscape(text)}`; - } catch (error) { - // If it can't be converted, skip this name-value pair - } - } - result += ']'; - return result; -} - -// const result = parseCQCode("[CQ:at,qq=114514]早上好啊[CQ:image,file=http://baidu.com/1.jpg,type=show,id=40004]") -// const result = parseCQCode("好好好") -// console.log(JSON.stringify(result)) diff --git a/src/onebot11/event/OB11BaseEvent.ts b/src/onebot11/event/OB11BaseEvent.ts deleted file mode 100644 index 377ad9ac..00000000 --- a/src/onebot11/event/OB11BaseEvent.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { selfInfo } from '@/core/data'; - -export enum EventType { - META = 'meta_event', - REQUEST = 'request', - NOTICE = 'notice', - MESSAGE = 'message', - MESSAGE_SENT = 'message_sent', -} - - -export abstract class OB11BaseEvent { - time = Math.floor(Date.now() / 1000); - self_id = parseInt(selfInfo.uin); - post_type: EventType = EventType.META; -} diff --git a/src/onebot11/event/message/OB11BaseMessageEvent.ts b/src/onebot11/event/message/OB11BaseMessageEvent.ts deleted file mode 100644 index 8ed0f8f6..00000000 --- a/src/onebot11/event/message/OB11BaseMessageEvent.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { EventType, OB11BaseEvent } from '../OB11BaseEvent'; - -export abstract class OB11BaseMessageEvent extends OB11BaseEvent { - post_type = EventType.MESSAGE; -} \ No newline at end of file diff --git a/src/onebot11/event/meta/OB11BaseMetaEvent.ts b/src/onebot11/event/meta/OB11BaseMetaEvent.ts deleted file mode 100644 index 4a1b9344..00000000 --- a/src/onebot11/event/meta/OB11BaseMetaEvent.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { EventType, OB11BaseEvent } from '../OB11BaseEvent'; - -export abstract class OB11BaseMetaEvent extends OB11BaseEvent { - post_type = EventType.META; - meta_event_type: string; -} \ No newline at end of file diff --git a/src/onebot11/event/meta/OB11HeartbeatEvent.ts b/src/onebot11/event/meta/OB11HeartbeatEvent.ts deleted file mode 100644 index ad2a0c55..00000000 --- a/src/onebot11/event/meta/OB11HeartbeatEvent.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { OB11BaseMetaEvent } from './OB11BaseMetaEvent'; - -interface HeartbeatStatus { - online: boolean | null, - good: boolean -} - -export class OB11HeartbeatEvent extends OB11BaseMetaEvent { - meta_event_type = 'heartbeat'; - status: HeartbeatStatus; - interval: number; - - public constructor(isOnline: boolean, isGood: boolean, interval: number) { - super(); - this.interval = interval; - this.status = { - online: isOnline, - good: isGood - }; - } -} \ No newline at end of file diff --git a/src/onebot11/event/meta/OB11LifeCycleEvent.ts b/src/onebot11/event/meta/OB11LifeCycleEvent.ts deleted file mode 100644 index a28f91eb..00000000 --- a/src/onebot11/event/meta/OB11LifeCycleEvent.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { OB11BaseMetaEvent } from './OB11BaseMetaEvent'; - -export enum LifeCycleSubType { - ENABLE = 'enable', - DISABLE = 'disable', - CONNECT = 'connect' -} - -export class OB11LifeCycleEvent extends OB11BaseMetaEvent { - meta_event_type = 'lifecycle'; - sub_type: LifeCycleSubType; - - public constructor(subType: LifeCycleSubType) { - super(); - this.sub_type = subType; - } -} \ No newline at end of file diff --git a/src/onebot11/event/notice/OB11BaseNoticeEvent.ts b/src/onebot11/event/notice/OB11BaseNoticeEvent.ts deleted file mode 100644 index 15c45893..00000000 --- a/src/onebot11/event/notice/OB11BaseNoticeEvent.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { EventType, OB11BaseEvent } from '../OB11BaseEvent'; - -export abstract class OB11BaseNoticeEvent extends OB11BaseEvent { - post_type = EventType.NOTICE; -} \ No newline at end of file diff --git a/src/onebot11/event/notice/OB11FriendAddNoticeEvent.ts b/src/onebot11/event/notice/OB11FriendAddNoticeEvent.ts deleted file mode 100644 index 185b574f..00000000 --- a/src/onebot11/event/notice/OB11FriendAddNoticeEvent.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent'; - -export class OB11FriendAddNoticeEvent extends OB11BaseNoticeEvent { - notice_type = 'friend_add'; - user_id: number; - - public constructor(user_Id: number) { - super(); - this.user_id = user_Id; - } -} \ No newline at end of file diff --git a/src/onebot11/event/notice/OB11FriendRecallNoticeEvent.ts b/src/onebot11/event/notice/OB11FriendRecallNoticeEvent.ts deleted file mode 100644 index 2e374878..00000000 --- a/src/onebot11/event/notice/OB11FriendRecallNoticeEvent.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent'; - -export class OB11FriendRecallNoticeEvent extends OB11BaseNoticeEvent { - notice_type = 'friend_recall'; - user_id: number; - message_id: number; - - public constructor(userId: number, messageId: number) { - super(); - this.user_id = userId; - this.message_id = messageId; - } -} \ No newline at end of file diff --git a/src/onebot11/event/notice/OB11GroupAdminNoticeEvent.ts b/src/onebot11/event/notice/OB11GroupAdminNoticeEvent.ts deleted file mode 100644 index a968de43..00000000 --- a/src/onebot11/event/notice/OB11GroupAdminNoticeEvent.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; - -export class OB11GroupAdminNoticeEvent extends OB11GroupNoticeEvent { - notice_type = 'group_admin'; - sub_type: 'set' | 'unset' = "set"; // "set" | "unset" -} \ No newline at end of file diff --git a/src/onebot11/event/notice/OB11GroupBanEvent.ts b/src/onebot11/event/notice/OB11GroupBanEvent.ts deleted file mode 100644 index 9b47fc36..00000000 --- a/src/onebot11/event/notice/OB11GroupBanEvent.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; - -export class OB11GroupBanEvent extends OB11GroupNoticeEvent { - notice_type = 'group_ban'; - operator_id: number; - duration: number; - sub_type: 'ban' | 'lift_ban'; - - constructor(groupId: number, userId: number, operatorId: number, duration: number, sub_type: 'ban' | 'lift_ban') { - super(); - this.group_id = groupId; - this.operator_id = operatorId; - this.user_id = userId; - this.duration = duration; - this.sub_type = sub_type; - } -} diff --git a/src/onebot11/event/notice/OB11GroupCardEvent.ts b/src/onebot11/event/notice/OB11GroupCardEvent.ts deleted file mode 100644 index 1c2e4bc0..00000000 --- a/src/onebot11/event/notice/OB11GroupCardEvent.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; - -export class OB11GroupCardEvent extends OB11GroupNoticeEvent { - notice_type = 'group_card'; - card_new: string; - card_old: string; - - - constructor(groupId: number, userId: number, cardNew: string, cardOld: string) { - super(); - this.group_id = groupId; - this.user_id = userId; - this.card_new = cardNew; - this.card_old = cardOld; - } -} diff --git a/src/onebot11/event/notice/OB11GroupDecreaseEvent.ts b/src/onebot11/event/notice/OB11GroupDecreaseEvent.ts deleted file mode 100644 index 33da8563..00000000 --- a/src/onebot11/event/notice/OB11GroupDecreaseEvent.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; - -export type GroupDecreaseSubType = 'leave' | 'kick' | 'kick_me'; - -export class OB11GroupDecreaseEvent extends OB11GroupNoticeEvent { - notice_type = 'group_decrease'; - sub_type: GroupDecreaseSubType = 'leave'; // TODO: 实现其他几种子类型的识别 ("leave" | "kick" | "kick_me") - operator_id: number; - - constructor(groupId: number, userId: number, operatorId: number, subType: GroupDecreaseSubType = 'leave') { - super(); - this.group_id = groupId; - this.operator_id = operatorId; // 实际上不应该这么实现,但是现在还没有办法识别用户是被踢出的,还是自己主动退出的 - this.user_id = userId; - this.sub_type = subType; - } -} diff --git a/src/onebot11/event/notice/OB11GroupEssenceEvent.ts b/src/onebot11/event/notice/OB11GroupEssenceEvent.ts deleted file mode 100644 index ae1053e1..00000000 --- a/src/onebot11/event/notice/OB11GroupEssenceEvent.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; -export class OB11GroupEssenceEvent extends OB11GroupNoticeEvent { - notice_type = 'essence'; - message_id: number; - sender_id: number; - sub_type: 'add' | 'delete' = 'add'; - - constructor(groupId: number, message_id: number, sender_id: number) { - super(); - this.group_id = groupId; - this.message_id = message_id; - this.sender_id = sender_id; - } -} diff --git a/src/onebot11/event/notice/OB11GroupIncreaseEvent.ts b/src/onebot11/event/notice/OB11GroupIncreaseEvent.ts deleted file mode 100644 index b0a86880..00000000 --- a/src/onebot11/event/notice/OB11GroupIncreaseEvent.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; - -type GroupIncreaseSubType = 'approve' | 'invite'; -export class OB11GroupIncreaseEvent extends OB11GroupNoticeEvent { - notice_type = 'group_increase'; - operator_id: number; - sub_type: GroupIncreaseSubType; - constructor(groupId: number, userId: number, operatorId: number, subType: GroupIncreaseSubType = 'approve') { - super(); - this.group_id = groupId; - this.operator_id = operatorId; - this.user_id = userId; - this.sub_type = subType; - } -} diff --git a/src/onebot11/event/notice/OB11GroupNoticeEvent.ts b/src/onebot11/event/notice/OB11GroupNoticeEvent.ts deleted file mode 100644 index 3e046f87..00000000 --- a/src/onebot11/event/notice/OB11GroupNoticeEvent.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent'; - -export abstract class OB11GroupNoticeEvent extends OB11BaseNoticeEvent { - group_id: number = 0; - user_id: number = 0; -} \ No newline at end of file diff --git a/src/onebot11/event/notice/OB11GroupRecallNoticeEvent.ts b/src/onebot11/event/notice/OB11GroupRecallNoticeEvent.ts deleted file mode 100644 index 8d35ca1b..00000000 --- a/src/onebot11/event/notice/OB11GroupRecallNoticeEvent.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; - -export class OB11GroupRecallNoticeEvent extends OB11GroupNoticeEvent { - notice_type = 'group_recall'; - operator_id: number; - message_id: number; - - constructor(groupId: number, userId: number, operatorId: number, messageId: number) { - super(); - this.group_id = groupId; - this.user_id = userId; - this.operator_id = operatorId; - this.message_id = messageId; - } -} \ No newline at end of file diff --git a/src/onebot11/event/notice/OB11GroupTitleEvent.ts b/src/onebot11/event/notice/OB11GroupTitleEvent.ts deleted file mode 100644 index 41eace84..00000000 --- a/src/onebot11/event/notice/OB11GroupTitleEvent.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; - -export class OB11GroupTitleEvent extends OB11GroupNoticeEvent { - notice_type = 'notify'; - sub_type = 'title'; - title: string; - - - constructor(groupId: number, userId: number, title: string) { - super(); - this.group_id = groupId; - this.user_id = userId; - this.title = title; - } -} diff --git a/src/onebot11/event/notice/OB11GroupUploadNoticeEvent.ts b/src/onebot11/event/notice/OB11GroupUploadNoticeEvent.ts deleted file mode 100644 index d5514872..00000000 --- a/src/onebot11/event/notice/OB11GroupUploadNoticeEvent.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; - -export interface GroupUploadFile{ - id: string, - name: string, - size: number, - busid: number, -} - -export class OB11GroupUploadNoticeEvent extends OB11GroupNoticeEvent { - notice_type = 'group_upload'; - file: GroupUploadFile; - - constructor(groupId: number, userId: number, file: GroupUploadFile) { - super(); - this.group_id = groupId; - this.user_id = userId; - this.file = file; - } -} \ No newline at end of file diff --git a/src/onebot11/event/notice/OB11InputStatusEvent.ts b/src/onebot11/event/notice/OB11InputStatusEvent.ts deleted file mode 100644 index ba255bc3..00000000 --- a/src/onebot11/event/notice/OB11InputStatusEvent.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent'; -//输入状态事件 初步完成 Mlikio wa Todo 需要做一些过滤 -export class OB11InputStatusEvent extends OB11BaseNoticeEvent { - notice_type = 'notify'; - sub_type = 'input_status'; - status_text = "对方正在输入..." - eventType = 1; - user_id = 0; - constructor(user_id: number, eventType: number, status_text: string) { - super(); - this.user_id = user_id; - this.eventType = eventType; - this.status_text = status_text; - } -} - diff --git a/src/onebot11/event/notice/OB11MsgEmojiLikeEvent.ts b/src/onebot11/event/notice/OB11MsgEmojiLikeEvent.ts deleted file mode 100644 index 1af5ced7..00000000 --- a/src/onebot11/event/notice/OB11MsgEmojiLikeEvent.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; - -export interface MsgEmojiLike { - emoji_id: string, - count: number -} - -export class OB11GroupMsgEmojiLikeEvent extends OB11GroupNoticeEvent { - notice_type = 'group_msg_emoji_like'; - message_id: number; - likes: MsgEmojiLike[]; - - constructor(groupId: number, userId: number, messageId: number, likes: MsgEmojiLike[]) { - super(); - this.group_id = groupId; - this.user_id = userId; // 可为空,表示是对别人的消息操作,如果是对bot自己的消息则不为空 - this.message_id = messageId; - this.likes = likes; - } -} diff --git a/src/onebot11/event/notice/OB11PokeEvent.ts b/src/onebot11/event/notice/OB11PokeEvent.ts deleted file mode 100644 index 192b558e..00000000 --- a/src/onebot11/event/notice/OB11PokeEvent.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent'; - -class OB11PokeEvent extends OB11BaseNoticeEvent { - notice_type = 'notify'; - sub_type = 'poke'; - target_id = 0; - user_id = 0; -} - -export class OB11FriendPokeEvent extends OB11PokeEvent { - raw_info: any; - //raw_message nb等框架标准为string - constructor(user_id: number, target_id: number, raw_message: any) { - super(); - this.target_id = target_id; - this.user_id = user_id; - this.raw_info = raw_message; - } -} - -export class OB11GroupPokeEvent extends OB11PokeEvent { - group_id: number; - raw_info: any; - //raw_message nb等框架标准为string - constructor(group_id: number, user_id: number = 0, target_id: number = 0, raw_message: any) { - super(); - this.group_id = group_id; - this.target_id = target_id; - this.user_id = user_id; - this.raw_info = raw_message; - } -} diff --git a/src/onebot11/event/request/OB11FriendRequest.ts b/src/onebot11/event/request/OB11FriendRequest.ts deleted file mode 100644 index 522aa483..00000000 --- a/src/onebot11/event/request/OB11FriendRequest.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { OB11BaseNoticeEvent } from '../notice/OB11BaseNoticeEvent'; -import { EventType } from '../OB11BaseEvent'; - - -export class OB11FriendRequestEvent extends OB11BaseNoticeEvent { - post_type = EventType.REQUEST; - user_id: number = 0; - request_type = 'friend' as const; - comment: string = ''; - flag: string = ''; -} diff --git a/src/onebot11/event/request/OB11GroupRequest.ts b/src/onebot11/event/request/OB11GroupRequest.ts deleted file mode 100644 index e06677e6..00000000 --- a/src/onebot11/event/request/OB11GroupRequest.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { OB11GroupNoticeEvent } from '../notice/OB11GroupNoticeEvent'; -import { EventType } from '../OB11BaseEvent'; - - -export class OB11GroupRequestEvent extends OB11GroupNoticeEvent { - post_type = EventType.REQUEST; - request_type = 'group' as const; - sub_type: 'add' | 'invite' = 'add'; - comment: string = ''; - flag: string = ''; -} diff --git a/src/onebot11/log.ts b/src/onebot11/log.ts deleted file mode 100644 index f95d9870..00000000 --- a/src/onebot11/log.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { OB11Message } from '@/onebot11/types'; -import { log } from '@/common/utils/log'; -import { getGroup, getGroupMember, selfInfo } from '@/core/data'; -import exp from 'constants'; -import { Group, NTQQMsgApi } from '@/core'; -import chalk from 'chalk'; - -const spSegColor = chalk.blue;// for special segment -const spColor = chalk.cyan;// for special - -// todo: 应该放到core去用RawMessage解析打印 -export async function logMessage(ob11Message: OB11Message) { - const isSelfSent = ob11Message.sender.user_id.toString() === selfInfo.uin; - let prefix = ''; - let group: Group | undefined; - if (isSelfSent) { - prefix = '发送消息 '; - if (ob11Message.message_type === 'private') { - prefix += '给私聊 '; - prefix += `${ob11Message.target_id}`; - } - else { - prefix += '给群聊 '; - } - } - if (ob11Message.message_type === 'group') { - if (ob11Message.group_id == 284840486) { - group = await getGroup(ob11Message.group_id!); - prefix += `转发消息[外部来源] `; - } else { - group = await getGroup(ob11Message.group_id!); - prefix += `群[${group?.groupName}(${ob11Message.group_id})] `; - } - } - let msgChain = ''; - if (Array.isArray(ob11Message.message)) { - const msgParts = []; - for (const segment of ob11Message.message) { - if (segment.type === 'text') { - msgParts.push(segment.data.text); - } - else if (segment.type === 'at') { - const groupMember = await getGroupMember(ob11Message.group_id!, segment.data.qq!); - msgParts.push(spSegColor(`[@${groupMember?.cardName || groupMember?.nick}(${segment.data.qq})]`)); - } - else if (segment.type === 'reply') { - msgParts.push(spSegColor(`[回复消息|id:${segment.data.id}]`)); - } - else if (segment.type === 'image') { - msgParts.push(spSegColor(`[图片|${segment.data.url}]`)); - } - else if (segment.type === 'face') { - msgParts.push(spSegColor(`[表情|id:${segment.data.id}]`)); - } - else if (segment.type === 'mface') { - // @ts-expect-error 商城表情 url - msgParts.push(spSegColor(`[商城表情|${segment.data.url}]`)); - } - else if (segment.type === 'record') { - msgParts.push(spSegColor(`[语音|${segment.data.file}]`)); - } - else if (segment.type === 'file') { - msgParts.push(spSegColor(`[文件|${segment.data.file}]`)); - } - else if (segment.type === 'json') { - msgParts.push(spSegColor(`[json|${JSON.stringify(segment.data)}]`)); - } - else if (segment.type === 'markdown') { - msgParts.push(spSegColor(`[markdown|${segment.data.content}]`)); - } - else if (segment.type === 'video') { - msgParts.push(spSegColor(`[视频|${segment.data.url}]`)); - } - else if (segment.type === 'forward') { - msgParts.push(spSegColor(`[转发|${segment.data.id}|消息开始]`)); - segment.data.content.forEach((msg) => { - logMessage(msg); - }); - msgParts.push(spSegColor(`[转发|${segment.data.id}|消息结束]`)); - } - else { - msgParts.push(spSegColor(`[未实现|${JSON.stringify(segment)}]`)); - } - } - msgChain = msgParts.join(' '); - } - else { - msgChain = ob11Message.message; - } - let msgString = `${prefix}${ob11Message.sender.nickname}(${ob11Message.sender.user_id}): ${msgChain}`; - if (isSelfSent) { - msgString = `${prefix}: ${msgChain}`; - } - log(msgString); -} - -export async function logNotice(ob11Notice: any) { - log(spColor('[Notice]'), ob11Notice); -} - -export async function logRequest(ob11Request: any) { - log(spColor('[Request]'), ob11Request); -} diff --git a/src/onebot11/main.ts b/src/onebot11/main.ts deleted file mode 100644 index 196d272d..00000000 --- a/src/onebot11/main.ts +++ /dev/null @@ -1,675 +0,0 @@ -import { napCatCore } from '@/core'; -import { DebugGroupListener, MsgListener, TempOnRecvParams } from '@/core/listeners'; -import { OB11Constructor } from '@/onebot11/constructor'; -import { postOB11Event } from '@/onebot11/server/postOB11Event'; -import { - BuddyReqType, - ChatType, - ElementType, - FriendRequest, - Group, - GroupMember, - GroupMemberRole, - GroupNotify, - GroupNotifyTypes, - KickedOffLineInfo, - RawMessage -} from '@/core/entities'; -import { OB11Config, ob11Config } from '@/onebot11/config'; -import { httpHeart, ob11HTTPServer } from '@/onebot11/server/http'; -import { ob11WebsocketServer } from '@/onebot11/server/ws/WebsocketServer'; -import { ob11ReverseWebsockets } from '@/onebot11/server/ws/ReverseWebsocket'; -import { getGroup, getGroupMember, groupMembers, selfInfo, tempGroupCodeMap } from '@/core/data'; -import { BuddyListener, GroupListener, NodeIKernelBuddyListener } from '@/core/listeners'; -import { OB11FriendRequestEvent } from '@/onebot11/event/request/OB11FriendRequest'; -import { NTQQGroupApi, NTQQUserApi, WebApi } from '@/core/apis'; -import { log, logDebug, logError, setLogSelfInfo } from '@/common/utils/log'; -import { OB11GroupRequestEvent } from '@/onebot11/event/request/OB11GroupRequest'; -import { OB11GroupAdminNoticeEvent } from '@/onebot11/event/notice/OB11GroupAdminNoticeEvent'; -import { GroupDecreaseSubType, OB11GroupDecreaseEvent } from '@/onebot11/event/notice/OB11GroupDecreaseEvent'; -import { OB11FriendRecallNoticeEvent } from '@/onebot11/event/notice/OB11FriendRecallNoticeEvent'; -import { OB11GroupRecallNoticeEvent } from '@/onebot11/event/notice/OB11GroupRecallNoticeEvent'; -import { logMessage, logNotice, logRequest } from '@/onebot11/log'; -import { OB11Message } from '@/onebot11/types'; -import { isEqual } from '@/common/utils/helper'; -import { MessageUnique } from '@/common/utils/MessageUnique'; -import { OB11InputStatusEvent } from './event/notice/OB11InputStatusEvent'; - -//下面几个其实应该移进Core-Data 缓存实现 但是现在在这里方便 -// -export interface LineDevice { - app_id: string; - device_name: string; - device_kind: string; -} -export const DeviceList = new Array(); - -//peer->cached(boolen) -// const PokeCache = new Map(); - -function check_http_ws_equal(conf: any) { // 放在NapCatOnebot11里能被onReady调用却不能被SetConfig调用 不知道为什么 只能放这里了 - return isEqual(conf.http.port, conf.ws.port) && isEqual(conf.http.host, conf.ws.host); -} - -export class NapCatOnebot11 { - private bootTime: number = Date.now() / 1000; // 秒 - - - constructor() { - // console.log('ob11 init'); - napCatCore.onLoginSuccess(this.onReady.bind(this)); - } - - public onReady() { - logDebug('ob11 ready'); - ob11Config.read(); - const serviceInfo = ` - HTTP服务 ${ob11Config.http.enable ? '已启动' : '未启动'}, ${ob11Config.http.host}:${ob11Config.http.port} - HTTP上报服务 ${ob11Config.http.enablePost ? '已启动' : '未启动'}, 上报地址: ${ob11Config.http.postUrls} - WebSocket服务 ${ob11Config.ws.enable ? '已启动' : '未启动'}, ${ob11Config.ws.host}:${ob11Config.ws.port} - WebSocket反向服务 ${ob11Config.reverseWs.enable ? '已启动' : '未启动'}, 反向地址: ${ob11Config.reverseWs.urls} - `; - log(serviceInfo); - NTQQUserApi.getUserDetailInfo(selfInfo.uid).then(user => { - selfInfo.nick = user.nick; - setLogSelfInfo(selfInfo); - }).catch(logError); - if (ob11Config.http.enable) { - ob11HTTPServer.start(ob11Config.http.port, ob11Config.http.host); - } - if (ob11Config.ws.enable) { - if (check_http_ws_equal(ob11Config) && ob11HTTPServer.server) { // ob11HTTPServer.server != null 隐含了 ob11Config.http.enable == true 的条件 - ob11WebsocketServer.start(ob11HTTPServer.server); - } else { - ob11WebsocketServer.start(ob11Config.ws.port, ob11Config.ws.host); - } - } - if (ob11Config.reverseWs.enable) { - ob11ReverseWebsockets.start(); - } - if (ob11Config.http.enableHeart) { - // 启动http心跳 - httpHeart.start(); - } - // Create MsgListener - const msgListener = new MsgListener(); - msgListener.onInputStatusPush = async (data: { - chatType: number; - eventType: number; - fromUin: string; - interval: string; - showTime: string; - statusText: string; - timestamp: string; - toUin: string; - } - ) => { - let uin = await NTQQUserApi.getUinByUid(data.fromUin); - logNotice(`[输入状态] ${uin} ${data.statusText}`); - postOB11Event(new OB11InputStatusEvent(parseInt(uin), data.eventType, data.statusText)); - } - msgListener.onRecvSysMsg = async (protobufData: number[]) => { - // function buf2hex(buffer: Buffer) { - // return [...new Uint8Array(buffer)] - // .map(x => x.toString(16).padStart(2, '0')) - // .join(''); - // } - // const hex = buf2hex(Buffer.from(protobufData)); - // console.log(hex); - // // let Data: Data = { - // // header: { - // // GroupNumber: 0, - // // GroupString: '', - // // QQ: 0, - // // Uid: '', - // // }, - // // Body: { - // // MsgType: 0, - // // SubType_0: 0, - // // SubType_1: 0, - // // MsgSeq: 0, - // // Time: 0, - // // MsgID: 0, - // // Other: 0, - // // } - // // }; - // try { - // // 生产环境会自己去掉 - // const hex = buf2hex(Buffer.from(protobufData)); - // //console.log(hex); - // const sysMsg = SysData.fromBinary(Buffer.from(protobufData)); - // const peeruin = sysMsg.header[0].peerNumber; - // const peeruid = sysMsg.header[0].peerString; - // const MsgType = sysMsg.body[0].msgType; - // const subType0 = sysMsg.body[0].subType0; - // const subType1 = sysMsg.body[0].subType1; - // // let pokeEvent: OB11FriendPokeEvent | OB11GroupPokeEvent; - // // //console.log(peeruid); - // // if (MsgType == 528 && subType0 == 290 && hex.length < 250 && hex.endsWith('04')) { - // // // 防止上报两次 私聊戳一戳 - // // if (PokeCache.has(peeruid)) { - // // //log('[私聊] 用户 ', peeruin, ' 对你戳一戳'); - // // pokeEvent = new OB11FriendPokeEvent(parseInt(selfInfo.uin), peeruin); - // // postOB11Event(pokeEvent); - // // } - // // PokeCache.set(peeruid, false); - // // setTimeout(() => { - // // PokeCache.delete(peeruid); - // // }, 1000); - // // } - // // if (MsgType == 732 && subType0 == 20 && hex.length < 150 && hex.endsWith('04')) { - // // // 防止上报两次 群聊戳一戳 - // // if (PokeCache.has(peeruid)) { - // // log('[群聊] 群组 ', peeruin, ' 戳一戳'); - // // pokeEvent = new OB11GroupPokeEvent(peeruin); - // // postOB11Event(pokeEvent); - // // } - // // PokeCache.set(peeruid, false); - // // setTimeout(() => { - // // PokeCache.delete(peeruid); - // // }, 1000); - // // } - // if (MsgType == 528 && subType0 == 349) { - // const sysDeviceMsg = DeviceData.fromBinary(Buffer.from(protobufData)); - // DeviceList = []; - // sysDeviceMsg.event[0].content[0].devices.forEach(device => { - // DeviceList.push({ - // app_id: '0', - // device_name: device.deviceName, - // device_kind: 'none' - // }); - // // log('[设备列表] 设备名称: ' + device.deviceName); - // }); - // } - // // 未区分增加与减少 - // // if (MsgType == 34 && subType0 == 0) { - // // const role = (await getGroupMember(peeruin, selfInfo.uin))?.role; - // // const isPrivilege = role === 3 || role === 4; - // // if (!isPrivilege) { - // // const leaveUin = - // // log('[群聊] 群组 ', peeruin, ' 成员' + leaveUin + '退出'); - // // const groupDecreaseEvent = new OB11GroupDecreaseEvent(peeruin, parseInt(leaveUin), 0, 'leave');// 不知道怎么出去的 - // // postOB11Event(groupDecreaseEvent, true); - // // } - // // } - // // MsgType (SubType) EventName - // // 33 GroupMemIncreased - // // 34 GroupMemberDecreased - // // 44 GroupAdminChange - // // 82 GroupMessage - // // 84 GroupApply - // // 87 InviteGroup - // // 528 35 FriendApply - // // 528 39 CardChange - // // 528 68 GroupApply - // // 528 138 C2CRecall - // // 528 290 C2CPoke - // // 528 349 DeviceChange - // // 732 12 GroupBan - // // 732 16 GroupUniqueTitleChange - // // 732 17 GroupRecall - // // 732 20 GroupCommonTips - // // 732 21 EssenceMessage - // // 732 16 16 GrayTips ->Busi->GroupEmjioLike - // } catch (e) { - // log('解析SysMsg异常', e); - // // console.log(e); - // } - }; - msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => { - // 下线通知 - //postOB11Event - selfInfo.online = false; - }; - msgListener.onTempChatInfoUpdate = (tempChatInfo: TempOnRecvParams) => { - if (tempChatInfo.sessionType == 1 && tempChatInfo.chatType == ChatType.temp) { - tempGroupCodeMap[tempChatInfo.peerUid] = tempChatInfo.groupCode; - } - // 临时会话更新 tempGroupCodeMap uid -> source/GroupCode - }; - msgListener.onRecvMsg = async (msg) => { - //console.log('ob11 onRecvMsg', JSON.stringify(msg, null, 2)); - // logDebug('收到消息', msg); - for (const m of msg) { - // try: 减掉3s 试图修复消息半天收不到(不减了不减了 会出大问题) - if (this.bootTime > parseInt(m.msgTime)) { - logDebug(`消息时间${m.msgTime}早于启动时间${this.bootTime},忽略上报`); - continue; - } - // 调用应该必须带 chatInfo 不然不行 想不通想不通 - // let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx(m.msgId, '0', '0', { - // chatInfo: { - // peerUid: '', - // chatType: 0, - // }, - // filterMsgType: [], - // filterSendersUid: [], - // filterMsgToTime: '0', - // filterMsgFromTime: '0', - // isReverseOrder: false, - // isIncludeCurrent: true, - // pageLimit: 2, - // }); - // console.log(ret); - new Promise((resolve) => { - m.id = MessageUnique.createMsg({ chatType: m.chatType, peerUid: m.peerUid, guildId: '' }, m.msgId); - console.log("消息接收 ", "MsgID", m.msgId, " ID", m.id, " MsgSeq", m.msgSeq, " Raw", m?.elements[0]?.textElement?.content); - this.postReceiveMsg([m]).then().catch(logError); - }).then(); - } - }; - msgListener.onMsgInfoListUpdate = (msgList) => { - this.postRecallMsg(msgList).then().catch(logError); - for (const msg of msgList.filter(e => e.senderUin == selfInfo.uin)) { - // console.log(msg); - if (msg.sendStatus == 2) { - //完成后再post - OB11Constructor.message(msg).then((_msg) => { - _msg.target_id = parseInt(msg.peerUin); - console.log("自身消息接收 ", "MsgID", msg.msgId, " MsgSeq", msg.msgSeq, " Raw", msg?.elements[0]?.textElement?.content); - if (ob11Config.reportSelfMessage) { - msg.id = MessageUnique.createMsg({ chatType: msg.chatType, peerUid: msg.peerUid, guildId: '' }, msg.msgId); - this.postReceiveMsg([msg]).then().catch(logError); - } else { - logMessage(_msg as OB11Message).then().catch(logError); - } - }).catch(logError); - } - - } - }; - msgListener.onAddSendMsg = (msg) => { - - }; - napCatCore.addListener(msgListener); - logDebug('ob11 msg listener added'); - - // BuddyListener - const buddyListener = new BuddyListener(); - buddyListener.onBuddyReqChange = ((req) => { - //从这里获取?好友请求 - this.postFriendRequest(req.buddyReqs).then().catch(logError); - }); - napCatCore.addListener(buddyListener); - logDebug('ob11 buddy listener added'); - - // GroupListener - const groupListener = new GroupListener(); - // groupListener.onMemberListChange = async (arg: { - // sceneId: string, - // ids: string[], - // infos: Map, // uid -> GroupMember - // finish: boolean, - // hasRobot: boolean - // }) => { - - // } - groupListener.onGroupNotifiesUpdated = async (doubt, notifies) => { - //console.log('ob11 onGroupNotifiesUpdated', notifies[0]); - if (![GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notifies[0].type)) { - this.postGroupNotifies(notifies).then().catch(e => logError('postGroupNotifies error: ', e)); - } - }; - groupListener.onMemberInfoChange = async (groupCode: string, changeType: number, members: Map) => { - // console.log("ob11 onMemberInfoChange", groupCode, changeType, members) - if (changeType === 1) { - let member; - for (const [key, value] of members) { - member = value; - break; - } - if (member) { - const existMembers = groupMembers.get(groupCode); - if (existMembers) { - const existMember = existMembers.get(member.uid); - if (existMember) { - if (existMember.isChangeRole) { - //console.log("ob11 onMemberInfoChange:eventMember:localMember", member, existMember) - const notify: GroupNotify[] = [ - { - time: Date.now(), - seq: (Date.now() * 1000 * 1000).toString(), - type: member.role === GroupMemberRole.admin ? GroupNotifyTypes.ADMIN_SET : GroupNotifyTypes.ADMIN_UNSET_OTHER, // 8 设置; 13 取消 - status: 0, - group: { groupCode: groupCode, groupName: '' }, - user1: { uid: member.uid, nickName: member.nick }, - user2: { uid: member.uid, nickName: member.nick }, - actionUser: { uid: '', nickName: '' }, - actionTime: '0', - invitationExt: { srcType: 0, groupCode: '0', waitStatus: 0 }, - postscript: '', - repeatSeqs: [], - warningTips: '' - } - ]; - this.postGroupNotifies(notify).then().catch(e => logError('postGroupNotifies error: ', e)); - } - } - } - } - } - // 如果自身是非管理员也许要从这里获取Delete 成员变动 待测试与验证 - const role = (await getGroupMember(groupCode, selfInfo.uin))?.role; - const isPrivilege = role === 3 || role === 4; - for (const member of members.values()) { - //console.log(member?.isDelete, role, isPrivilege); - // Develop Mlikiowa Taged: 暂时屏蔽这个方案 考虑onMemberListChange - // if (member?.isDelete && !isPrivilege && selfInfo.uin !== member.uin) { - // log('[群聊] 群组 ', groupCode, ' 成员' + member.uin + '退出'); - // const groupDecreaseEvent = new OB11GroupDecreaseEvent(parseInt(groupCode), parseInt(member.uin), 0, 'leave');// 不知道怎么出去的 - // postOB11Event(groupDecreaseEvent, true); - // } - } - }; - groupListener.onJoinGroupNotify = (...notify) => { - // console.log('ob11 onJoinGroupNotify', notify); - }; - groupListener.onGroupListUpdate = (updateType, groupList) => { - // console.log('ob11 onGroupListUpdate', updateType, groupList); - // this.postGroupMemberChange(groupList).then(); - }; - - napCatCore.addListener(groupListener); - logDebug('ob11 group listener added'); - } - - async postReceiveMsg(msgList: RawMessage[]) { - const { debug, reportSelfMessage } = ob11Config; - for (const message of msgList) { - logDebug('收到新消息', message); - OB11Constructor.message(message).then((msg) => { - logDebug('收到消息: ', msg); - if (debug) { - msg.raw = message; - } else { - if (msg.message.length === 0) { - return; - } - } - if (msg.post_type === 'message') { - logMessage(msg as OB11Message).then().catch(logError); - } else if (msg.post_type === 'notice') { - logNotice(msg).then().catch(logError); - } else if (msg.post_type === 'request') { - logRequest(msg).then().catch(logError); - } - const isSelfMsg = msg.user_id.toString() == selfInfo.uin; - if (isSelfMsg && !reportSelfMessage) { - return; - } - if (isSelfMsg) { - msg.target_id = parseInt(message.peerUin); - } - postOB11Event(msg); - // log("post msg", msg) - }).catch(e => logError('constructMessage error: ', e)); - OB11Constructor.GroupEvent(message).then(groupEvent => { - if (groupEvent) { - // log("post group event", groupEvent); - postOB11Event(groupEvent); - } - }).catch(e => logError('constructGroupEvent error: ', e)); - - OB11Constructor.PrivateEvent(message).then(privateEvent => { - if (privateEvent) { - // log("post private event", privateEvent); - postOB11Event(privateEvent); - } - }); - - } - } - async SetConfig(NewOb11: OB11Config) { - try { - // if (!NewOb11 || typeof NewOb11 !== 'object') { - // throw new Error('Invalid configuration object'); - // } - const OldConfig = JSON.parse(JSON.stringify(ob11Config)); //进行深拷贝 - ob11Config.save(NewOb11, true);//保存新配置 - - const isHttpChanged = !isEqual(NewOb11.http.enable, OldConfig.http.enable) || - !isEqual(NewOb11.http.host, OldConfig.http.host) || - !isEqual(NewOb11.http.port, OldConfig.http.port); - - // const isHttpPostChanged = !isEqual(NewOb11.http.postUrls, OldConfig.http.postUrls); - // const isEnanleHttpPostChanged = !isEqual(NewOb11.http.enablePost, OldConfig.http.enablePost); - - const isWsChanged = !isEqual(NewOb11.ws.enable, OldConfig.ws.enable) || - !isEqual(NewOb11.ws.host, OldConfig.ws.host) || - !isEqual(NewOb11.ws.port, OldConfig.ws.port); - - const isWsReverseChanged = !isEqual(NewOb11.reverseWs.enable, OldConfig.reverseWs.enable) || - !isEqual(NewOb11.reverseWs.urls, OldConfig.reverseWs.urls); - - //const isEnableHeartBeatChanged = !isEqual(NewOb11.heartInterval, OldConfig.heartInterval); - - if (check_http_ws_equal(NewOb11) || check_http_ws_equal(OldConfig)) { - // http与ws共站 需要同步重启 - if (isHttpChanged || isWsChanged) { - log('http与ws进行热重载'); - ob11WebsocketServer.stop(); - ob11HTTPServer.stop(); - if (NewOb11.http.enable) { - ob11HTTPServer.start(NewOb11.http.port, NewOb11.http.host); - } - if (NewOb11.ws.enable) { - if (check_http_ws_equal(NewOb11) && ob11HTTPServer.server) { - ob11WebsocketServer.start(ob11HTTPServer.server); - } else { - ob11WebsocketServer.start(NewOb11.ws.port, NewOb11.ws.host); - } - } - } - } else { - // http重启逻辑 - if (isHttpChanged) { - log('http进行热重载'); - ob11HTTPServer.stop(); - if (NewOb11.http.enable) { - ob11HTTPServer.start(NewOb11.http.port, NewOb11.http.host); - } - } - - // ws重启逻辑 - if (isWsChanged) { - log('ws进行热重载'); - ob11WebsocketServer.stop(); - if (NewOb11.ws.enable) { - ob11WebsocketServer.start(NewOb11.ws.port, NewOb11.ws.host); - } - } - } - - // 反向ws重启逻辑 - if (isWsReverseChanged) { - log('反向ws进行热重载'); - ob11ReverseWebsockets.stop(); - if (NewOb11.reverseWs.enable) { - ob11ReverseWebsockets.start(); - } - } - - } catch (e) { - logError('热重载配置失败', e); - } - - } - async postGroupNotifies(notifies: GroupNotify[]) { - for (const notify of notifies) { - try { - notify.time = Date.now(); - const notifyTime = parseInt(notify.seq) / 1000 / 1000; - // log(`群通知时间${notifyTime}`, `启动时间${this.bootTime}`); - if (notifyTime < this.bootTime) { - continue; - } - const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type; - logDebug('收到群通知', notify); - // let member2: GroupMember; - // if (notify.user2.uid) { - // member2 = await getGroupMember(notify.group.groupCode, null, notify.user2.uid); - // } - - if ([GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notify.type)) { - const member1 = await getGroupMember(notify.group.groupCode, notify.user1.uid); - logDebug('有管理员变动通知'); - // refreshGroupMembers(notify.group.groupCode).then(); - const groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent(); - groupAdminNoticeEvent.group_id = parseInt(notify.group.groupCode); - logDebug('开始获取变动的管理员'); - if (member1) { - logDebug('变动管理员获取成功'); - groupAdminNoticeEvent.user_id = parseInt(member1.uin); - groupAdminNoticeEvent.sub_type = [GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notify.type) ? 'unset' : 'set'; - // member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal; - postOB11Event(groupAdminNoticeEvent, true); - } else { - logDebug('获取群通知的成员信息失败', notify, getGroup(notify.group.groupCode)); - } - } else if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) { - logDebug('有成员退出通知', notify); - try { - const member1Uin = (await NTQQUserApi.getUinByUid(notify.user1.uid))!; - let operatorId = member1Uin; - let subType: GroupDecreaseSubType = 'leave'; - if (notify.user2.uid) { - // 是被踢的 - const member2Uin = await NTQQUserApi.getUinByUid(notify.user2.uid); - if (member2Uin) { - operatorId = member2Uin; - } - subType = 'kick'; - } - const groupDecreaseEvent = new OB11GroupDecreaseEvent(parseInt(notify.group.groupCode), parseInt(member1Uin), parseInt(operatorId), subType); - postOB11Event(groupDecreaseEvent, true); - } catch (e: any) { - logError('获取群通知的成员信息失败', notify, e.stack.toString()); - } - //notify.status == 1 表示未处理 2表示处理完成 - } else if ([GroupNotifyTypes.JOIN_REQUEST].includes(notify.type) && notify.status == 1) { - logDebug('有加群请求'); - const groupRequestEvent = new OB11GroupRequestEvent(); - groupRequestEvent.group_id = parseInt(notify.group.groupCode); - let requestQQ = ''; - try { - // uid-->uin - requestQQ = (await NTQQUserApi.getUinByUid(notify.user1.uid))!; - if (isNaN(parseInt(requestQQ))) { - requestQQ = (await NTQQUserApi.getUserDetailInfo(notify.user1.uid)).uin; - } - } catch (e) { - logError('获取加群人QQ号失败 Uid:', notify.user1.uid, e); - } - groupRequestEvent.user_id = parseInt(requestQQ) || 0; - groupRequestEvent.sub_type = 'add'; - groupRequestEvent.comment = notify.postscript; - groupRequestEvent.flag = flag; - postOB11Event(groupRequestEvent); - } else if (notify.type == GroupNotifyTypes.INVITE_ME) { - logDebug(`收到邀请我加群通知:${notify}`); - const groupInviteEvent = new OB11GroupRequestEvent(); - groupInviteEvent.group_id = parseInt(notify.group.groupCode); - const user_id = (await NTQQUserApi.getUinByUid(notify.user2.uid)) || ''; - groupInviteEvent.user_id = parseInt(user_id); - groupInviteEvent.sub_type = 'invite'; - groupInviteEvent.flag = flag; - postOB11Event(groupInviteEvent); - } - } catch (e: any) { - logDebug('解析群通知失败', e.stack.toString()); - } - } - - } - - async postRecallMsg(msgList: RawMessage[]) { - for (const message of msgList) { - // log("message update", message.sendStatus, message.msgId, message.msgSeq) - if (message.recallTime != '0') { //todo: 这个判断方法不太好,应该使用灰色消息元素来判断? - // 撤回消息上报 - const oriMessageId = await MessageUnique.getShortIdByMsgId(message.msgId); - if (!oriMessageId) { - continue; - } - if (message.chatType == ChatType.friend) { - const friendRecallEvent = new OB11FriendRecallNoticeEvent(parseInt(message!.senderUin), oriMessageId); - postOB11Event(friendRecallEvent); - } else if (message.chatType == ChatType.group) { - let operatorId = message.senderUin; - for (const element of message.elements) { - const operatorUid = element.grayTipElement?.revokeElement.operatorUid; - const operator = await getGroupMember(message.peerUin, operatorUid); - operatorId = operator?.uin || message.senderUin; - } - const groupRecallEvent = new OB11GroupRecallNoticeEvent( - parseInt(message.peerUin), - parseInt(message.senderUin), - parseInt(operatorId), - oriMessageId - ); - postOB11Event(groupRecallEvent); - } - } - } - } - - async postFriendRequest(reqs: FriendRequest[]) { - for (const req of reqs) { - if (!!req.isInitiator || (req.isDecide && req.reqType !== BuddyReqType.KMEINITIATORWAITPEERCONFIRM)) { - continue; - } - const friendRequestEvent = new OB11FriendRequestEvent(); - try { - const requesterUin = await NTQQUserApi.getUinByUid(req.friendUid); - friendRequestEvent.user_id = parseInt(requesterUin!); - } catch (e) { - logDebug('获取加好友者QQ号失败', e); - } - friendRequestEvent.flag = req.friendUid + '|' + req.reqTime; - friendRequestEvent.comment = req.extWords; - postOB11Event(friendRequestEvent); - } - } - - // async postGroupMemberChange(groupList: Group[]) { - // // todo: 有无更好的方法判断群成员变动 - // const newGroupList = groupList; - // for (const group of newGroupList) { - // const existGroup = await getGroup(group.groupCode); - // if (existGroup) { - // if (existGroup.memberCount > group.memberCount) { - // log(`群(${group.groupCode})成员数量减少${existGroup.memberCount} -> ${group.memberCount}`); - // const oldMembers = existGroup.members; - // const newMembers = await NTQQGroupApi.getGroupMembers(group.groupCode); - // group.members = newMembers; - // const newMembersSet = new Set(); // 建立索引降低时间复杂度 - // - // for (const member of newMembers) { - // newMembersSet.add(member.uin); - // } - // - // // 判断bot是否是管理员,如果是管理员不需要从这里得知有人退群,这里的退群无法得知是主动退群还是被踢 - // const bot = await getGroupMember(group.groupCode, selfInfo.uin); - // if (bot!.role == GroupMemberRole.admin || bot!.role == GroupMemberRole.owner) { - // continue; - // } - // for (const member of oldMembers) { - // if (!newMembersSet.has(member.uin) && member.uin != selfInfo.uin) { - // postOB11Event(new OB11GroupDecreaseEvent(parseInt(group.groupCode), parseInt(member.uin), parseInt(member.uin), 'leave')); - // break; - // } - // } - // } - // } - // } - // } -} - -// export const napCatOneBot11 = new NapCatOnebot11(); -// setTimeout(async () => { -// let ret = await MiniAppUtil.RunMiniAppWithGUI(); -// console.log(ret); -// }, 20000); -// setTimeout(async () => { -// await SignMusicWrapper('429450678'); -// }, 15000) \ No newline at end of file diff --git a/src/onebot11/onebot11.json b/src/onebot11/onebot11.json deleted file mode 100644 index d0f2c793..00000000 --- a/src/onebot11/onebot11.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "http": { - "enable": false, - "host": "", - "port": 3000, - "secret": "", - "enableHeart": false, - "enablePost": false, - "postUrls": [] - }, - "ws": { - "enable": false, - "host": "", - "port": 3001 - }, - "reverseWs": { - "enable": false, - "urls": [] - }, - "GroupLocalTime": { - "Record": false, - "RecordList": [] - }, - "debug": false, - "heartInterval": 30000, - "messagePostFormat": "array", - "enableLocalFile2Url": true, - "musicSignUrl": "", - "reportSelfMessage": false, - "token": "" -} \ No newline at end of file diff --git a/src/onebot11/server/http.ts b/src/onebot11/server/http.ts deleted file mode 100644 index 095be65d..00000000 --- a/src/onebot11/server/http.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Response } from 'express'; -import { OB11Response } from '../action/OB11Response'; -import { HttpServerBase } from '@/common/server/http'; -import { actionMap } from '../action'; -import { ob11Config } from '@/onebot11/config'; -import { selfInfo } from '@/core/data'; -import { OB11HeartbeatEvent } from '@/onebot11/event/meta/OB11HeartbeatEvent'; -import { postOB11Event } from '@/onebot11/server/postOB11Event'; - -class OB11HTTPServer extends HttpServerBase { - name = 'OneBot V11 server'; - - handleFailed(res: Response, payload: any, e: Error) { - res.send(OB11Response.error(e?.stack?.toString() || e.message || 'Error Handle', 200)); - } - - protected listen(port: number, host: string) { - if (ob11Config.http.enable) { - super.listen(port, host); - } - } -} - -export const ob11HTTPServer = new OB11HTTPServer(); - -setTimeout(() => { - for (const [actionName, action] of actionMap) { - for (const method of ['post', 'get']) { - ob11HTTPServer.registerRouter(method, actionName, (res, payload) => { - return action.handle(payload); - }); - } - } -}, 0); - - -class HTTPHeart { - intervalId: NodeJS.Timeout | null = null; - start(NewHeartInterval: number | undefined = undefined) { - let { heartInterval } = ob11Config; - if (NewHeartInterval && !Number.isNaN(NewHeartInterval)) { - heartInterval = NewHeartInterval; - } - if (this.intervalId) { - clearInterval(this.intervalId); - } - this.intervalId = setInterval(() => { - // ws的心跳是ws自己维护的 - postOB11Event(new OB11HeartbeatEvent(!!selfInfo.online, true, heartInterval), false, false); - }, heartInterval); - } - - stop() { - if (this.intervalId) { - clearInterval(this.intervalId); - } - } -} - -export const httpHeart = new HTTPHeart(); diff --git a/src/onebot11/server/postOB11Event.ts b/src/onebot11/server/postOB11Event.ts deleted file mode 100644 index fe7d2662..00000000 --- a/src/onebot11/server/postOB11Event.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { OB11Message, OB11MessageAt, OB11MessageData, OB11MessageReply } from '../types'; -import { OB11BaseMetaEvent } from '../event/meta/OB11BaseMetaEvent'; -import { OB11BaseNoticeEvent } from '../event/notice/OB11BaseNoticeEvent'; -import { WebSocket as WebSocketClass } from 'ws'; -import { wsReply } from './ws/reply'; -import { logDebug, logError } from '@/common/utils/log'; -import { ob11Config } from '@/onebot11/config'; -import crypto from 'crypto'; -import { ChatType, Group, GroupRequestOperateTypes, Peer } from '@/core/entities'; -import { normalize, sendMsg } from '../action/msg/SendMsg'; -import { OB11FriendRequestEvent } from '../event/request/OB11FriendRequest'; -import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest'; -import { isNull } from '@/common/utils/helper'; -import { getGroup, selfInfo } from '@/core/data'; -import { NTQQFriendApi, NTQQGroupApi, NTQQUserApi } from '@/core/apis'; -import createSendElements from '../action/msg/SendMsg/create-send-elements'; - -export type QuickActionEvent = OB11Message | OB11BaseMetaEvent | OB11BaseNoticeEvent -export type PostEventType = OB11Message | OB11BaseMetaEvent | OB11BaseNoticeEvent - -interface QuickActionPrivateMessage { - reply?: string; - auto_escape?: boolean; -} - -interface QuickActionGroupMessage extends QuickActionPrivateMessage { - // 回复群消息 - at_sender?: boolean; - delete?: boolean; - kick?: boolean; - ban?: boolean; - ban_duration?: number; - // -} - -interface QuickActionFriendRequest { - approve?: boolean; - remark?: string; -} - -interface QuickActionGroupRequest { - approve?: boolean; - reason?: string; -} - -export type QuickAction = - QuickActionPrivateMessage - & QuickActionGroupMessage - & QuickActionFriendRequest - & QuickActionGroupRequest - -const eventWSList: WebSocketClass[] = []; - -export function registerWsEventSender(ws: WebSocketClass) { - eventWSList.push(ws); -} - -export function unregisterWsEventSender(ws: WebSocketClass) { - const index = eventWSList.indexOf(ws); - if (index !== -1) { - eventWSList.splice(index, 1); - } -} - -export function postWsEvent(event: QuickActionEvent) { - for (const ws of eventWSList) { - new Promise(() => { - wsReply(ws, event); - }).then(); - } -} - -export function postOB11Event(msg: QuickActionEvent, reportSelf = false, postWs = true) { - const config = ob11Config; - - // 判断msg是否是event - if (!config.reportSelfMessage && !reportSelf) { - if (msg.post_type === 'message' && (msg as OB11Message).user_id.toString() == selfInfo.uin) { - return; - } - } - if (config.http.enablePost) { - const msgStr = JSON.stringify(msg); - const hmac = crypto.createHmac('sha1', ob11Config.http.secret); - hmac.update(msgStr); - const sig = hmac.digest('hex'); - const headers: Record = { - 'Content-Type': 'application/json', - 'x-self-id': selfInfo.uin - }; - if (config.http.secret) { - headers['x-signature'] = 'sha1=' + sig; - } - for (const host of config.http.postUrls) { - fetch(host, { - method: 'POST', - headers, - body: msgStr - }).then(async (res) => { - //logDebug(`新消息事件HTTP上报成功: ${host} `, msgStr); - // todo: 处理不够优雅,应该使用高级泛型进行QuickAction类型识别 - let resJson: QuickAction; - try { - resJson = await res.json(); - //logDebug('新消息事件HTTP上报返回快速操作: ', JSON.stringify(resJson)); - } catch (e) { - logDebug('新消息事件HTTP上报没有返回快速操作,不需要处理'); - return; - } - try { - handleQuickOperation(msg as QuickActionEvent, resJson).then().catch(logError); - } catch (e: any) { - logError('新消息事件HTTP上报返回快速操作失败', e); - } - - }, (err: any) => { - logError(`新消息事件HTTP上报失败: ${host} `, err, msg); - }); - } - } - if (postWs) { - postWsEvent(msg); - } -} -async function handleMsg(msg: OB11Message, quickAction: QuickAction) { - msg = msg as OB11Message; - const reply = quickAction.reply; - const peer: Peer = { - chatType: ChatType.friend, - peerUid: await NTQQUserApi.getUidByUin(msg.user_id.toString()) as string - }; - if (msg.message_type == 'private') { - if (msg.sub_type === 'group') { - peer.chatType = ChatType.temp; - } - } else { - peer.chatType = ChatType.group; - peer.peerUid = msg.group_id!.toString(); - } - if (reply) { - let group: Group | undefined; - let replyMessage: OB11MessageData[] = []; - - if (msg.message_type == 'group') { - group = await getGroup(msg.group_id!.toString()); - replyMessage.push({ - type: 'reply', - data: { - id: msg.message_id.toString() - } - } as OB11MessageReply); - if ((quickAction as QuickActionGroupMessage).at_sender) { - replyMessage.push({ - type: 'at', - data: { - qq: msg.user_id.toString() - } - } as OB11MessageAt); - } - } - replyMessage = replyMessage.concat(normalize(reply, quickAction.auto_escape)); - const { sendElements, deleteAfterSentFiles } = await createSendElements(replyMessage, peer); - sendMsg(peer, sendElements, deleteAfterSentFiles, false).then().catch(logError); - } -} -async function handleGroupRequest(request: OB11GroupRequestEvent, quickAction: QuickActionGroupRequest) { - if (!isNull(quickAction.approve)) { - NTQQGroupApi.handleGroupRequest( - request.flag, - quickAction.approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject, - quickAction.reason, - ).then().catch(logError); - } -} -async function handleFriendRequest(request: OB11FriendRequestEvent, quickAction: QuickActionFriendRequest) { - if (!isNull(quickAction.approve)) { - NTQQFriendApi.handleFriendRequest(request.flag, !!quickAction.approve).then().catch(logError); - } -} -export async function handleQuickOperation(context: QuickActionEvent, quickAction: QuickAction) { - if (context.post_type === 'message') { - handleMsg(context as OB11Message, quickAction).then().catch(logError); - } - if (context.post_type === 'request') { - const friendRequest = context as OB11FriendRequestEvent; - const groupRequest = context as OB11GroupRequestEvent; - if ((friendRequest).request_type === 'friend') { - handleFriendRequest(friendRequest, quickAction).then().catch(logError); - } - else if (groupRequest.request_type === 'group') { - handleGroupRequest(groupRequest, quickAction).then().catch(logError); - } - } -} \ No newline at end of file diff --git a/src/onebot11/server/ws/ReverseWebsocket.ts b/src/onebot11/server/ws/ReverseWebsocket.ts deleted file mode 100644 index 08792ce7..00000000 --- a/src/onebot11/server/ws/ReverseWebsocket.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { LifeCycleSubType, OB11LifeCycleEvent } from '../../event/meta/OB11LifeCycleEvent'; -import { ActionName } from '../../action/types'; -import { OB11Response } from '../../action/OB11Response'; -import BaseAction from '../../action/BaseAction'; -import { actionMap } from '../../action'; -import { postWsEvent, registerWsEventSender, unregisterWsEventSender } from '../postOB11Event'; -import { wsReply } from './reply'; -import { WebSocket as WebSocketClass } from 'ws'; -import { OB11HeartbeatEvent } from '../../event/meta/OB11HeartbeatEvent'; -import { log, logDebug, logError } from '../../../common/utils/log'; -import { ob11Config } from '@/onebot11/config'; -import { napCatCore } from '@/core'; -import { selfInfo } from '@/core/data'; - -export let rwsList: ReverseWebsocket[] = []; - -export class ReverseWebsocket { - public websocket: WebSocketClass | undefined; - public url: string; - private running: boolean = false; - - public constructor(url: string) { - this.url = url; - this.running = true; - this.connect(); - } - - public stop() { - this.running = false; - this.websocket!.close(); - } - - public onopen() { - wsReply(this.websocket!, new OB11LifeCycleEvent(LifeCycleSubType.CONNECT)); - } - - public async onmessage(msg: string) { - let receiveData: { action: ActionName | undefined, params: any, echo?: any } = { action: undefined, params: {} }; - let echo = null; - try { - receiveData = JSON.parse(msg.toString()); - echo = receiveData.echo; - //logDebug('收到反向Websocket消息', receiveData); - } catch (e) { - return wsReply(this.websocket!, OB11Response.error('json解析失败,请检查数据格式', 1400, echo)); - } - const action: BaseAction | undefined = actionMap.get(receiveData.action!); - if (!action) { - return wsReply(this.websocket!, OB11Response.error('不支持的api ' + receiveData.action, 1404, echo)); - } - try { - receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证 - const handleResult = await action.websocketHandle(receiveData.params, echo); - wsReply(this.websocket!, handleResult); - } catch (e) { - wsReply(this.websocket!, OB11Response.error(`api处理出错:${e}`, 1200, echo)); - } - } - - public onclose = () => { - logError('反向ws断开', this.url); - unregisterWsEventSender(this.websocket!); - if (this.running) { - this.reconnect(); - } - }; - - public send(msg: string) { - if (this.websocket && this.websocket.readyState == WebSocket.OPEN) { - this.websocket.send(msg); - } - } - - private reconnect() { - setTimeout(() => { - this.connect(); - }, 3000); // TODO: 重连间隔在配置文件中实现 - } - - private connect() { - const { token, heartInterval } = ob11Config; - this.websocket = new WebSocketClass(this.url, { - maxPayload: 1024 * 1024 * 1024, - handshakeTimeout: 2000, - perMessageDeflate: false, - headers: { - 'X-Self-ID': selfInfo.uin, - 'Authorization': `Bearer ${token}`, - 'x-client-role': 'Universal', // koishi-adapter-onebot 需要这个字段 - 'User-Agent': 'OneBot/11', - } - }); - registerWsEventSender(this.websocket); - logDebug('Trying to connect to the websocket server: ' + this.url); - - - this.websocket.on('open', () => { - logDebug('Connected to the websocket server: ' + this.url); - this.onopen(); - }); - - this.websocket.on('message', async (data) => { - await this.onmessage(data.toString()); - }); - - this.websocket.on('error', log); - - const wsClientInterval = setInterval(() => { - wsReply(this.websocket!, new OB11HeartbeatEvent(!!selfInfo.online, true, heartInterval)); - }, heartInterval); // 心跳包 - this.websocket.on('close', () => { - clearInterval(wsClientInterval); - logDebug('The websocket connection: ' + this.url + ' closed, trying reconnecting...'); - this.onclose(); - }); - } -} - -class OB11ReverseWebsockets { - start() { - for (const url of ob11Config.reverseWs.urls) { - log('开始连接反向ws', url); - new Promise(() => { - try { - rwsList.push(new ReverseWebsocket(url)); - } catch (e: any) { - logError(e.stack); - } - }).then(); - } - } - - stop() { - for (const rws of rwsList) { - rws.stop(); - } - rwsList = [];//清空旧的反向ws - } - - restart() { - this.stop(); - this.start(); - } -} - -export const ob11ReverseWebsockets = new OB11ReverseWebsockets(); - diff --git a/src/onebot11/server/ws/WebsocketServer.ts b/src/onebot11/server/ws/WebsocketServer.ts deleted file mode 100644 index 838de2a5..00000000 --- a/src/onebot11/server/ws/WebsocketServer.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { WebSocket } from 'ws'; -import http from 'http'; -import { actionMap } from '../../action'; -import { OB11Response } from '../../action/OB11Response'; -import { postWsEvent, registerWsEventSender, unregisterWsEventSender } from '../postOB11Event'; -import { ActionName } from '../../action/types'; -import BaseAction from '../../action/BaseAction'; -import { LifeCycleSubType, OB11LifeCycleEvent } from '../../event/meta/OB11LifeCycleEvent'; -import { OB11HeartbeatEvent } from '../../event/meta/OB11HeartbeatEvent'; -import { WebsocketServerBase } from '@/common/server/websocket'; -import { IncomingMessage } from 'node:http'; -import { wsReply } from './reply'; -import { napCatCore } from '@/core'; -import { log, logDebug, logError } from '../../../common/utils/log'; -import { ob11Config } from '@/onebot11/config'; -import { selfInfo } from '@/core/data'; - -const heartbeatRunning = false; - -class OB11WebsocketServer extends WebsocketServerBase { - - public start(port: number | http.Server, host: string = '') { - this.token = ob11Config.token; - super.start(port, host); - } - - authorizeFailed(wsClient: WebSocket) { - wsClient.send(JSON.stringify(OB11Response.res(null, 'failed', 1403, 'token验证失败'))); - } - - async handleAction(wsClient: WebSocket, actionName: string, params: any, echo?: any) { - const action: BaseAction | undefined = actionMap.get(actionName); - if (!action) { - return wsReply(wsClient, OB11Response.error('不支持的api ' + actionName, 1404, echo)); - } - try { - const handleResult = await action.websocketHandle(params, echo); - wsReply(wsClient, handleResult); - } catch (e: any) { - wsReply(wsClient, OB11Response.error(`api处理出错:${e.stack}`, 1200, echo)); - } - } - - onConnect(wsClient: WebSocket, url: string, req: IncomingMessage) { - if (url == '/api' || url == '/api/' || url == '/') { - wsClient.on('message', async (msg) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - let receiveData: { action: ActionName, params?: any, echo?: any } = { action: '', params: {} }; - let echo = null; - try { - receiveData = JSON.parse(msg.toString()); - echo = receiveData.echo; - logDebug('收到正向Websocket消息', receiveData); - } catch (e) { - return wsReply(wsClient, OB11Response.error('json解析失败,请检查数据格式', 1400, echo)); - } - receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证 - this.handleAction(wsClient, receiveData.action, receiveData.params, receiveData.echo).then(); - }); - } - if (url == '/event' || url == '/event/' || url == '/') { - registerWsEventSender(wsClient); - - logDebug('event上报ws客户端已连接'); - - try { - wsReply(wsClient, new OB11LifeCycleEvent(LifeCycleSubType.CONNECT)); - } catch (e) { - logError('发送生命周期失败', e); - } - const { heartInterval } = ob11Config; - const wsClientInterval = setInterval(() => { - wsReply(wsClient, new OB11HeartbeatEvent(!!selfInfo.online, true, heartInterval)); - }, heartInterval); // 心跳包 - wsClient.on('close', () => { - logError('event上报ws客户端已断开'); - clearInterval(wsClientInterval); - unregisterWsEventSender(wsClient); - }); - } - } -} - -export const ob11WebsocketServer = new OB11WebsocketServer(); - diff --git a/src/onebot11/server/ws/reply.ts b/src/onebot11/server/ws/reply.ts deleted file mode 100644 index 7e53a1c6..00000000 --- a/src/onebot11/server/ws/reply.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { WebSocket as WebSocketClass } from 'ws'; -import { OB11Response } from '../../action/OB11Response'; -import { PostEventType } from '../postOB11Event'; -import { log, logDebug, logError } from '@/common/utils/log'; -import { isNull } from '@/common/utils/helper'; - - -export function wsReply(wsClient: WebSocketClass, data: OB11Response | PostEventType) { - try { - const packet = Object.assign({}, data); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - if (isNull(packet['echo'])) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - delete packet['echo']; - } - wsClient.send(JSON.stringify(packet)); - logDebug('ws 消息上报', wsClient.url || '', data); - } catch (e: any) { - logError('websocket 回复失败', e.stack, data); - } -} diff --git a/src/onebot11/types/entity.ts b/src/onebot11/types/entity.ts deleted file mode 100644 index d17eab8b..00000000 --- a/src/onebot11/types/entity.ts +++ /dev/null @@ -1,65 +0,0 @@ -export interface OB11User { - user_id: number; - nickname: string; - remark?: string; - sex?: OB11UserSex; - level?: number; - age?: number; - qid?: string; - login_days?: number; - categroyName?:string; - categoryId?:number; -} - -export enum OB11UserSex { - male = 'male', - female = 'female', - unknown = 'unknown' -} - -export enum OB11GroupMemberRole { - owner = 'owner', - admin = 'admin', - member = 'member', -} - -export interface OB11GroupMember { - group_id: number - user_id: number - nickname: string - card?: string - sex?: OB11UserSex - age?: number - join_time?: number - last_sent_time?: number - level?: string - qq_level?: number - role?: OB11GroupMemberRole - title?: string - area?: string - unfriendly?: boolean - title_expire_time?: number - card_changeable?: boolean - // 以下为gocq字段 - shut_up_timestamp?: number - // 以下为扩展字段 - is_robot?: boolean - qage?: number -} - -export interface OB11Group { - group_id: number - group_name: string - member_count?: number - max_member_count?: number -} - -export interface OB11Sender { - user_id: number, - nickname: string, - sex?: OB11UserSex, - age?: number, - card?: string, // 群名片 - level?: string, // 群等级 - role?: OB11GroupMemberRole -} diff --git a/src/onebot11/types/index.ts b/src/onebot11/types/index.ts deleted file mode 100644 index e640c90d..00000000 --- a/src/onebot11/types/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './entity'; -export * from './message'; -export * from './meta'; diff --git a/src/onebot11/types/message.ts b/src/onebot11/types/message.ts deleted file mode 100644 index 18cfc25c..00000000 --- a/src/onebot11/types/message.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { OB11Sender } from './entity'; -import { EventType } from '@/onebot11/event/OB11BaseEvent'; -import { CustomMusicSignPostData, IdMusicSignPostData, PicSubType, RawMessage } from '@/core'; - -export enum OB11MessageType { - private = 'private', - group = 'group' -} - -export interface OB11Message { - target_id?: number; // 自己发送的消息才有此字段 - self_id?: number, - time: number, - message_id: number, - message_seq: number, // 和message_id一样 - real_id: number, - user_id: number, - group_id?: number, - message_type: 'private' | 'group', - sub_type?: 'friend' | 'group' | 'normal', - sender: OB11Sender, - message: OB11MessageData[] | string, - message_format: 'array' | 'string', - raw_message: string, - font: number, - post_type?: EventType, - raw?: RawMessage -} - -export interface OB11ForwardMessage extends OB11Message { - content: OB11MessageData[] | string; -} - -export interface OB11Return { - status: string - retcode: number - data: DataType - message: string, - echo?: any, // ws调用api才有此字段 - wording?: string, // go-cqhttp字段,错误信息 -} - -export enum OB11MessageDataType { - text = 'text', - image = 'image', - music = 'music', - video = 'video', - voice = 'record', - file = 'file', - at = 'at', - reply = 'reply', - json = 'json', - face = 'face', - mface = 'mface', // 商城表情 - markdown = 'markdown', - node = 'node', // 合并转发消息节点 - forward = 'forward', // 合并转发消息,用于上报 - xml = 'xml', - poke = 'poke', - dice = 'dice', - RPS = 'rps', - miniapp = 'miniapp',//json类 - Location = 'location' -} - -export interface OB11MessageMFace { - type: OB11MessageDataType.mface - data: { - emoji_package_id: number - emoji_id: string - key: string - summary: string - } -} - -export interface OB11MessageText { - type: OB11MessageDataType.text, - data: { - text: string, // 纯文本 - } -} - -export interface OB11MessageFileBase { - data: { - thumb?: string; - name?: string; - file: string, - url?: string; - } -} - - -export interface OB11MessageImage extends OB11MessageFileBase { - type: OB11MessageDataType.image - data: OB11MessageFileBase['data'] & { - summary?: string; // 图片摘要 - subType?: PicSubType - }, -} - -export interface OB11MessageRecord extends OB11MessageFileBase { - type: OB11MessageDataType.voice -} - -export interface OB11MessageFile extends OB11MessageFileBase { - type: OB11MessageDataType.file -} - -export interface OB11MessageVideo extends OB11MessageFileBase { - type: OB11MessageDataType.video -} - -export interface OB11MessageAt { - type: OB11MessageDataType.at - data: { - qq: `${number}` | 'all' - name?: string - } -} - -export interface OB11MessageReply { - type: OB11MessageDataType.reply - data: { - id: string - } -} - -export interface OB11MessageFace { - type: OB11MessageDataType.face - data: { - id: string - } -} - -export type OB11MessageMixType = OB11MessageData[] | string | OB11MessageData; - -export interface OB11MessageNode { - type: OB11MessageDataType.node - data: { - id?: string - user_id?: number - nickname: string - content: OB11MessageMixType - } -} - -export interface OB11MessageIdMusic { - type: OB11MessageDataType.music - data: IdMusicSignPostData -} -export interface OB11MessageCustomMusic { - type: OB11MessageDataType.music - data: Omit & { content?: string } -} - -export interface OB11MessageJson { - type: OB11MessageDataType.json - data: { config: { token: string } } & any -} - -export interface OB11MessageDice { - type: OB11MessageDataType.dice, - data: { - result: number - } -} -export interface OB11MessageRPS { - type: OB11MessageDataType.RPS, - data: { - result: number - } -} - -export interface OB11MessageMarkdown { - type: OB11MessageDataType.markdown - data: { - content: string - } -} - -export interface OB11MessageForward { - type: OB11MessageDataType.forward - data: { - id: string, - content: OB11Message[] - } -} - -export type OB11MessageData = - OB11MessageText | - OB11MessageFace | OB11MessageMFace | - OB11MessageAt | OB11MessageReply | - OB11MessageImage | OB11MessageRecord | OB11MessageFile | OB11MessageVideo | - OB11MessageNode | OB11MessageIdMusic | OB11MessageCustomMusic | OB11MessageJson | - OB11MessageDice | OB11MessageRPS | OB11MessageMarkdown | OB11MessageForward - -export interface OB11PostSendMsg { - message_type?: 'private' | 'group' - user_id?: string, - group_id?: string, - message: OB11MessageMixType; - messages?: OB11MessageMixType; // 兼容 go-cqhttp - auto_escape?: boolean | string -} diff --git a/src/onebot11/types/meta.ts b/src/onebot11/types/meta.ts deleted file mode 100644 index 768dde54..00000000 --- a/src/onebot11/types/meta.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { stat } from '@/core/data'; - -export interface OB11Version { - app_name: string - app_version: string - protocol_version: 'v11' -} - -export interface OB11Status { - online: boolean | null, - good: boolean, - stat: typeof stat -} diff --git a/src/onebot11/version.ts b/src/onebot11/version.ts deleted file mode 100644 index 875bf1ac..00000000 --- a/src/onebot11/version.ts +++ /dev/null @@ -1 +0,0 @@ -export const version = '1.8.3'; diff --git a/src/proto/SysMessage.DeviceChange.proto b/src/proto/SysMessage.DeviceChange.proto deleted file mode 100644 index 3ea5cceb..00000000 --- a/src/proto/SysMessage.DeviceChange.proto +++ /dev/null @@ -1,32 +0,0 @@ -syntax = "proto3"; -package SysMessage; -message Data { - repeated Header header = 1; - repeated Body body = 2; - repeated Event event = 3; -} -message Event { - repeated Content content = 2; -} -message Devices { - string deviceName = 5; - string appname = 9; -} -message Content { -repeated Devices devices = 5; -} -message Header { - uint32 PeerNumber = 1; - string PeerString = 2; - uint32 Uin = 5; - optional string Uid = 6; - } -message Body { - uint32 MsgType = 1; - uint32 SubType_0 = 2; - uint32 SubType_1 = 3; - uint32 MsgSeq= 5; - uint32 Time = 6; - uint64 MsgID = 12; - uint32 Other = 13; -} \ No newline at end of file diff --git a/src/proto/SysMessage.DeviceChange.ts b/src/proto/SysMessage.DeviceChange.ts deleted file mode 100644 index a25fa969..00000000 --- a/src/proto/SysMessage.DeviceChange.ts +++ /dev/null @@ -1,491 +0,0 @@ -// @generated by protobuf-ts 2.9.4 -// @generated from protobuf file "SysMessage.DeviceChange.proto" (package "SysMessage", syntax proto3) -// tslint:disable -import type { BinaryWriteOptions } from "@protobuf-ts/runtime"; -import type { IBinaryWriter } from "@protobuf-ts/runtime"; -import { WireType } from "@protobuf-ts/runtime"; -import type { BinaryReadOptions } from "@protobuf-ts/runtime"; -import type { IBinaryReader } from "@protobuf-ts/runtime"; -import { UnknownFieldHandler } from "@protobuf-ts/runtime"; -import type { PartialMessage } from "@protobuf-ts/runtime"; -import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MessageType } from "@protobuf-ts/runtime"; -/** - * @generated from protobuf message SysMessage.Data - */ -export interface Data { - /** - * @generated from protobuf field: repeated SysMessage.Header header = 1; - */ - header: Header[]; - /** - * @generated from protobuf field: repeated SysMessage.Body body = 2; - */ - body: Body[]; - /** - * @generated from protobuf field: repeated SysMessage.Event event = 3; - */ - event: Event[]; -} -/** - * @generated from protobuf message SysMessage.Event - */ -export interface Event { - /** - * @generated from protobuf field: repeated SysMessage.Content content = 2; - */ - content: Content[]; -} -/** - * @generated from protobuf message SysMessage.Devices - */ -export interface Devices { - /** - * @generated from protobuf field: string deviceName = 5; - */ - deviceName: string; - /** - * @generated from protobuf field: string appname = 9; - */ - appname: string; -} -/** - * @generated from protobuf message SysMessage.Content - */ -export interface Content { - /** - * @generated from protobuf field: repeated SysMessage.Devices devices = 5; - */ - devices: Devices[]; -} -/** - * @generated from protobuf message SysMessage.Header - */ -export interface Header { - /** - * @generated from protobuf field: uint32 PeerNumber = 1 [json_name = "PeerNumber"]; - */ - peerNumber: number; - /** - * @generated from protobuf field: string PeerString = 2 [json_name = "PeerString"]; - */ - peerString: string; - /** - * @generated from protobuf field: uint32 Uin = 5 [json_name = "Uin"]; - */ - uin: number; - /** - * @generated from protobuf field: optional string Uid = 6 [json_name = "Uid"]; - */ - uid?: string; -} -/** - * @generated from protobuf message SysMessage.Body - */ -export interface Body { - /** - * @generated from protobuf field: uint32 MsgType = 1 [json_name = "MsgType"]; - */ - msgType: number; - /** - * @generated from protobuf field: uint32 SubType_0 = 2 [json_name = "SubType0"]; - */ - subType0: number; - /** - * @generated from protobuf field: uint32 SubType_1 = 3 [json_name = "SubType1"]; - */ - subType1: number; - /** - * @generated from protobuf field: uint32 MsgSeq = 5 [json_name = "MsgSeq"]; - */ - msgSeq: number; - /** - * @generated from protobuf field: uint32 Time = 6 [json_name = "Time"]; - */ - time: number; - /** - * @generated from protobuf field: uint64 MsgID = 12 [json_name = "MsgID"]; - */ - msgID: bigint; - /** - * @generated from protobuf field: uint32 Other = 13 [json_name = "Other"]; - */ - other: number; -} -// @generated message type with reflection information, may provide speed optimized methods -class Data$Type extends MessageType { - constructor() { - super("SysMessage.Data", [ - { no: 1, name: "header", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Header }, - { no: 2, name: "body", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Body }, - { no: 3, name: "event", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Event } - ]); - } - create(value?: PartialMessage): Data { - const message = globalThis.Object.create((this.messagePrototype!)); - message.header = []; - message.body = []; - message.event = []; - if (value !== undefined) - reflectionMergePartial(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Data): Data { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* repeated SysMessage.Header header */ 1: - message.header.push(Header.internalBinaryRead(reader, reader.uint32(), options)); - break; - case /* repeated SysMessage.Body body */ 2: - message.body.push(Body.internalBinaryRead(reader, reader.uint32(), options)); - break; - case /* repeated SysMessage.Event event */ 3: - message.event.push(Event.internalBinaryRead(reader, reader.uint32(), options)); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Data, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* repeated SysMessage.Header header = 1; */ - for (let i = 0; i < message.header.length; i++) - Header.internalBinaryWrite(message.header[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join(); - /* repeated SysMessage.Body body = 2; */ - for (let i = 0; i < message.body.length; i++) - Body.internalBinaryWrite(message.body[i], writer.tag(2, WireType.LengthDelimited).fork(), options).join(); - /* repeated SysMessage.Event event = 3; */ - for (let i = 0; i < message.event.length; i++) - Event.internalBinaryWrite(message.event[i], writer.tag(3, WireType.LengthDelimited).fork(), options).join(); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message SysMessage.Data - */ -export const Data = new Data$Type(); -// @generated message type with reflection information, may provide speed optimized methods -class Event$Type extends MessageType { - constructor() { - super("SysMessage.Event", [ - { no: 2, name: "content", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Content } - ]); - } - create(value?: PartialMessage): Event { - const message = globalThis.Object.create((this.messagePrototype!)); - message.content = []; - if (value !== undefined) - reflectionMergePartial(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Event): Event { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* repeated SysMessage.Content content */ 2: - message.content.push(Content.internalBinaryRead(reader, reader.uint32(), options)); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Event, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* repeated SysMessage.Content content = 2; */ - for (let i = 0; i < message.content.length; i++) - Content.internalBinaryWrite(message.content[i], writer.tag(2, WireType.LengthDelimited).fork(), options).join(); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message SysMessage.Event - */ -export const Event = new Event$Type(); -// @generated message type with reflection information, may provide speed optimized methods -class Devices$Type extends MessageType { - constructor() { - super("SysMessage.Devices", [ - { no: 5, name: "deviceName", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, - { no: 9, name: "appname", kind: "scalar", T: 9 /*ScalarType.STRING*/ } - ]); - } - create(value?: PartialMessage): Devices { - const message = globalThis.Object.create((this.messagePrototype!)); - message.deviceName = ""; - message.appname = ""; - if (value !== undefined) - reflectionMergePartial(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Devices): Devices { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* string deviceName */ 5: - message.deviceName = reader.string(); - break; - case /* string appname */ 9: - message.appname = reader.string(); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Devices, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* string deviceName = 5; */ - if (message.deviceName !== "") - writer.tag(5, WireType.LengthDelimited).string(message.deviceName); - /* string appname = 9; */ - if (message.appname !== "") - writer.tag(9, WireType.LengthDelimited).string(message.appname); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message SysMessage.Devices - */ -export const Devices = new Devices$Type(); -// @generated message type with reflection information, may provide speed optimized methods -class Content$Type extends MessageType { - constructor() { - super("SysMessage.Content", [ - { no: 5, name: "devices", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Devices } - ]); - } - create(value?: PartialMessage): Content { - const message = globalThis.Object.create((this.messagePrototype!)); - message.devices = []; - if (value !== undefined) - reflectionMergePartial(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Content): Content { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* repeated SysMessage.Devices devices */ 5: - message.devices.push(Devices.internalBinaryRead(reader, reader.uint32(), options)); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Content, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* repeated SysMessage.Devices devices = 5; */ - for (let i = 0; i < message.devices.length; i++) - Devices.internalBinaryWrite(message.devices[i], writer.tag(5, WireType.LengthDelimited).fork(), options).join(); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message SysMessage.Content - */ -export const Content = new Content$Type(); -// @generated message type with reflection information, may provide speed optimized methods -class Header$Type extends MessageType
{ - constructor() { - super("SysMessage.Header", [ - { no: 1, name: "PeerNumber", kind: "scalar", jsonName: "PeerNumber", T: 13 /*ScalarType.UINT32*/ }, - { no: 2, name: "PeerString", kind: "scalar", jsonName: "PeerString", T: 9 /*ScalarType.STRING*/ }, - { no: 5, name: "Uin", kind: "scalar", jsonName: "Uin", T: 13 /*ScalarType.UINT32*/ }, - { no: 6, name: "Uid", kind: "scalar", jsonName: "Uid", opt: true, T: 9 /*ScalarType.STRING*/ } - ]); - } - create(value?: PartialMessage
): Header { - const message = globalThis.Object.create((this.messagePrototype!)); - message.peerNumber = 0; - message.peerString = ""; - message.uin = 0; - if (value !== undefined) - reflectionMergePartial
(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Header): Header { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* uint32 PeerNumber = 1 [json_name = "PeerNumber"];*/ 1: - message.peerNumber = reader.uint32(); - break; - case /* string PeerString = 2 [json_name = "PeerString"];*/ 2: - message.peerString = reader.string(); - break; - case /* uint32 Uin = 5 [json_name = "Uin"];*/ 5: - message.uin = reader.uint32(); - break; - case /* optional string Uid = 6 [json_name = "Uid"];*/ 6: - message.uid = reader.string(); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Header, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* uint32 PeerNumber = 1 [json_name = "PeerNumber"]; */ - if (message.peerNumber !== 0) - writer.tag(1, WireType.Varint).uint32(message.peerNumber); - /* string PeerString = 2 [json_name = "PeerString"]; */ - if (message.peerString !== "") - writer.tag(2, WireType.LengthDelimited).string(message.peerString); - /* uint32 Uin = 5 [json_name = "Uin"]; */ - if (message.uin !== 0) - writer.tag(5, WireType.Varint).uint32(message.uin); - /* optional string Uid = 6 [json_name = "Uid"]; */ - if (message.uid !== undefined) - writer.tag(6, WireType.LengthDelimited).string(message.uid); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message SysMessage.Header - */ -export const Header = new Header$Type(); -// @generated message type with reflection information, may provide speed optimized methods -class Body$Type extends MessageType { - constructor() { - super("SysMessage.Body", [ - { no: 1, name: "MsgType", kind: "scalar", jsonName: "MsgType", T: 13 /*ScalarType.UINT32*/ }, - { no: 2, name: "SubType_0", kind: "scalar", jsonName: "SubType0", T: 13 /*ScalarType.UINT32*/ }, - { no: 3, name: "SubType_1", kind: "scalar", jsonName: "SubType1", T: 13 /*ScalarType.UINT32*/ }, - { no: 5, name: "MsgSeq", kind: "scalar", jsonName: "MsgSeq", T: 13 /*ScalarType.UINT32*/ }, - { no: 6, name: "Time", kind: "scalar", jsonName: "Time", T: 13 /*ScalarType.UINT32*/ }, - { no: 12, name: "MsgID", kind: "scalar", jsonName: "MsgID", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 13, name: "Other", kind: "scalar", jsonName: "Other", T: 13 /*ScalarType.UINT32*/ } - ]); - } - create(value?: PartialMessage): Body { - const message = globalThis.Object.create((this.messagePrototype!)); - message.msgType = 0; - message.subType0 = 0; - message.subType1 = 0; - message.msgSeq = 0; - message.time = 0; - message.msgID = 0n; - message.other = 0; - if (value !== undefined) - reflectionMergePartial(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Body): Body { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* uint32 MsgType = 1 [json_name = "MsgType"];*/ 1: - message.msgType = reader.uint32(); - break; - case /* uint32 SubType_0 = 2 [json_name = "SubType0"];*/ 2: - message.subType0 = reader.uint32(); - break; - case /* uint32 SubType_1 = 3 [json_name = "SubType1"];*/ 3: - message.subType1 = reader.uint32(); - break; - case /* uint32 MsgSeq = 5 [json_name = "MsgSeq"];*/ 5: - message.msgSeq = reader.uint32(); - break; - case /* uint32 Time = 6 [json_name = "Time"];*/ 6: - message.time = reader.uint32(); - break; - case /* uint64 MsgID = 12 [json_name = "MsgID"];*/ 12: - message.msgID = reader.uint64().toBigInt(); - break; - case /* uint32 Other = 13 [json_name = "Other"];*/ 13: - message.other = reader.uint32(); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Body, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* uint32 MsgType = 1 [json_name = "MsgType"]; */ - if (message.msgType !== 0) - writer.tag(1, WireType.Varint).uint32(message.msgType); - /* uint32 SubType_0 = 2 [json_name = "SubType0"]; */ - if (message.subType0 !== 0) - writer.tag(2, WireType.Varint).uint32(message.subType0); - /* uint32 SubType_1 = 3 [json_name = "SubType1"]; */ - if (message.subType1 !== 0) - writer.tag(3, WireType.Varint).uint32(message.subType1); - /* uint32 MsgSeq = 5 [json_name = "MsgSeq"]; */ - if (message.msgSeq !== 0) - writer.tag(5, WireType.Varint).uint32(message.msgSeq); - /* uint32 Time = 6 [json_name = "Time"]; */ - if (message.time !== 0) - writer.tag(6, WireType.Varint).uint32(message.time); - /* uint64 MsgID = 12 [json_name = "MsgID"]; */ - if (message.msgID !== 0n) - writer.tag(12, WireType.Varint).uint64(message.msgID); - /* uint32 Other = 13 [json_name = "Other"]; */ - if (message.other !== 0) - writer.tag(13, WireType.Varint).uint32(message.other); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message SysMessage.Body - */ -export const Body = new Body$Type(); diff --git a/src/proto/SysMessage.MemberDecrease.proto b/src/proto/SysMessage.MemberDecrease.proto deleted file mode 100644 index 062a660a..00000000 --- a/src/proto/SysMessage.MemberDecrease.proto +++ /dev/null @@ -1,28 +0,0 @@ -syntax = "proto3"; -package SysMessage; -message Data { - repeated Header header = 1; - repeated Body body = 2; - repeated Other other = 2; -} -message Header { - uint32 PeerNumber = 1; - string PeerString = 2; - uint32 Uin = 5; - optional string Uid = 6; - } -message Body { - uint32 MsgType = 1; - uint32 SubType_0 = 2; - uint32 SubType_1 = 3; - uint32 MsgSeq= 5; - uint32 Time = 6; - uint64 MsgID = 12; - uint32 Other = 13; -} -message Event { - -} -message Other { - repeated Event event = 2; -} diff --git a/src/proto/SysMessage.proto b/src/proto/SysMessage.proto deleted file mode 100644 index 762c768c..00000000 --- a/src/proto/SysMessage.proto +++ /dev/null @@ -1,21 +0,0 @@ -syntax = "proto3"; -package SysMessage; -message Data { - repeated Header header = 1; - repeated Body body = 2; -} -message Header { - uint32 PeerNumber = 1; - string PeerString = 2; - uint32 Uin = 5; - optional string Uid = 6; - } -message Body { - uint32 MsgType = 1; - uint32 SubType_0 = 2; - uint32 SubType_1 = 3; - uint32 MsgSeq= 5; - uint32 Time = 6; - uint64 MsgID = 12; - uint32 Other = 13; -} \ No newline at end of file diff --git a/src/proto/SysMessage.ts b/src/proto/SysMessage.ts deleted file mode 100644 index 8423361d..00000000 --- a/src/proto/SysMessage.ts +++ /dev/null @@ -1,299 +0,0 @@ -// @generated by protobuf-ts 2.9.4 -// @generated from protobuf file "SysMessage.proto" (package "SysMessage", syntax proto3) -// tslint:disable -import type { BinaryWriteOptions } from "@protobuf-ts/runtime"; -import type { IBinaryWriter } from "@protobuf-ts/runtime"; -import { WireType } from "@protobuf-ts/runtime"; -import type { BinaryReadOptions } from "@protobuf-ts/runtime"; -import type { IBinaryReader } from "@protobuf-ts/runtime"; -import { UnknownFieldHandler } from "@protobuf-ts/runtime"; -import type { PartialMessage } from "@protobuf-ts/runtime"; -import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MessageType } from "@protobuf-ts/runtime"; -/** - * @generated from protobuf message SysMessage.Data - */ -export interface Data { - /** - * @generated from protobuf field: repeated SysMessage.Header header = 1; - */ - header: Header[]; - /** - * @generated from protobuf field: repeated SysMessage.Body body = 2; - */ - body: Body[]; -} -/** - * @generated from protobuf message SysMessage.Header - */ -export interface Header { - /** - * @generated from protobuf field: uint32 PeerNumber = 1 [json_name = "PeerNumber"]; - */ - peerNumber: number; - /** - * @generated from protobuf field: string PeerString = 2 [json_name = "PeerString"]; - */ - peerString: string; - /** - * @generated from protobuf field: uint32 Uin = 5 [json_name = "Uin"]; - */ - uin: number; - /** - * @generated from protobuf field: optional string Uid = 6 [json_name = "Uid"]; - */ - uid?: string; -} -/** - * @generated from protobuf message SysMessage.Body - */ -export interface Body { - /** - * @generated from protobuf field: uint32 MsgType = 1 [json_name = "MsgType"]; - */ - msgType: number; - /** - * @generated from protobuf field: uint32 SubType_0 = 2 [json_name = "SubType0"]; - */ - subType0: number; - /** - * @generated from protobuf field: uint32 SubType_1 = 3 [json_name = "SubType1"]; - */ - subType1: number; - /** - * @generated from protobuf field: uint32 MsgSeq = 5 [json_name = "MsgSeq"]; - */ - msgSeq: number; - /** - * @generated from protobuf field: uint32 Time = 6 [json_name = "Time"]; - */ - time: number; - /** - * @generated from protobuf field: uint64 MsgID = 12 [json_name = "MsgID"]; - */ - msgID: bigint; - /** - * @generated from protobuf field: uint32 Other = 13 [json_name = "Other"]; - */ - other: number; -} -// @generated message type with reflection information, may provide speed optimized methods -class Data$Type extends MessageType { - constructor() { - super("SysMessage.Data", [ - { no: 1, name: "header", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Header }, - { no: 2, name: "body", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Body } - ]); - } - create(value?: PartialMessage): Data { - const message = globalThis.Object.create((this.messagePrototype!)); - message.header = []; - message.body = []; - if (value !== undefined) - reflectionMergePartial(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Data): Data { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* repeated SysMessage.Header header */ 1: - message.header.push(Header.internalBinaryRead(reader, reader.uint32(), options)); - break; - case /* repeated SysMessage.Body body */ 2: - message.body.push(Body.internalBinaryRead(reader, reader.uint32(), options)); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Data, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* repeated SysMessage.Header header = 1; */ - for (let i = 0; i < message.header.length; i++) - Header.internalBinaryWrite(message.header[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join(); - /* repeated SysMessage.Body body = 2; */ - for (let i = 0; i < message.body.length; i++) - Body.internalBinaryWrite(message.body[i], writer.tag(2, WireType.LengthDelimited).fork(), options).join(); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message SysMessage.Data - */ -export const Data = new Data$Type(); -// @generated message type with reflection information, may provide speed optimized methods -class Header$Type extends MessageType
{ - constructor() { - super("SysMessage.Header", [ - { no: 1, name: "PeerNumber", kind: "scalar", jsonName: "PeerNumber", T: 13 /*ScalarType.UINT32*/ }, - { no: 2, name: "PeerString", kind: "scalar", jsonName: "PeerString", T: 9 /*ScalarType.STRING*/ }, - { no: 5, name: "Uin", kind: "scalar", jsonName: "Uin", T: 13 /*ScalarType.UINT32*/ }, - { no: 6, name: "Uid", kind: "scalar", jsonName: "Uid", opt: true, T: 9 /*ScalarType.STRING*/ } - ]); - } - create(value?: PartialMessage
): Header { - const message = globalThis.Object.create((this.messagePrototype!)); - message.peerNumber = 0; - message.peerString = ""; - message.uin = 0; - if (value !== undefined) - reflectionMergePartial
(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Header): Header { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* uint32 PeerNumber = 1 [json_name = "PeerNumber"];*/ 1: - message.peerNumber = reader.uint32(); - break; - case /* string PeerString = 2 [json_name = "PeerString"];*/ 2: - message.peerString = reader.string(); - break; - case /* uint32 Uin = 5 [json_name = "Uin"];*/ 5: - message.uin = reader.uint32(); - break; - case /* optional string Uid = 6 [json_name = "Uid"];*/ 6: - message.uid = reader.string(); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Header, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* uint32 PeerNumber = 1 [json_name = "PeerNumber"]; */ - if (message.peerNumber !== 0) - writer.tag(1, WireType.Varint).uint32(message.peerNumber); - /* string PeerString = 2 [json_name = "PeerString"]; */ - if (message.peerString !== "") - writer.tag(2, WireType.LengthDelimited).string(message.peerString); - /* uint32 Uin = 5 [json_name = "Uin"]; */ - if (message.uin !== 0) - writer.tag(5, WireType.Varint).uint32(message.uin); - /* optional string Uid = 6 [json_name = "Uid"]; */ - if (message.uid !== undefined) - writer.tag(6, WireType.LengthDelimited).string(message.uid); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message SysMessage.Header - */ -export const Header = new Header$Type(); -// @generated message type with reflection information, may provide speed optimized methods -class Body$Type extends MessageType { - constructor() { - super("SysMessage.Body", [ - { no: 1, name: "MsgType", kind: "scalar", jsonName: "MsgType", T: 13 /*ScalarType.UINT32*/ }, - { no: 2, name: "SubType_0", kind: "scalar", jsonName: "SubType0", T: 13 /*ScalarType.UINT32*/ }, - { no: 3, name: "SubType_1", kind: "scalar", jsonName: "SubType1", T: 13 /*ScalarType.UINT32*/ }, - { no: 5, name: "MsgSeq", kind: "scalar", jsonName: "MsgSeq", T: 13 /*ScalarType.UINT32*/ }, - { no: 6, name: "Time", kind: "scalar", jsonName: "Time", T: 13 /*ScalarType.UINT32*/ }, - { no: 12, name: "MsgID", kind: "scalar", jsonName: "MsgID", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 13, name: "Other", kind: "scalar", jsonName: "Other", T: 13 /*ScalarType.UINT32*/ } - ]); - } - create(value?: PartialMessage): Body { - const message = globalThis.Object.create((this.messagePrototype!)); - message.msgType = 0; - message.subType0 = 0; - message.subType1 = 0; - message.msgSeq = 0; - message.time = 0; - message.msgID = 0n; - message.other = 0; - if (value !== undefined) - reflectionMergePartial(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Body): Body { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* uint32 MsgType = 1 [json_name = "MsgType"];*/ 1: - message.msgType = reader.uint32(); - break; - case /* uint32 SubType_0 = 2 [json_name = "SubType0"];*/ 2: - message.subType0 = reader.uint32(); - break; - case /* uint32 SubType_1 = 3 [json_name = "SubType1"];*/ 3: - message.subType1 = reader.uint32(); - break; - case /* uint32 MsgSeq = 5 [json_name = "MsgSeq"];*/ 5: - message.msgSeq = reader.uint32(); - break; - case /* uint32 Time = 6 [json_name = "Time"];*/ 6: - message.time = reader.uint32(); - break; - case /* uint64 MsgID = 12 [json_name = "MsgID"];*/ 12: - message.msgID = reader.uint64().toBigInt(); - break; - case /* uint32 Other = 13 [json_name = "Other"];*/ 13: - message.other = reader.uint32(); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Body, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* uint32 MsgType = 1 [json_name = "MsgType"]; */ - if (message.msgType !== 0) - writer.tag(1, WireType.Varint).uint32(message.msgType); - /* uint32 SubType_0 = 2 [json_name = "SubType0"]; */ - if (message.subType0 !== 0) - writer.tag(2, WireType.Varint).uint32(message.subType0); - /* uint32 SubType_1 = 3 [json_name = "SubType1"]; */ - if (message.subType1 !== 0) - writer.tag(3, WireType.Varint).uint32(message.subType1); - /* uint32 MsgSeq = 5 [json_name = "MsgSeq"]; */ - if (message.msgSeq !== 0) - writer.tag(5, WireType.Varint).uint32(message.msgSeq); - /* uint32 Time = 6 [json_name = "Time"]; */ - if (message.time !== 0) - writer.tag(6, WireType.Varint).uint32(message.time); - /* uint64 MsgID = 12 [json_name = "MsgID"]; */ - if (message.msgID !== 0n) - writer.tag(12, WireType.Varint).uint64(message.msgID); - /* uint32 Other = 13 [json_name = "Other"]; */ - if (message.other !== 0) - writer.tag(13, WireType.Varint).uint32(message.other); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message SysMessage.Body - */ -export const Body = new Body$Type(); diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts deleted file mode 100644 index d4d12c26..00000000 --- a/src/vite-env.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -/// - -interface ImportMetaEnv { - VITE_BUILD_TYPE: string -} - -interface ImportMeta { - readonly env: ImportMetaEnv -} \ No newline at end of file diff --git a/src/webui/Readme.md b/src/webui/Readme.md deleted file mode 100644 index c79d50bd..00000000 --- a/src/webui/Readme.md +++ /dev/null @@ -1,2 +0,0 @@ -# The Path of NapCatQQ -Tiny WebUi for NapCatQQ \ No newline at end of file diff --git a/src/webui/index.ts b/src/webui/index.ts deleted file mode 100644 index ed65bd81..00000000 --- a/src/webui/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import express from 'express'; -import { NextFunction, Request, Response } from 'express'; -import { AuthHelper } from './src/helper/SignToken'; -import { resolve } from 'node:path'; -import { ALLRouter } from './src/router'; -import { WebUiConfig } from './src/helper/config'; -const app = express(); -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { log } from '@/common/utils/log'; - - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -/** - * 初始化并启动WebUI服务。 - * 该函数配置了Express服务器以支持JSON解析和静态文件服务,并监听6099端口。 - * 无需参数。 - * @returns {Promise} 无返回值。 - */ -export async function InitWebUi() { - const config = await WebUiConfig.GetWebUIConfig(); - if (config.port == 0) { - log('[NapCat] [WebUi] Current WebUi is not run.'); - return; - } - app.use(express.json()); - // 初始服务 - // WebUI只在config.prefix所示路径上提供服务,可配合Nginx挂载到子目录中 - app.all(config.prefix + '/', (_req, res) => { - res.json({ - msg: 'NapCat WebAPI is now running!', - }); - }); - // 配置静态文件服务,提供./static目录下的文件服务,访问路径为/webui - app.use(config.prefix + '/webui', express.static(resolve(__dirname, './static'))); - //挂载API接口 - app.use(config.prefix + '/api', ALLRouter); - app.listen(config.port, config.host, async () => { - log(`[NapCat] [WebUi] Current WebUi is running at http://${config.host}:${config.port}${config.prefix}`); - log(`[NapCat] [WebUi] Login URL is http://${config.host}:${config.port}${config.prefix}/webui`); - log(`[NapCat] [WebUi] Login Token is ${config.token}`); - }); -} diff --git a/src/webui/src/api/Auth.ts b/src/webui/src/api/Auth.ts deleted file mode 100644 index 7f8e9d8c..00000000 --- a/src/webui/src/api/Auth.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { RequestHandler } from 'express'; -import { AuthHelper } from '../helper/SignToken'; -import { WebUiConfig } from '../helper/config'; -import { WebUiDataRuntime } from '../helper/Data'; -const isEmpty = (data: any) => data === undefined || data === null || data === ''; -export const LoginHandler: RequestHandler = async (req, res) => { - const WebUiConfigData = await WebUiConfig.GetWebUIConfig(); - const { token } = req.body; - if (isEmpty(token)) { - res.json({ - code: -1, - message: 'token is empty' - }); - return; - } - if (!await WebUiDataRuntime.checkLoginRate(WebUiConfigData.loginRate)) { - res.json({ - code: -1, - message: 'login rate limit' - }); - return; - } - //验证config.token是否等于token - if (WebUiConfigData.token !== token) { - res.json({ - code: -1, - message: 'token is invalid' - }); - return; - } - const signCredential = Buffer.from(JSON.stringify(await AuthHelper.signCredential(WebUiConfigData.token))).toString('base64'); - res.json({ - code: 0, - message: 'success', - data: { - 'Credential': signCredential - } - }); - return; -}; -export const LogoutHandler: RequestHandler = (req, res) => { - // 这玩意无状态销毁个灯 得想想办法 - res.json({ - code: 0, - message: 'success' - }); - return; -}; -export const checkHandler: RequestHandler = async (req, res) => { - const WebUiConfigData = await WebUiConfig.GetWebUIConfig(); - const authorization = req.headers.authorization; - try { - const CredentialBase64:string = authorization?.split(' ')[1] as string; - const Credential = JSON.parse(Buffer.from(CredentialBase64, 'base64').toString()); - await AuthHelper.validateCredentialWithinOneHour(WebUiConfigData.token,Credential); - res.json({ - code: 0, - message: 'success' - }); - return; - } catch (e) { - res.json({ - code: -1, - message: 'failed' - }); - } - return; -}; diff --git a/src/webui/src/api/LogConsole.ts b/src/webui/src/api/LogConsole.ts deleted file mode 100644 index 68eec759..00000000 --- a/src/webui/src/api/LogConsole.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { RequestHandler } from 'express'; -import { resolve } from 'path'; -import { readdir, stat } from 'fs/promises'; -import { existsSync } from 'fs'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; - - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); -export const GetLogFileListHandler: RequestHandler = async (req, res) => { - try { - const LogsPath = resolve(__dirname, './logs/'); - const LogFiles = await readdir(LogsPath); - res.json({ - code: 0, - data: LogFiles - }); - } catch (error) { - res.json({ code: -1, msg: 'Failed to retrieve log file list.' }); - } -}; - -export const GetLogFileHandler: RequestHandler = async (req, res) => { - const LogsPath = resolve(__dirname, './logs/'); - const LogFile = req.query.file as string; - - // if (!isValidFileName(LogFile)) { - // res.json({ code: -1, msg: 'LogFile is not safe' }); - // return; - // } - - const filePath = `${LogsPath}/${LogFile}`; - if (!existsSync(filePath)) { - res.status(404).json({ code: -1, msg: 'LogFile does not exist' }); - return; - } - - try { - const fileStats = await stat(filePath); - if (!fileStats.isFile()) { - res.json({ code: -1, msg: 'LogFile must be a file' }); - return; - } - - res.sendFile(filePath); - } catch (error) { - res.json({ code: -1, msg: 'Failed to send log file.' }); - } -}; -// export function isValidFileName(fileName: string): boolean { -// const invalidChars = /[\.\:\*\?\"\<\>\|\/\\]/; -// return !invalidChars.test(fileName); -// } \ No newline at end of file diff --git a/src/webui/src/api/OB11Config.ts b/src/webui/src/api/OB11Config.ts deleted file mode 100644 index 1a3ffd50..00000000 --- a/src/webui/src/api/OB11Config.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { RequestHandler } from 'express'; -import { WebUiDataRuntime } from '../helper/Data'; -import { existsSync, readFileSync, writeFileSync } from 'node:fs'; -import { resolve } from 'node:path'; -import { OB11Config } from '@/webui/ui/components/WebUiApiOB11Config'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; - - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -const isEmpty = (data: any) => - data === undefined || data === null || data === ''; -export const OB11GetConfigHandler: RequestHandler = async (req, res) => { - const isLogin = await WebUiDataRuntime.getQQLoginStatus(); - if (!isLogin) { - res.send({ - code: -1, - message: 'Not Login', - }); - return; - } - const uin = await WebUiDataRuntime.getQQLoginUin(); - const configFilePath = resolve(__dirname, `./config/onebot11_${uin}.json`); - //console.log(configFilePath); - let data: OB11Config; - try { - data = JSON.parse( - existsSync(configFilePath) - ? readFileSync(configFilePath).toString() - : readFileSync(resolve(__dirname, './config/onebot11.json')).toString() - ); - } catch (e) { - data = {} as OB11Config; - res.send({ - code: -1, - message: 'Config Get Error', - }); - return; - } - res.send({ - code: 0, - message: 'success', - data: data, - }); - return; -}; -export const OB11SetConfigHandler: RequestHandler = async (req, res) => { - const isLogin = await WebUiDataRuntime.getQQLoginStatus(); - if (!isLogin) { - res.send({ - code: -1, - message: 'Not Login', - }); - return; - } - if (isEmpty(req.body.config)) { - res.send({ - code: -1, - message: 'config is empty', - }); - return; - } - let SetResult; - try { - await WebUiDataRuntime.setOB11Config(JSON.parse(req.body.config)); - SetResult = true; - } catch (e) { - SetResult = false; - } - - // let configFilePath = resolve(__dirname, `./config/onebot11_${await WebUiDataRuntime.getQQLoginUin()}.json`); - // try { - // JSON.parse(req.body.config) - // readFileSync(configFilePath); - // } - // catch (e) { - // //console.log(e); - // configFilePath = resolve(__dirname, `./config/onebot11.json`); - // } - // //console.log(configFilePath,JSON.parse(req.body.config)); - // writeFileSync(configFilePath, JSON.stringify(JSON.parse(req.body.config), null, 4)); - if (SetResult) { - res.send({ - code: 0, - message: 'success', - }); - } else { - res.send({ - code: -1, - message: 'Config Set Error', - }); - } - - return; -}; diff --git a/src/webui/src/api/QQLogin.ts b/src/webui/src/api/QQLogin.ts deleted file mode 100644 index 84355f62..00000000 --- a/src/webui/src/api/QQLogin.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { RequestHandler } from 'express'; -import { WebUiDataRuntime } from '../helper/Data'; -import { sleep } from '@/common/utils/helper'; -const isEmpty = (data: any) => data === undefined || data === null || data === ''; -export const QQGetQRcodeHandler: RequestHandler = async (req, res) => { - if (await WebUiDataRuntime.getQQLoginStatus()) { - res.send({ - code: -1, - message: 'QQ Is Logined' - }); - return; - } - const qrcodeUrl = await WebUiDataRuntime.getQQLoginQrcodeURL(); - if (isEmpty(qrcodeUrl)) { - res.send({ - code: -1, - message: 'QRCode Get Error' - }); - return; - } - res.send({ - code: 0, - message: 'success', - data: { - qrcode: qrcodeUrl - } - }); - return; -}; -export const QQCheckLoginStatusHandler: RequestHandler = async (req, res) => { - res.send({ - code: 0, - message: 'success', - data: { - isLogin: await WebUiDataRuntime.getQQLoginStatus() - } - }); -}; -export const QQSetQuickLoginHandler: RequestHandler = async (req, res) => { - const { uin } = req.body; - const isLogin = await WebUiDataRuntime.getQQLoginStatus(); - if (isLogin) { - res.send({ - code: -1, - message: 'QQ Is Logined' - }); - return; - } - if (isEmpty(uin)) { - res.send({ - code: -1, - message: 'uin is empty' - }); - return; - } - const { result, message } = await WebUiDataRuntime.getQQQuickLogin(uin); - if (!result) { - res.send({ - code: -1, - message: message - }); - return; - } - //本来应该验证 但是http不宜这么搞 建议前端验证 - //isLogin = await WebUiDataRuntime.getQQLoginStatus(); - res.send({ - code: 0, - message: 'success' - }); -}; -export const QQGetQuickLoginListHandler: RequestHandler = async (req, res) => { - const quickLoginList = await WebUiDataRuntime.getQQQuickLoginList(); - res.send({ - code: 0, - data: quickLoginList - }); -}; \ No newline at end of file diff --git a/src/webui/src/helper/Data.ts b/src/webui/src/helper/Data.ts deleted file mode 100644 index 8be898c5..00000000 --- a/src/webui/src/helper/Data.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { OB11Config } from '@/onebot11/config'; - -interface LoginRuntimeType { - LoginCurrentTime: number; - LoginCurrentRate: number; - QQLoginStatus: boolean; - QQQRCodeURL: string; - QQLoginUin: string; - NapCatHelper: { - CoreQuickLoginCall: (uin: string) => Promise<{ result: boolean, message: string }>; - SetOb11ConfigCall: (ob11: OB11Config) => Promise; - QQLoginList: string[] - } -} -const LoginRuntime: LoginRuntimeType = { - LoginCurrentTime: Date.now(), - LoginCurrentRate: 0, - QQLoginStatus: false, //已实现 但太傻了 得去那边注册个回调刷新 - QQQRCodeURL: '', - QQLoginUin: '', - NapCatHelper: { - SetOb11ConfigCall: async (ob11: OB11Config) => { return; }, - CoreQuickLoginCall: async (uin: string) => { return { result: false, message: '' }; }, - QQLoginList: [] - } -}; -export const WebUiDataRuntime = { - checkLoginRate: async function (RateLimit: number): Promise { - LoginRuntime.LoginCurrentRate++; - //console.log(RateLimit, LoginRuntime.LoginCurrentRate, Date.now() - LoginRuntime.LoginCurrentTime); - if (Date.now() - LoginRuntime.LoginCurrentTime > 1000 * 60) { - LoginRuntime.LoginCurrentRate = 0;//超出时间重置限速 - LoginRuntime.LoginCurrentTime = Date.now(); - return true; - } - if (LoginRuntime.LoginCurrentRate <= RateLimit) { - return true; - } - return false; - } - , - getQQLoginStatus: async function (): Promise { - return LoginRuntime.QQLoginStatus; - } - , - setQQLoginStatus: async function (status: boolean): Promise { - LoginRuntime.QQLoginStatus = status; - } - , - setQQLoginQrcodeURL: async function (url: string): Promise { - LoginRuntime.QQQRCodeURL = url; - } - , - getQQLoginQrcodeURL: async function (): Promise { - return LoginRuntime.QQQRCodeURL; - } - , - setQQLoginUin: async function (uin: string): Promise { - LoginRuntime.QQLoginUin = uin; - } - , - getQQLoginUin: async function (): Promise { - return LoginRuntime.QQLoginUin; - }, - getQQQuickLoginList: async function (): Promise { - return LoginRuntime.NapCatHelper.QQLoginList; - }, - setQQQuickLoginList: async function (list: string[]): Promise { - LoginRuntime.NapCatHelper.QQLoginList = list; - }, - setQQQuickLoginCall(func: (uin: string) => Promise<{ result: boolean, message: string }>): void { - LoginRuntime.NapCatHelper.CoreQuickLoginCall = func; - }, - getQQQuickLogin: async function (uin: string): Promise<{ result: boolean, message: string }> { - return await LoginRuntime.NapCatHelper.CoreQuickLoginCall(uin); - }, - setOB11ConfigCall: async function (func: (ob11: OB11Config) => Promise): Promise { - LoginRuntime.NapCatHelper.SetOb11ConfigCall = func; - }, - setOB11Config: async function (ob11: OB11Config): Promise { - await LoginRuntime.NapCatHelper.SetOb11ConfigCall(ob11); - } -}; \ No newline at end of file diff --git a/src/webui/src/helper/SignToken.ts b/src/webui/src/helper/SignToken.ts deleted file mode 100644 index 8803a9e1..00000000 --- a/src/webui/src/helper/SignToken.ts +++ /dev/null @@ -1,68 +0,0 @@ -import crypto from 'crypto'; - -interface WebUiCredentialInnerJson { - CreatedTime: number; - TokenEncoded: string; -} - -interface WebUiCredentialJson { - Data: WebUiCredentialInnerJson; - Hmac: string; -} - -export class AuthHelper { - private static secretKey = Math.random().toString(36).slice(2); - - /** - * 签名凭证方法。 - * @param token 待签名的凭证字符串。 - * @returns 签名后的凭证对象。 - */ - public static async signCredential(token: string): Promise { - const innerJson: WebUiCredentialInnerJson = { - CreatedTime: Date.now(), - TokenEncoded: token, - }; - const jsonString = JSON.stringify(innerJson); - const hmac = crypto.createHmac('sha256', AuthHelper.secretKey) - .update(jsonString, 'utf8') - .digest('hex'); - return { Data: innerJson, Hmac: hmac }; - } - - /** - * 检查凭证是否被篡改的方法。 - * @param credentialJson 凭证的JSON对象。 - * @returns 布尔值,表示凭证是否有效。 - */ - public static async checkCredential(credentialJson: WebUiCredentialJson): Promise { - try { - const jsonString = JSON.stringify(credentialJson.Data); - const calculatedHmac = crypto.createHmac('sha256', AuthHelper.secretKey) - .update(jsonString, 'utf8') - .digest('hex'); - return calculatedHmac === credentialJson.Hmac; - } catch (error) { - return false; - } - } - - /** - * 验证凭证在1小时内有效且token与原始token相同。 - * @param token 待验证的原始token。 - * @param credentialJson 已签名的凭证JSON对象。 - * @returns 布尔值,表示凭证是否有效且token匹配。 - */ - public static async validateCredentialWithinOneHour(token: string, credentialJson: WebUiCredentialJson): Promise { - const isValid = await AuthHelper.checkCredential(credentialJson); - if (!isValid) { - return false; - } - - const currentTime = Date.now() / 1000; - const createdTime = credentialJson.Data.CreatedTime; - const timeDifference = currentTime - createdTime; - - return timeDifference <= 3600 && credentialJson.Data.TokenEncoded === token; - } -} \ No newline at end of file diff --git a/src/webui/src/helper/config.ts b/src/webui/src/helper/config.ts deleted file mode 100644 index 44b77c75..00000000 --- a/src/webui/src/helper/config.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { existsSync, readFileSync, writeFileSync } from 'node:fs'; -import { resolve } from 'node:path'; -import * as net from 'node:net'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { logError } from '@/common/utils/log'; - - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -// 限制尝试端口的次数,避免死循环 -const MAX_PORT_TRY = 100; - -async function tryUseHost(host: string): Promise { - return new Promise(async (resolve, reject) => { - try { - const server = net.createServer(); - server.on('listening', () => { - server.close(); - resolve(host); - }); - - server.on('error', (err: any) => { - if (err.code === 'EADDRNOTAVAIL') { - reject('主机地址验证失败,可能为非本机地址'); - } else { - reject(`遇到错误: ${err.code}`); - } - }); - - // 尝试监听 让系统随机分配一个端口 - server.listen(0, host); - } catch (error) { - // 这里捕获到的错误应该是启动服务器时的同步错误 - reject(`服务器启动时发生错误: ${error}`); - } - }); -} - -async function tryUsePort(port: number, host: string, tryCount: number = 0): Promise { - return new Promise(async (resolve, reject) => { - try { - const server = net.createServer(); - server.on('listening', () => { - server.close(); - resolve(port); - }); - - server.on('error', (err: any) => { - if (err.code === 'EADDRINUSE') { - if (tryCount < MAX_PORT_TRY) { - // 使用循环代替递归 - resolve(tryUsePort(port + 1, host, tryCount + 1)); - } else { - reject(`端口尝试失败,达到最大尝试次数: ${MAX_PORT_TRY}`); - } - } else { - reject(`遇到错误: ${err.code}`); - } - }); - - // 尝试监听端口 - server.listen(port, host); - } catch (error) { - // 这里捕获到的错误应该是启动服务器时的同步错误 - reject(`服务器启动时发生错误: ${error}`); - } - }); -} - -export interface WebUiConfigType { - host: string; - port: number; - prefix: string; - token: string; - loginRate: number -} -// 读取当前目录下名为 webui.json 的配置文件,如果不存在则创建初始化配置文件 -class WebUiConfigWrapper { - WebUiConfigData: WebUiConfigType | undefined = undefined; - private applyDefaults(obj: Partial, defaults: T): T { - return { ...defaults, ...obj }; - } - async GetWebUIConfig(): Promise { - if (this.WebUiConfigData) { - return this.WebUiConfigData; - } - const defaultconfig: WebUiConfigType = { - host: '0.0.0.0', - port: 6099, - prefix: '', - token: '', // 默认先填空,空密码无法登录 - loginRate: 3 - }; - try { - defaultconfig.token = Math.random().toString(36).slice(2); //生成随机密码 - } catch (e) { - logError('随机密码生成失败', e); - } - try { - const configPath = resolve(__dirname, './config/webui.json'); - - if (!existsSync(configPath)) { - writeFileSync(configPath, JSON.stringify(defaultconfig, null, 4)); - } - - const fileContent = readFileSync(configPath, 'utf-8'); - // 更新配置字段后新增字段可能会缺失,同步一下 - const parsedConfig = this.applyDefaults(JSON.parse(fileContent) as Partial, defaultconfig); - - if (!parsedConfig.prefix.startsWith('/')) parsedConfig.prefix = '/' + parsedConfig.prefix; - if (parsedConfig.prefix.endsWith('/')) parsedConfig.prefix = parsedConfig.prefix.slice(0, -1); - // 配置已经被操作过了,还是回写一下吧,不然新配置不会出现在配置文件里 - writeFileSync(configPath, JSON.stringify(parsedConfig, null, 4)); - // 不希望回写的配置放后面 - - // 查询主机地址是否可用 - const [host_err, host] = await tryUseHost(parsedConfig.host).then(data => [null, data as string]).catch(err => [err, null]); - if (host_err) { - logError('host不可用', host_err); - parsedConfig.port = 0; // 设置为0,禁用WebUI - } else { - parsedConfig.host = host; - // 修正端口占用情况 - const [port_err, port] = await tryUsePort(parsedConfig.port, parsedConfig.host).then(data => [null, data as number]).catch(err => [err, null]); - if (port_err) { - logError('port不可用', port_err); - parsedConfig.port = 0; // 设置为0,禁用WebUI - } else { - parsedConfig.port = port; - } - } - this.WebUiConfigData = parsedConfig; - return this.WebUiConfigData; - } catch (e) { - logError('读取配置文件失败', e); - } - return defaultconfig; // 理论上这行代码到不了,到了只能返回默认配置了 - } -} -export const WebUiConfig = new WebUiConfigWrapper(); diff --git a/src/webui/src/router/OB11Config.ts b/src/webui/src/router/OB11Config.ts deleted file mode 100644 index c9fae805..00000000 --- a/src/webui/src/router/OB11Config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Router } from 'express'; -import { OB11GetConfigHandler,OB11SetConfigHandler } from '../api/OB11Config'; -const router = Router(); -router.post('/GetConfig', OB11GetConfigHandler); -router.post('/SetConfig', OB11SetConfigHandler); -export { router as OB11ConfigRouter }; \ No newline at end of file diff --git a/src/webui/src/router/QQLogin.ts b/src/webui/src/router/QQLogin.ts deleted file mode 100644 index 61fccd80..00000000 --- a/src/webui/src/router/QQLogin.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Router } from 'express'; -import { QQCheckLoginStatusHandler, QQGetQRcodeHandler, QQGetQuickLoginListHandler, QQSetQuickLoginHandler } from '../api/QQLogin'; -const router = Router(); -router.all('/GetQuickLoginList', QQGetQuickLoginListHandler); -router.post('/CheckLoginStatus', QQCheckLoginStatusHandler); -router.post('/GetQQLoginQrcode', QQGetQRcodeHandler); -router.post('/SetQuickLogin', QQSetQuickLoginHandler); -export { router as QQLoginRouter }; \ No newline at end of file diff --git a/src/webui/src/router/auth.ts b/src/webui/src/router/auth.ts deleted file mode 100644 index c61367ec..00000000 --- a/src/webui/src/router/auth.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Router } from 'express'; -import { LoginHandler, LogoutHandler, checkHandler } from '../api/Auth'; - -const router = Router(); - -router.post('/login', LoginHandler); -router.post('/check', checkHandler); -router.post('/logout', LogoutHandler); -export { router as AuthRouter }; \ No newline at end of file diff --git a/src/webui/src/router/index.ts b/src/webui/src/router/index.ts deleted file mode 100644 index 6efd6e76..00000000 --- a/src/webui/src/router/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Router } from 'express'; -import { AuthHelper } from '../../src/helper/SignToken'; -import { NextFunction, Request, Response } from 'express'; -import { QQLoginRouter } from './QQLogin'; -import { AuthRouter } from './auth'; -import { OB11ConfigRouter } from './OB11Config'; -import { WebUiConfig } from '../helper/config'; -const router = Router(); -export async function AuthApi(req: Request, res: Response, next: NextFunction) { - //判断当前url是否为/login 如果是跳过鉴权 - if (req.url == '/auth/login') { - next(); - return; - } - if (req.headers?.authorization) { - const authorization = req.headers.authorization.split(' '); - if (authorization.length < 2) { - res.json({ - code: -1, - msg: 'Unauthorized', - }); - return; - } - const token = authorization[1]; - let Credential: any; - try { - Credential = JSON.parse(Buffer.from(token, 'base64').toString('utf-8')); - } catch (e) { - res.json({ - code: -1, - msg: 'Unauthorized', - }); - return; - } - const config = await WebUiConfig.GetWebUIConfig(); - const credentialJson = await AuthHelper.validateCredentialWithinOneHour(config.token, Credential); - if (credentialJson) { - //通过验证 - next(); - return; - } - res.json({ - code: -1, - msg: 'Unauthorized', - }); - return; - } - - res.json({ - code: -1, - msg: 'Server Error', - }); - return; -} -router.use(AuthApi); -router.all('/test', (req, res) => { - res.json({ - code: 0, - msg: 'ok', - }); -}); -router.use('/auth', AuthRouter); -router.use('/QQLogin', QQLoginRouter); -router.use('/OB11Config', OB11ConfigRouter); -export { router as ALLRouter }; \ No newline at end of file diff --git a/src/webui/ui/NapCat.ts b/src/webui/ui/NapCat.ts deleted file mode 100644 index 2f3f8108..00000000 --- a/src/webui/ui/NapCat.ts +++ /dev/null @@ -1,392 +0,0 @@ -import { SettingList } from './components/SettingList'; -import { SettingItem } from './components/SettingItem'; -import { SettingButton } from './components/SettingButton'; -import { SettingSwitch } from './components/SettingSwitch'; -import { SettingSelect } from './components/SettingSelect'; -import { OB11Config, OB11ConfigWrapper } from './components/WebUiApiOB11Config'; -async function onSettingWindowCreated(view: Element) { - const isEmpty = (value: any) => value === undefined || value === undefined || value === ''; - await OB11ConfigWrapper.Init(localStorage.getItem('auth') as string); - const ob11Config: OB11Config = await OB11ConfigWrapper.GetOB11Config(); - const setOB11Config = (key: string, value: any) => { - const configKey = key.split('.'); - if (configKey.length === 2) { - ob11Config[configKey[1]] = value; - } else if (configKey.length === 3) { - ob11Config[configKey[1]][configKey[2]] = value; - } - // OB11ConfigWrapper.SetOB11Config(ob11Config); // 只有当点保存时才下发配置,而不是在修改值后立即下发 - }; - - const parser = new DOMParser(); - const doc = parser.parseFromString( - [ - '
', - ` -
-
`, - SettingList([ - SettingItem( - 'Napcat', - undefined, - SettingButton('V1.8.3', 'napcat-update-button', 'secondary') - ), - ]), - SettingList([ - SettingItem( - '启用 HTTP 服务', - undefined, - SettingSwitch('ob11.http.enable', ob11Config.http.enable, { - 'control-display-id': 'config-ob11-http-port', - }) - ), - SettingItem( - 'HTTP 服务监听端口', - undefined, - `
`, - 'config-ob11-http-port', - ob11Config.http.enable - ), - SettingItem( - '启用 HTTP 心跳', - undefined, - SettingSwitch('ob11.http.enableHeart', ob11Config.http.enableHeart, { - 'control-display-id': 'config-ob11-HTTP.enableHeart', - }) - ), - SettingItem( - '启用 HTTP 事件上报', - undefined, - SettingSwitch('ob11.http.enablePost', ob11Config.http.enablePost, { - 'control-display-id': 'config-ob11-http-postUrls', - }) - ), - `
- -
- HTTP 事件上报密钥 -
-
- -
-
- -
- HTTP 事件上报地址 -
- 添加 -
-
-
`, - SettingItem( - '启用正向 WebSocket 服务', - undefined, - SettingSwitch('ob11.ws.enable', ob11Config.ws.enable, { - 'control-display-id': 'config-ob11-ws-port', - }) - ), - SettingItem( - '正向 WebSocket 服务监听端口', - undefined, - `
`, - 'config-ob11-ws-port', - ob11Config.ws.enable - ), - SettingItem( - '启用反向 WebSocket 服务', - undefined, - SettingSwitch('ob11.reverseWs.enable', ob11Config.reverseWs.enable, { - 'control-display-id': 'config-ob11-reverseWs-urls', - }) - ), - `
- -
- 反向 WebSocket 监听地址 -
- 添加 -
-
-
`, - SettingItem( - ' WebSocket 服务心跳间隔', - '控制每隔多久发送一个心跳包,单位为毫秒', - `
` - ), - SettingItem( - 'Access token', - undefined, - `
` - ), - SettingItem( - '新消息上报格式', - '如客户端无特殊需求推荐保持默认设置,两者的详细差异可参考 OneBot v11 文档', - SettingSelect( - [ - { text: '消息段', value: 'array' }, - { text: 'CQ码', value: 'string' }, - ], - 'ob11.messagePostFormat', - ob11Config.messagePostFormat - ) - ), - SettingItem( - '音乐卡片签名地址', - undefined, - `
`, - 'ob11.musicSignUrl' - ), - SettingItem( - '启用本地进群时间与发言时间记录', - undefined, - SettingSwitch('ob11.GroupLocalTime.Record', ob11Config.GroupLocalTime.Record, { - 'control-display-id': 'config-ob11-GroupLocalTime-RecordList', - }) - ), - `
- -
- 群列表 -
- 添加 -
-
-
`, - SettingItem( - '', - undefined, - SettingButton('保存', 'config-ob11-save', 'primary') - ), - ]), - SettingList([ - SettingItem( - '上报 Bot 自身发送的消息', - '上报 event 为 message_sent', - SettingSwitch('ob11.reportSelfMessage', ob11Config.reportSelfMessage) - ), - ]), - SettingList([ - SettingItem( - 'GitHub 仓库', - 'https://github.com/NapNeko/NapCatQQ', - SettingButton('点个星星', 'open-github') - ), - SettingItem('NapCat 文档', '', SettingButton('看看文档', 'open-docs')), - SettingItem( - 'Telegram 群', - 'https://t.me/+nLZEnpne-pQ1OWFl', - SettingButton('进去逛逛', 'open-telegram') - ), - SettingItem( - 'QQ 群', - '545402644', - SettingButton('我要进去', 'open-qq-group') - ), - ]), - '
', - ].join(''), - 'text/html' - ); - - // 外链按钮 - doc.querySelector('#open-github')?.addEventListener('click', () => { - window.open('https://github.com/NapNeko/NapCatQQ', '_blank'); - }); - doc.querySelector('#open-telegram')?.addEventListener('click', () => { - window.open('https://t.me/+nLZEnpne-pQ1OWFl'); - }); - doc.querySelector('#open-qq-group')?.addEventListener('click', () => { - window.open('https://qm.qq.com/q/bDnHRG38aI'); - }); - doc.querySelector('#open-docs')?.addEventListener('click', () => { - window.open('https://napneko.github.io/', '_blank'); - }); - // 生成反向地址列表 - const buildHostListItem = ( - type: string, - host: string, - index: number, - inputAttrs: any = {} - ) => { - const dom = { - container: document.createElement('setting-item'), - input: document.createElement('input'), - inputContainer: document.createElement('div'), - deleteBtn: document.createElement('setting-button'), - }; - dom.container.classList.add('setting-host-list-item'); - dom.container.dataset.direction = 'row'; - Object.assign(dom.input, inputAttrs); - dom.input.classList.add('q-input__inner'); - dom.input.type = 'url'; - dom.input.value = host; - dom.input.addEventListener('input', () => { - ob11Config[type.split('-')[0]][type.split('-')[1]][index] = - dom.input.value; - }); - - dom.inputContainer.classList.add('q-input'); - dom.inputContainer.appendChild(dom.input); - - dom.deleteBtn.innerHTML = '删除'; - dom.deleteBtn.dataset.type = 'secondary'; - dom.deleteBtn.addEventListener('click', () => { - ob11Config[type.split('-')[0]][type.split('-')[1]].splice(index, 1); - initReverseHost(type); - }); - - dom.container.appendChild(dom.inputContainer); - dom.container.appendChild(dom.deleteBtn); - - return dom.container; - }; - const buildHostList = ( - hosts: string[], - type: string, - inputAttr: any = {} - ) => { - const result: HTMLElement[] = []; - - hosts?.forEach((host, index) => { - result.push(buildHostListItem(type, host, index, inputAttr)); - }); - - return result; - }; - const addReverseHost = ( - type: string, - doc: Document = document, - inputAttr: any = {} - ) => { - type = type.replace(/\./g, '-');//替换操作 - const hostContainerDom = doc.body.querySelector( - `#config-ob11-${type}-list` - ); - hostContainerDom?.appendChild( - buildHostListItem( - type, - '', - ob11Config[type.split('-')[0]][type.split('-')[1]].length, - inputAttr - ) - ); - ob11Config[type.split('-')[0]][type.split('-')[1]].push(''); - }; - const initReverseHost = (type: string, doc: Document = document) => { - type = type.replace(/\./g, '-');//替换操作 - const hostContainerDom = doc.body?.querySelector( - `#config-ob11-${type}-list` - ); - if (hostContainerDom) { - [...hostContainerDom.childNodes].forEach((dom) => dom.remove()); - buildHostList( - ob11Config[type.split('-')[0]][type.split('-')[1]], - type - ).forEach((dom) => { - hostContainerDom?.appendChild(dom); - }); - } - }; - - initReverseHost('http.postUrls', doc); - initReverseHost('reverseWs.urls', doc); - initReverseHost('GroupLocalTime.RecordList', doc); - - doc - .querySelector('#config-ob11-http-postUrls-add') - ?.addEventListener('click', () => - addReverseHost('http.postUrls', document, { - placeholder: '如:http://127.0.0.1:5140/onebot', - }) - ); - - doc - .querySelector('#config-ob11-reverseWs-urls-add') - ?.addEventListener('click', () => - addReverseHost('reverseWs.urls', document, { - placeholder: '如:ws://127.0.0.1:5140/onebot', - }) - ); - doc - .querySelector('#config-ob11-GroupLocalTime-RecordList-add') - ?.addEventListener('click', () => - addReverseHost('GroupLocalTime.RecordList', document, { - placeholder: '此处填写群号 -1为全部', - }) - ); - doc.querySelector('#config-ffmpeg-select')?.addEventListener('click', () => { - //选择ffmpeg - }); - - doc.querySelector('#config-open-log-path')?.addEventListener('click', () => { - //打开日志 - }); - - // 开关 - doc - .querySelectorAll('setting-switch[data-config-key]') - .forEach((dom: Element) => { - dom.addEventListener('click', () => { - const active = dom.getAttribute('is-active') == undefined; - //@ts-expect-error 等待修复 - setOB11Config(dom.dataset.configKey, active); - if (active) dom.setAttribute('is-active', ''); - else dom.removeAttribute('is-active'); - //@ts-expect-error 等待修复 - if (!isEmpty(dom.dataset.controlDisplayId)) { - const displayDom = document.querySelector( - //@ts-expect-error 等待修复 - `#${dom.dataset.controlDisplayId}` - ); - if (active) displayDom?.removeAttribute('is-hidden'); - else displayDom?.setAttribute('is-hidden', ''); - } - }); - }); - - // 输入框 - doc - .querySelectorAll( - 'setting-item .q-input input.q-input__inner[data-config-key]' - ) - .forEach((dom: Element) => { - dom.addEventListener('input', () => { - const Type = dom.getAttribute('type'); - //@ts-expect-error等待修复 - const configKey = dom.dataset.configKey; - const configValue = - Type === 'number' - ? parseInt((dom as HTMLInputElement).value) >= 1 - ? parseInt((dom as HTMLInputElement).value) - : 1 - : (dom as HTMLInputElement).value; - - setOB11Config(configKey, configValue); - }); - }); - - // 下拉框 - doc - .querySelectorAll('ob-setting-select[data-config-key]') - .forEach((dom: Element) => { - //@ts-expect-error等待修复 - dom?.addEventListener('selected', (e: CustomEvent) => { - //@ts-expect-error等待修复 - const configKey = dom.dataset.configKey; - const configValue = e.detail.value; - setOB11Config(configKey, configValue); - }); - }); - - // 保存按钮 - doc.querySelector('#config-ob11-save')?.addEventListener('click', () => { - OB11ConfigWrapper.SetOB11Config(ob11Config); - alert('保存成功'); - }); - doc.body.childNodes.forEach((node) => { - view.appendChild(node); - }); -} -export { onSettingWindowCreated }; diff --git a/src/webui/ui/components/SettingButton.ts b/src/webui/ui/components/SettingButton.ts deleted file mode 100644 index 35f6bc87..00000000 --- a/src/webui/ui/components/SettingButton.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const SettingButton = (text: string, id?: string, type: string = 'secondary') => { - return `${text}`; -}; \ No newline at end of file diff --git a/src/webui/ui/components/SettingItem.ts b/src/webui/ui/components/SettingItem.ts deleted file mode 100644 index 40c573ae..00000000 --- a/src/webui/ui/components/SettingItem.ts +++ /dev/null @@ -1,15 +0,0 @@ -export const SettingItem = ( - title: string, - subtitle?: string, - action?: string, - id?: string, - visible: boolean = true, -) => { - return ` -
- ${title} - ${subtitle ? `${subtitle}` : ''} -
- ${action ? `
${action}
` : ''} -
`; -}; \ No newline at end of file diff --git a/src/webui/ui/components/SettingList.ts b/src/webui/ui/components/SettingList.ts deleted file mode 100644 index 2357773a..00000000 --- a/src/webui/ui/components/SettingList.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const SettingList = ( - items: string[], - title?: string, - isCollapsible: boolean = false, - direction: string = 'column', -) => { - return ` - - - ${items.join('')} - - - `; -}; \ No newline at end of file diff --git a/src/webui/ui/components/SettingOption.ts b/src/webui/ui/components/SettingOption.ts deleted file mode 100644 index ccb0654b..00000000 --- a/src/webui/ui/components/SettingOption.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const SettingOption = (text: string, value?: string, isSelected: boolean = false) => { - return `${text}`; -}; \ No newline at end of file diff --git a/src/webui/ui/components/SettingSelect.ts b/src/webui/ui/components/SettingSelect.ts deleted file mode 100644 index 7764cd4a..00000000 --- a/src/webui/ui/components/SettingSelect.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { SettingOption } from './SettingOption'; - -interface MouseEventExtend extends MouseEvent { - target: HTMLElement -} - -// -const SelectTemplate = document.createElement('template'); -SelectTemplate.innerHTML = ` -
-
- - - - -
- -
`; - -window.customElements.define( - 'ob-setting-select', - class extends HTMLElement { - readonly _button: HTMLDivElement; - readonly _text: HTMLInputElement; - readonly _context: HTMLUListElement; - - constructor() { - super(); - - this.attachShadow({ mode: 'open' }); - this.shadowRoot?.append(SelectTemplate.content.cloneNode(true)); - - this._button = this.shadowRoot.querySelector('div[part="button"]'); - this._text = this.shadowRoot.querySelector('input[part="current-text"]'); - this._context = this.shadowRoot.querySelector('ul[part="option-list"]'); - - const buttonClick = () => { - const isHidden = this._context.classList.toggle('hidden'); - window[`${isHidden ? 'remove' : 'add'}EventListener`]('pointerdown', windowPointerDown); - }; - - const windowPointerDown = ({ target }) => { - if (!this.contains(target)) buttonClick(); - }; - - this._button.addEventListener('click', buttonClick); - this._context.addEventListener('click', ({ target }: MouseEventExtend) => { - if (target.tagName !== 'SETTING-OPTION') return; - buttonClick(); - - if (target.hasAttribute('is-selected')) return; - - this.querySelectorAll('setting-option[is-selected]').forEach((dom) => dom.toggleAttribute('is-selected')); - target.toggleAttribute('is-selected'); - - this._text.value = target.textContent as string; - this.dispatchEvent( - new CustomEvent('selected', { - bubbles: true, - composed: true, - detail: { - name: target.textContent, - value: target.dataset.value, - }, - }), - ); - }); - - this._text.value = this.querySelector('setting-option[is-selected]')?.textContent as string; - } - }, -); - -export const SettingSelect = (items: Array<{ text: string; value: string }>, configKey?: string, configValue?: any) => { - return ` - ${items - .map((e, i) => { - return SettingOption(e.text, e.value, configKey && configValue ? configValue === e.value : i === 0); - }) - .join('')} -`; -}; \ No newline at end of file diff --git a/src/webui/ui/components/SettingSwitch.ts b/src/webui/ui/components/SettingSwitch.ts deleted file mode 100644 index bb18fd30..00000000 --- a/src/webui/ui/components/SettingSwitch.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const SettingSwitch = (configKey?: string, isActive: boolean = false, extraData?: Record) => { - return ` `data-${key}="${extraData[key]}"`) : ''} - > - `; -}; \ No newline at end of file diff --git a/src/webui/ui/components/WebUiApiOB11Config.ts b/src/webui/ui/components/WebUiApiOB11Config.ts deleted file mode 100644 index 492cc6bf..00000000 --- a/src/webui/ui/components/WebUiApiOB11Config.ts +++ /dev/null @@ -1,74 +0,0 @@ -export interface OB11Config { - [key: string]: any; - http: { - enable: boolean; - host: ''; - port: number; - secret: ''; - enableHeart: boolean; - enablePost: boolean; - postUrls: string[]; - }; - ws: { - enable: boolean; - host: ''; - port: number; - }; - reverseWs: { - enable: boolean; - urls: string[]; - }; - GroupLocalTime: { - Record: boolean, - RecordList: Array - }; - debug: boolean; - heartInterval: number; - messagePostFormat: 'array' | 'string'; - enableLocalFile2Url: boolean; - musicSignUrl: ''; - reportSelfMessage: boolean; - token: ''; - -} - -class WebUiApiOB11ConfigWrapper { - private retCredential: string = ''; - async Init(Credential: string) { - this.retCredential = Credential; - } - async GetOB11Config(): Promise { - const ConfigResponse = await fetch('../api/OB11Config/GetConfig', { - method: 'POST', - headers: { - Authorization: 'Bearer ' + this.retCredential, - 'Content-Type': 'application/json', - }, - }); - if (ConfigResponse.status == 200) { - const ConfigResponseJson = await ConfigResponse.json(); - if (ConfigResponseJson.code == 0) { - return ConfigResponseJson?.data; - } - } - return {} as OB11Config; - } - async SetOB11Config(config: OB11Config): Promise { - const ConfigResponse = await fetch('../api/OB11Config/SetConfig', { - method: 'POST', - headers: { - Authorization: 'Bearer ' + this.retCredential, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ config: JSON.stringify(config) }), - }); - if (ConfigResponse.status == 200) { - const ConfigResponseJson = await ConfigResponse.json(); - if (ConfigResponseJson.code == 0) { - return true; - } - } - return false; - } -} -export const OB11ConfigWrapper = new WebUiApiOB11ConfigWrapper(); diff --git a/src/webui/vite.config.ts b/src/webui/vite.config.ts deleted file mode 100644 index dd98d374..00000000 --- a/src/webui/vite.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from 'vite'; - -export default defineConfig({ - build:{ - target: 'esnext', - minify: false, - lib: { - entry: 'ui/NapCat.ts', - formats: ['es'], - fileName: () => 'renderer.js', - } - } -}); \ No newline at end of file diff --git a/src/webui/webui.json b/src/webui/webui.json deleted file mode 100644 index 793b8cf1..00000000 --- a/src/webui/webui.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "host": "0.0.0.0", - "port": 6099, - "prefix": "", - "token": "random", - "loginRate": 3 - -} \ No newline at end of file diff --git a/test/MessageUnique.ts b/test/MessageUnique.ts deleted file mode 100644 index 4412257b..00000000 --- a/test/MessageUnique.ts +++ /dev/null @@ -1,93 +0,0 @@ -describe('MessageUniqueWrapper', () => { - let messageUniqueWrapper: MessageUniqueWrapper; - beforeEach(() => { - messageUniqueWrapper = new MessageUniqueWrapper(); - }); - - test('createMsg should return a unique shortId for a new message', () => { - const peer = new Peer(); - peer.chatType = 1; - peer.peerUid = '123'; - const msgId = 'msgId123'; - - const key = `${msgId}|${peer.chatType}|${peer.peerUid}`; - const hash = crypto.createHash('sha1').update(key); - const expectedShortId = parseInt(hash.digest('hex').slice(0, 8), 16); - - const shortId = messageUniqueWrapper.createMsg(peer, msgId); - - expect(shortId).toBeDefined(); - expect(shortId).toBe(expectedShortId); - }); - - test('createMsg should return undefined if the same message is added again', () => { - const peer = new Peer(); - peer.chatType = 1; - peer.peerUid = '123'; - const msgId = 'msgId123'; - - const shortId = messageUniqueWrapper.createMsg(peer, msgId); - const secondShortId = messageUniqueWrapper.createMsg(peer, msgId); - - expect(shortId).toBeDefined(); - expect(secondShortId).toBeUndefined(); - }); - - test('getMsgIdAndPeerByShortId should return the message and peer for a given shortId', () => { - const peer = new Peer(); - peer.chatType = 1; - peer.peerUid = '123'; - const msgId = 'msgId123'; - messageUniqueWrapper.createMsg(peer, msgId); - - const shortId = messageUniqueWrapper.getShortIdByMsgId(msgId); - const result = messageUniqueWrapper.getMsgIdAndPeerByShortId(shortId); - - expect(result).toBeDefined(); - expect(result.MsgId).toBe(msgId); - expect(result.Peer.chatType).toBe(peer.chatType); - expect(result.Peer.peerUid).toBe(peer.peerUid); - }); - - test('getMsgIdAndPeerByShortId should return undefined if the shortId does not exist', () => { - const peer = new Peer(); - peer.chatType = 1; - peer.peerUid = '123'; - const msgId = 'msgId123'; - - messageUniqueWrapper.createMsg(peer, msgId); - - const invalidShortId = 12345678; - const result = messageUniqueWrapper.getMsgIdAndPeerByShortId(invalidShortId); - - expect(result).toBeUndefined(); - }); - - test('getShortIdByMsgId should return the shortId for a given message Id', () => { - const peer = new Peer(); - peer.chatType = 1; - peer.peerUid = '123'; - const msgId = 'msgId123'; - - messageUniqueWrapper.createMsg(peer, msgId); - - const shortId = messageUniqueWrapper.getShortIdByMsgId(msgId); - - expect(shortId).toBeDefined(); - expect(typeof shortId).toBe('number'); - }); - - test('getShortIdByMsgId should return undefined if the message Id does not exist', () => { - const peer = new Peer(); - peer.chatType = 1; - peer.peerUid = '123'; - const msgId = 'msgId123'; - - messageUniqueWrapper.createMsg(peer, msgId); - - const invalidMsgId = 'invalidMsgId'; - const shortId = messageUniqueWrapper.getShortIdByMsgId(invalidMsgId); - - expect(shortId).toBeUndefined(); - }); - });