Compare commits

..

140 Commits

Author SHA1 Message Date
手瓜一十雪
edf80775b7 release: v2.4.9 2024-09-12 19:47:57 +08:00
手瓜一十雪
46e56ac726 remove: polyFill 2024-09-12 19:35:54 +08:00
手瓜一十雪
40b2f6bfd6 release: 2.4.7 2024-09-12 18:31:11 +08:00
手瓜一十雪
911e4921e2 fix: 删除旧文件 2024-09-12 18:15:38 +08:00
手瓜一十雪
1db9bb419d fix: 一处异常字段 2024-09-12 10:55:18 +08:00
手瓜一十雪
c6241a94e3 style: lint 2024-09-12 09:28:41 +08:00
手瓜一十雪
1cbf75ca36 style: lint 2024-09-12 09:28:26 +08:00
手瓜一十雪
8f85c897c8 refactor: SysMsg 2024-09-12 09:20:10 +08:00
手瓜一十雪
29c31b7aba release: 2.4.6 2024-09-12 09:01:13 +08:00
手瓜一十雪
402919d6f2 feat: qucikLogin 2024-09-12 09:00:53 +08:00
手瓜一十雪
82608dd5ff fix: build 2024-09-12 00:17:35 +08:00
手瓜一十雪
f312368df2 build: fix2 2024-09-11 23:40:05 +08:00
手瓜一十雪
374fc64427 feat: delFile 2024-09-11 23:29:26 +08:00
手瓜一十雪
95bd74bb0d BUILD: TEST 2024-09-11 23:18:38 +08:00
手瓜一十雪
a9f5069649 Revert "build: debug"
This reverts commit 957f7ffd8d.
2024-09-11 22:41:59 +08:00
手瓜一十雪
957f7ffd8d build: debug 2024-09-11 22:28:28 +08:00
手瓜一十雪
336dd3ce10 chore: 扩展 2024-09-11 22:13:45 +08:00
手瓜一十雪
47a7295477 fix: typo
copilot
2024-09-11 20:24:50 +08:00
手瓜一十雪
341a0e1c2a chore: code 2024-09-11 20:10:52 +08:00
手瓜一十雪
c4f73d0eb8 Merge branch 'main' of https://github.com/NapNeko/NapCatQQ 2024-09-11 20:01:36 +08:00
手瓜一十雪
bd9258bae4 release: 2.4.5 2024-09-11 20:01:27 +08:00
手瓜一十雪
e3b3260aa0 Merge pull request #357 from cnxysoft/test
feat: 被点赞事件
2024-09-11 20:00:11 +08:00
手瓜一十雪
676766c99e refactor: protobuf 2024-09-11 19:56:51 +08:00
Alen
1025a07593 revert 2024-09-11 17:17:49 +08:00
Alen
00c3fcd033 Merge branch 'main' into test 2024-09-11 16:32:45 +08:00
Alen
b8457d4aff feat: 被点赞事件 2024-09-11 16:32:28 +08:00
手瓜一十雪
a2ecf10d19 feat: 全面迁移V2 2024-09-11 15:44:41 +08:00
Alen
1e63a2a7e7 test: 被赞事件(未完成) 2024-09-11 02:28:47 +08:00
手瓜一十雪
964014fc5c fix: #355 2024-09-10 22:27:06 +08:00
手瓜一十雪
fc2bb6d8c3 docs: 移除注释 2024-09-10 18:58:27 +08:00
手瓜一十雪
1b10252d76 remove: NTQQCacheApi 2024-09-10 18:42:49 +08:00
手瓜一十雪
ad8af12a10 refactor: fsPromise catch 2024-09-10 18:41:01 +08:00
手瓜一十雪
b040c9b118 refactor: audio 2024-09-10 18:39:14 +08:00
Alen
f6da7da90b Merge pull request #352 from cnxysoft/upmain
fix: 踢官方机器人报错
2024-09-10 00:40:58 +08:00
Alen
a745185408 fix: 踢官方机器人报错 2024-09-10 00:38:10 +08:00
手瓜一十雪
d3336f9027 release: 2.4.3 2024-09-09 21:37:22 +08:00
手瓜一十雪
daf42c8203 release: 2.4.2 2024-09-09 15:04:19 +08:00
手瓜一十雪
0a18bae3b5 fix: #351 2024-09-09 15:04:00 +08:00
手瓜一十雪
919705966c build: 2.4.1 2024-09-09 09:19:23 +08:00
手瓜一十雪
2c54aee63e build: test 2024-09-08 21:39:53 +08:00
手瓜一十雪
3f80bdf2a3 fix 2024-09-08 18:29:21 +08:00
手瓜一十雪
1c429b8dd3 fix: type 2024-09-08 18:26:07 +08:00
手瓜一十雪
5669e2b0b7 fix: 跟进实际逻辑 2024-09-08 18:21:55 +08:00
手瓜一十雪
1a6a43babf release: 2.4.0 2024-09-08 10:50:30 +08:00
手瓜一十雪
2650db5ddc fix: 字段V2 2024-09-08 10:48:33 +08:00
手瓜一十雪
255491a107 fix: hex计算问题 2024-09-08 10:41:30 +08:00
手瓜一十雪
5c64147dfa fix: encodeFile 2024-09-08 10:34:49 +08:00
手瓜一十雪
39f4118577 fix: #347 2024-09-08 10:30:30 +08:00
手瓜一十雪
f7f6e4736a fix #349 2024-09-08 10:24:36 +08:00
手瓜一十雪
c635da7ebb style: lint 2024-09-08 10:10:47 +08:00
手瓜一十雪
58124b006a Merge pull request #346 from NapNeko/Refactor-2.4.x
refactor: v2.4.0
2024-09-08 10:08:41 +08:00
手瓜一十雪
563aeccd0f refactor: fileNameEncode 2024-09-08 10:07:49 +08:00
手瓜一十雪
bd1a95a7f5 style: apis 2024-09-07 23:48:41 +08:00
手瓜一十雪
cdb25828f2 chore: code 2024-09-07 23:34:52 +08:00
手瓜一十雪
45803b3b23 Merge branch 'main' into Refactor-2.4.x 2024-09-07 23:34:23 +08:00
手瓜一十雪
0e5e3d3383 refactor: Service 2024-09-07 23:33:40 +08:00
Wesley F. Young
4672930037 update: move to recallMsg(V2) 2024-09-07 23:28:35 +08:00
手瓜一十雪
09be7131c3 refactor: 整理Service 2024-09-07 23:07:24 +08:00
手瓜一十雪
a804f90b9c refactor: adapter 2024-09-07 22:58:29 +08:00
手瓜一十雪
264cb6bbd2 release: 2.3.7 2024-09-07 21:29:22 +08:00
手瓜一十雪
b7772e867b Merge pull request #344 from qhy040404/patch-1
feat: 允许保存的token自动填写
2024-09-07 20:05:25 +08:00
Alen
cc0e77abfb Merge pull request #345 from cnxysoft/upmain
fix: 群成员列表获取
2024-09-07 19:55:41 +08:00
Alen
537d1c6f4f fix: 群成员列表获取
修复部分群成员列表返回为空的问题
2024-09-07 19:54:46 +08:00
Seijo Cecilia
80facadd67 chore: fix prefer-const 2024-09-07 19:49:54 +08:00
Seijo Cecilia
ba097dad23 update: recallMsgV2 2024-09-07 19:49:18 +08:00
qhy040404
c13c15d046 feat: 允许保存的token自动填写 2024-09-07 19:37:39 +08:00
手瓜一十雪
4f52128a06 fix 2024-09-07 17:17:07 +08:00
手瓜一十雪
500b2d0e6d release: 2.3.6 2024-09-07 13:31:32 +08:00
手瓜一十雪
e59d094feb feat: 提升使用体验 2024-09-07 10:45:45 +08:00
手瓜一十雪
a8372f14f8 fix: member info 2024-09-07 09:18:29 +08:00
Wesley F. Young
5174ff422d update: optimize message logging to console 2024-09-07 01:29:50 +08:00
Wesley F. Young
5c06751c3b fix: reference error 2024-09-07 00:04:35 +08:00
手瓜一十雪
ac2b0118a6 release: 2.3.5 2024-09-06 12:13:22 +08:00
手瓜一十雪
3eb8fd4abe Merge pull request #343 from drsanwujiang/patch-1
Fix bug: active HTTP adapter
2024-09-06 11:42:05 +08:00
Drsanwujiang
48b389ebe3 Fix bug: active HTTP adapter 2024-09-06 11:02:41 +08:00
手瓜一十雪
065adeb2cd fix 2024-09-06 07:40:33 +08:00
Wesley F. Young
269d0a06fe docs: deprecated features 2024-09-06 01:03:04 +08:00
手瓜一十雪
8eca26b1a5 fix 2024-09-05 18:03:32 +08:00
手瓜一十雪
3019ef7de4 release: 2.3.4 2024-09-05 16:15:21 +08:00
手瓜一十雪
522311b547 release: 2.3.4 2024-09-05 16:00:13 +08:00
手瓜一十雪
21061561ec fix: 字段兼容 2024-09-05 15:06:11 +08:00
手瓜一十雪
b83c41ad56 fix: #339 2024-09-05 14:55:11 +08:00
Version
e80a1cc64a chore:version change 2024-09-05 06:03:22 +00:00
手瓜一十雪
a01e4ca89f release: 2.3.1 2024-09-05 14:03:03 +08:00
手瓜一十雪
c20362e9b6 release: 2.3.0 2024-09-05 14:00:57 +08:00
手瓜一十雪
c90cfb99bd Merge pull request #340 from 123233513/main
%RetString% 增加引号,解决QQ目录包含空格的问题
2024-09-05 13:56:58 +08:00
123233513
7bcea14799 Update launcher.bat
%RetString% 增加引号,解决QQ目录包含空格的问题,比如安装在:C:\Program Files\Tencent\QQNT时,获取不到正确的路径
2024-09-05 10:41:04 +08:00
Wesley F. Young
b415c1a6d1 fix: file encoding 2024-09-04 23:26:55 +08:00
手瓜一十雪
452c72d280 release: 2.2.47 2024-09-04 23:12:38 +08:00
手瓜一十雪
48350be625 fix: 进一步筛选 2024-09-04 18:05:44 +08:00
手瓜一十雪
ab824fb219 Revert "update: normalize log"
This reverts commit d36a28fa81.
2024-09-04 18:05:01 +08:00
手瓜一十雪
043d8a1861 Revert "rollback unlink -> unlinkSync"
This reverts commit 074ac15d0f.
2024-09-04 18:04:58 +08:00
Seijo Cecilia
074ac15d0f rollback unlink -> unlinkSync 2024-09-04 15:50:23 +08:00
Seijo Cecilia
d36a28fa81 update: normalize log 2024-09-04 15:47:14 +08:00
手瓜一十雪
ba12bc6c91 docs: fix 2024-09-04 14:03:55 +08:00
手瓜一十雪
87332778e5 docs: fix 2024-09-04 13:26:38 +08:00
手瓜一十雪
453feb8473 release: 2.2.46 2024-09-04 13:21:40 +08:00
手瓜一十雪
8ff469974c build: test2 2024-09-04 13:19:02 +08:00
手瓜一十雪
994ec5ac0f fix: 极端情况下uin暴毙的情况 2024-09-04 12:40:59 +08:00
手瓜一十雪
43f7f9a363 build: test 2024-09-04 12:37:23 +08:00
Wesley F. Young
4a11ebc9b9 Revert "chore: optimize vite.config.ts"
This reverts commit 6a0d592491.
2024-09-04 10:38:10 +08:00
Wesley F. Young
d76a1305e7 chore: optimize import 2024-09-04 10:06:09 +08:00
Wesley F. Young
6a0d592491 chore: optimize vite.config.ts 2024-09-04 10:05:24 +08:00
Wesley F. Young
9898c2196d chore: optimize tsconfig.json 2024-09-04 00:29:55 +08:00
Wesley F. Young
41a8dc840f chore: completely comment onRecvSysMsg 2024-09-03 23:54:46 +08:00
Wesley F. Young
c3eaae9d88 chore: optimize imports 2024-09-03 23:46:10 +08:00
手瓜一十雪
3ca959b7a6 docs: update 2024-09-03 21:51:16 +08:00
手瓜一十雪
1d2e2b6e5c release: 2.2.44 2024-09-03 21:33:48 +08:00
手瓜一十雪
31d963c4d1 Merge pull request #336 from hguandl/feat/macos
feat: 支持 macOS
2024-09-03 21:16:03 +08:00
Hao Guan
7e96118cdc feat: support macOS 2024-09-03 20:17:10 +08:00
Hao Guan
709a0744bd chore: refactor path config 2024-09-03 20:14:35 +08:00
手瓜一十雪
f59248cc5a release: 2.2.43 2024-09-03 18:49:45 +08:00
手瓜一十雪
8647c5c607 fix: echo丢失问题 2024-09-03 18:37:28 +08:00
手瓜一十雪
6699ff38a1 Revert "fix: Error Handle"
This reverts commit d79b98bd55.
2024-09-03 18:36:20 +08:00
手瓜一十雪
d79b98bd55 fix: Error Handle 2024-09-03 18:34:33 +08:00
手瓜一十雪
5065a052fb release: 2.2.42 2024-09-03 18:12:59 +08:00
Wesley F. Young
45603bb78c fix(docs): unexpected spaces 2024-09-03 15:48:08 +08:00
手瓜一十雪
40948995b4 build: test 2024-09-03 14:09:17 +08:00
手瓜一十雪
4ccdd8d1d3 docs: update 2024-09-03 13:37:19 +08:00
手瓜一十雪
30d0174f47 fix: #334 2024-09-03 13:20:10 +08:00
手瓜一十雪
5a986ba25c release: 2.2.40 2024-09-03 13:01:37 +08:00
手瓜一十雪
fe63c24ac3 release: 2.2.39 2024-09-03 12:40:13 +08:00
手瓜一十雪
c384bd6875 release: 2.2.38 2024-09-02 17:31:27 +08:00
手瓜一十雪
dcbff3f569 release: 2.2.37 2024-09-02 16:31:42 +08:00
手瓜一十雪
7d91e05a69 fix: #332 2024-09-02 16:31:18 +08:00
手瓜一十雪
a5ce424a40 release: 2.2.36 2024-09-01 18:44:23 +08:00
手瓜一十雪
47c36ca062 release: 2.2.35 2024-09-01 18:24:49 +08:00
手瓜一十雪
c4c5b3bf8b fix: remark 2024-09-01 18:24:29 +08:00
手瓜一十雪
b1a81b0d12 release: 2.2.32 2024-09-01 16:32:13 +08:00
手瓜一十雪
ad9fe64850 release: 2.2.32 2024-09-01 16:13:41 +08:00
手瓜一十雪
f236349dc6 Revert "release:2.2.31"
This reverts commit 309d8a9f18.
2024-09-01 16:13:14 +08:00
手瓜一十雪
5f56c8a7d4 fix 2024-09-01 16:10:16 +08:00
手瓜一十雪
309d8a9f18 release:2.2.31 2024-09-01 15:59:02 +08:00
手瓜一十雪
2981799803 fix: file api 2024-09-01 14:11:28 +08:00
手瓜一十雪
00f8e1c0da Revert "fix: fileId"
This reverts commit ae009f98c1.
2024-09-01 13:41:19 +08:00
手瓜一十雪
e9482e2ec4 Revert "fix: encode fileId"
This reverts commit 9bff327377.
2024-09-01 13:41:14 +08:00
手瓜一十雪
9bff327377 fix: encode fileId 2024-09-01 12:17:42 +08:00
手瓜一十雪
ae009f98c1 fix: fileId 2024-09-01 12:17:17 +08:00
手瓜一十雪
77505a6f5b release: 2.2.31 2024-09-01 09:31:59 +08:00
手瓜一十雪
19c729aa23 chore: appid 2024-09-01 09:30:38 +08:00
126 changed files with 1358 additions and 2283 deletions

View File

@@ -17,5 +17,8 @@ charset = utf-8
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
[*.bat]
charset = latin1
# Unfortunately, EditorConfig doesn't support space configuration inside import braces directly. # Unfortunately, EditorConfig doesn't support space configuration inside import braces directly.
# You'll need to rely on your linter/formatter like ESLint or Prettier for that. # You'll need to rely on your linter/formatter like ESLint or Prettier for that.

View File

@@ -10,6 +10,7 @@ body:
在提交新的 Bug 反馈前,请确保您: 在提交新的 Bug 反馈前,请确保您:
* 已经搜索了现有的 issues并且没有找到可以解决您问题的方法 * 已经搜索了现有的 issues并且没有找到可以解决您问题的方法
* 不与现有的某一 issue 重复 * 不与现有的某一 issue 重复
* 不涉及[已经停止维护的特性](https://github.com/NapNeko/NapCatQQ?tab=readme-ov-file#挥别昨日),例如 CQ 码
- type: input - type: input
id: system-version id: system-version
attributes: attributes:

View File

@@ -7,10 +7,14 @@
NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现。 NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现。
## 猫猫技能 ## 猫猫技能
- [x] **高性能**1K+ 群聊数目、20 线程并行发送消息毫无压力
- [x] **多种启动方式**支持以无头、LiteLoader 插件、仅 QQ GUI 三种方式启动 - [x] **多种启动方式**支持以无头、LiteLoader 插件、仅 QQ GUI 三种方式启动
- [x] **多平台支持**: 覆盖 Windows / Linux (可选 Docker) / Android Termux / MacOS
- [x] **安装简单**: 支持一键脚本/程序自动部署/镜像部署等多种覆盖范围
- [x] **低占用**:无头模式占用资源极低,适合在服务器上运行 - [x] **低占用**:无头模式占用资源极低,适合在服务器上运行
- [x] **超多接口**实现大部分Onebot接口上扩展了一套私有API - [x] **超多接口**:实现大部分 OneBot 和 go-cqhttp 接口,超多扩展 API
- [x] **WebUI**:自带 WebUI 支持,远程管理更加便捷 - [x] **WebUI**:自带 WebUI 支持,远程管理更加便捷
- [x] **低故障率**:快速适配最新版本,日常保证 0 Issue
## 使用猫猫 ## 使用猫猫
@@ -24,10 +28,12 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
[Telegram Link](https://t.me/+nLZEnpne-pQ1OWFl) [Telegram Link](https://t.me/+nLZEnpne-pQ1OWFl)
## 猫猫朋友 ## 猫猫朋友
感谢 [LLOneBot](https://github.com/LLOneBot/LLOneBot) 提供初始版本基础 感谢 [LLOneBot](https://github.com/LLOneBot/LLOneBot) 提供部分参考
感谢 [Lagrange](https://github.com/LagrangeDev/Lagrange.Core) 对本项目的大力支持 感谢 [Lagrange](https://github.com/LagrangeDev/Lagrange.Core) 对本项目的大力支持
不过最最重要的 还是需要感谢屏幕前的你哦~
--- ---
## 约法三章 ## 约法三章

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,40 @@
@echo off
chcp 65001
net session >nul 2>&1
if %errorLevel% == 0 (
echo Administrator mode detected.
) else (
echo Please run this script in administrator mode.
powershell -Command "Start-Process 'cmd.exe' -ArgumentList '/c cd /d \"%cd%\" && \"%~f0\" %1' -Verb runAs"
exit
)
set NAPCAT_PATCH_PATH=%cd%\patchNapCat.js
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
set NAPCAT_MAIN_PATH=%cd%\napcat.mjs
: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
if not exist "%QQpath%" (
echo provided QQ path is invalid: %QQpath%
pause
exit /b
)
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %1
REM "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" 123456

39
launcher/launcher.bat Normal file
View File

@@ -0,0 +1,39 @@
@echo off
chcp 65001
net session >nul 2>&1
if %errorLevel% == 0 (
echo Administrator mode detected.
) else (
echo Please run this script in administrator mode.
powershell -Command "Start-Process 'wt.exe' -ArgumentList 'cmd /c cd /d \"%cd%\" && \"%~f0\" %1' -Verb runAs"
exit
)
set NAPCAT_PATCH_PATH=%cd%\patchNapCat.js
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
set NAPCAT_MAIN_PATH=%cd%\napcat.mjs
: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
if not exist "%QQpath%" (
echo provided QQ path is invalid: %QQpath%
pause
exit /b
)
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %1

5
launcher/loadNapCat.js Normal file
View File

@@ -0,0 +1,5 @@
const path = require('path');
const CurrentPath = path.dirname(__filename);
(async () => {
await import("file://" + path.join(CurrentPath, './napcat/napcat.mjs'));
})();

1
launcher/patchNapCat.js Normal file
View File

@@ -0,0 +1 @@
require('./launcher.node').load('external_index', module);

View File

@@ -0,0 +1,4 @@
@echo off
REM ./launcher.bat 123456
REM ./launcher-win10.bat 123456
REM 带有REM的为注释 删掉你需要的系统的那行REM这三个单词 修改QQ本脚本启动即可

View File

@@ -4,7 +4,7 @@
"name": "NapCatQQ", "name": "NapCatQQ",
"slug": "NapCat.Framework", "slug": "NapCat.Framework",
"description": "高性能的 OneBot 11 协议实现", "description": "高性能的 OneBot 11 协议实现",
"version": "2.2.30", "version": "2.4.9",
"icon": "./logo.png", "icon": "./logo.png",
"authors": [ "authors": [
{ {

View File

@@ -2,7 +2,7 @@
"name": "napcat", "name": "napcat",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "2.2.30", "version": "2.4.9",
"scripts": { "scripts": {
"build:framework": "vite build --mode framework", "build:framework": "vite build --mode framework",
"build:shell": "vite build --mode shell", "build:shell": "vite build --mode shell",
@@ -57,6 +57,7 @@
"image-size": "^1.1.1", "image-size": "^1.1.1",
"json-schema-to-ts": "^3.1.0", "json-schema-to-ts": "^3.1.0",
"log4js": "^6.9.1", "log4js": "^6.9.1",
"protobufjs": "~7.4.0",
"qrcode-terminal": "^0.12.0", "qrcode-terminal": "^0.12.0",
"silk-wasm": "^3.6.1", "silk-wasm": "^3.6.1",
"strtok3": "8.0.1", "strtok3": "8.0.1",

Binary file not shown.

View File

@@ -1,66 +1,63 @@
import fs from 'fs';
import { encode, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
import fsPromise from 'fs/promises'; import fsPromise from 'fs/promises';
import path from 'node:path'; import path from 'node:path';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
import { spawn } from 'node:child_process'; import { spawn } from 'node:child_process';
import { encode, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
import { LogWrapper } from './log'; import { LogWrapper } from './log';
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) { const ALLOW_SAMPLE_RATE = [8000, 12000, 16000, 24000, 32000, 44100, 48000];
async function guessDuration(pttPath: string) { const EXIT_CODES = [0, 255];
const FFMPEG_PATH = process.env.FFMPEG_PATH || 'ffmpeg';
async function guessDuration(pttPath: string, logger: LogWrapper) {
const pttFileInfo = await fsPromise.stat(pttPath); const pttFileInfo = await fsPromise.stat(pttPath);
let duration = pttFileInfo.size / 1024 / 3; // 3kb/s const duration = Math.max(1, Math.floor(pttFileInfo.size / 1024 / 3)); // 3kb/s
duration = Math.floor(duration);
duration = Math.max(1, duration);
logger.log('通过文件大小估算语音的时长:', duration); logger.log('通过文件大小估算语音的时长:', duration);
return duration; return duration;
} }
async function convert(filePath: string, pcmPath: string, logger: LogWrapper): Promise<Buffer> {
return new Promise<Buffer>((resolve, reject) => {
const cp = spawn(FFMPEG_PATH, ['-y', '-i', filePath, '-ar', '24000', '-ac', '1', '-f', 's16le', pcmPath]);
cp.on('error', (err: Error) => {
logger.log('FFmpeg处理转换出错: ', err.message);
reject(err);
});
cp.on('exit', async (code, signal) => {
if (code == null || EXIT_CODES.includes(code)) {
try {
const data = await fsPromise.readFile(pcmPath);
await fsPromise.unlink(pcmPath);
resolve(data);
} catch (err) {
reject(err);
}
} else {
logger.log(`FFmpeg exit: code=${code ?? 'unknown'} sig=${signal ?? 'unknown'}`);
reject(new Error('FFmpeg处理转换失败'));
}
});
});
}
async function handleWavFile(file: Buffer, filePath: string, pcmPath: string, logger: LogWrapper): Promise<Buffer> {
const { fmt } = getWavFileInfo(file);
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
return await convert(filePath, pcmPath, logger);
}
return file;
}
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) {
try { try {
const file = await fsPromise.readFile(filePath); const file = await fsPromise.readFile(filePath);
const pttPath = path.join(TEMP_DIR, randomUUID()); const pttPath = path.join(TEMP_DIR, randomUUID());
if (!isSilk(file)) { if (!isSilk(file)) {
logger.log(`语音文件${filePath}需要转换成silk`); logger.log(`语音文件${filePath}需要转换成silk`);
const _isWav = isWav(file); const pcmPath = `${pttPath}.pcm`;
const pcmPath = pttPath + '.pcm'; const input = isWav(file) ? await handleWavFile(file, filePath, pcmPath, logger) : await convert(filePath, pcmPath, logger);
let sampleRate = 0; const silk = await encode(input, 24000);
const convert = () => { await fsPromise.writeFile(pttPath, silk.data);
return new Promise<Buffer>((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 => {
logger.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);
}
logger.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);
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration); logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
return { return {
converted: true, converted: true,
@@ -68,15 +65,13 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
duration: silk.duration / 1000, duration: silk.duration / 1000,
}; };
} else { } else {
const silk = file;
let duration = 0; let duration = 0;
try { try {
duration = getDuration(silk) / 1000; duration = getDuration(file) / 1000;
} catch (e: any) { } catch (e: any) {
logger.log('获取语音文件时长失败, 使用文件大小推测时长', filePath, e.stack); logger.log('获取语音文件时长失败, 使用文件大小推测时长', filePath, e.stack);
duration = await guessDuration(filePath); duration = await guessDuration(filePath, logger);
} }
return { return {
converted: false, converted: false,
path: filePath, path: filePath,

View File

@@ -22,10 +22,15 @@ export abstract class ConfigBase<T> {
} }
getConfigPath(pathName: string | undefined): string { getConfigPath(pathName: string | undefined): string {
const suffix = pathName ? `_${pathName}` : ''; if (!pathName) {
const filename = `${this.name}${suffix}.json`; const filename = `${this.name}.json`;
const mainPath = this.core.context.pathWrapper.binaryPath;
return path.join(mainPath, 'config', filename);
} else {
const filename = `${this.name}_${pathName}.json`;
return path.join(this.configPath, filename); return path.join(this.configPath, filename);
} }
}
read(): T { read(): T {
const logger = this.core.context.logger; const logger = this.core.context.logger;

View File

@@ -128,6 +128,7 @@ export async function httpDownload(options: string | HttpDownloadOptions): Promi
let url: string; let url: string;
let headers: Record<string, string> = { let headers: Record<string, string> = {
'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', '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',
'referer': typeof options === 'string' ? options : options.url,
}; };
if (typeof options === 'string') { if (typeof options === 'string') {
url = options; url = options;
@@ -160,8 +161,7 @@ type Uri2LocalRes = {
errMsg: string, errMsg: string,
fileName: string, fileName: string,
ext: string, ext: string,
path: string, path: string
isLocal: boolean
} }
export async function checkFileV2(filePath: string) { export async function checkFileV2(filePath: string) {
@@ -194,7 +194,6 @@ export async function checkUriType(Uri: string) {
return undefined; return undefined;
}, Uri); }, Uri);
if (LocalFileRet) return LocalFileRet; if (LocalFileRet) return LocalFileRet;
const OtherFileRet = await solveProblem((uri: string) => { const OtherFileRet = await solveProblem((uri: string) => {
//再判断是否是Http //再判断是否是Http
if (uri.startsWith('http://') || uri.startsWith('https://')) { if (uri.startsWith('http://') || uri.startsWith('https://')) {
@@ -206,15 +205,19 @@ export async function checkUriType(Uri: string) {
} }
if (uri.startsWith('file://')) { if (uri.startsWith('file://')) {
let filePath: string; let filePath: string;
// await fs.copyFile(url.pathname, filePath);
const pathname = decodeURIComponent(new URL(uri).pathname); const pathname = decodeURIComponent(new URL(uri).pathname);
if (process.platform === 'win32') { if (process.platform === 'win32') {
filePath = pathname.slice(1); filePath = pathname.slice(1);
} else { } else {
filePath = pathname; filePath = pathname;
} }
return { Uri: filePath, Type: FileUriType.Local }; return { Uri: filePath, Type: FileUriType.Local };
} }
if (uri.startsWith('data:')) {
const data = uri.split(',')[1];
if (data) return { Uri: data, Type: FileUriType.Base64 };
}
}, Uri); }, Uri);
if (OtherFileRet) return OtherFileRet; if (OtherFileRet) return OtherFileRet;
@@ -224,34 +227,42 @@ export async function checkUriType(Uri: string) {
export async function uri2local(dir: string, uri: string, filename: string | undefined = undefined): Promise<Uri2LocalRes> { export async function uri2local(dir: string, uri: string, filename: string | undefined = undefined): Promise<Uri2LocalRes> {
const { Uri: HandledUri, Type: UriType } = await checkUriType(uri); const { Uri: HandledUri, Type: UriType } = await checkUriType(uri);
//解析失败 //解析失败
const tempName = randomUUID();
if (!filename) filename = randomUUID();
//解析Http和Https协议
if (UriType == FileUriType.Unknown) { if (UriType == FileUriType.Unknown) {
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false }; return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '' };
} }
//解析File协议和本地文件 //解析File协议和本地文件
if (UriType == FileUriType.Local) { if (UriType == FileUriType.Local) {
const fileExt = path.extname(HandledUri); const fileExt = path.extname(HandledUri);
const filename = path.basename(HandledUri, fileExt); let filename = path.basename(HandledUri, fileExt);
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: HandledUri, isLocal: true }; filename += fileExt;
//复制文件到临时文件并保持后缀
const filenameTemp = tempName + fileExt;
const filePath = path.join(dir, filenameTemp);
fs.copyFileSync(HandledUri, filePath);
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
} }
//接下来都要有文件名 //接下来都要有文件名
if (!filename) filename = randomUUID();
//解析Http和Https协议
if (UriType == FileUriType.Remote) { if (UriType == FileUriType.Remote) {
const pathInfo = path.parse(decodeURIComponent(new URL(HandledUri).pathname)); const pathInfo = path.parse(decodeURIComponent(new URL(HandledUri).pathname));
if (pathInfo.name) { if (pathInfo.name) {
filename = pathInfo.name; const pathlen = 200 - dir.length - pathInfo.name.length;
filename = pathlen > 0 ? pathInfo.name.substring(0, pathlen) : pathInfo.name.substring(pathInfo.name.length, pathInfo.name.length - 10);//过长截断
if (pathInfo.ext) { if (pathInfo.ext) {
filename += pathInfo.ext; filename += pathInfo.ext;
} }
} }
filename = filename.replace(/[/\\:*?"<>|]/g, '_'); filename = filename.replace(/[/\\:*?"<>|]/g, '_');
const fileExt = path.extname(HandledUri); const fileExt = path.extname(HandledUri).replace(/[/\\:*?"<>|]/g, '_').substring(0, 10);
const filePath = path.join(dir, filename); const filePath = path.join(dir, tempName + fileExt);
const buffer = await httpDownload(HandledUri); const buffer = await httpDownload(HandledUri);
fs.writeFileSync(filePath, buffer); //没有文件就创建
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: true }; fs.writeFileSync(filePath, buffer, { flag: 'wx' });
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
} }
//解析Base64 //解析Base64
if (UriType == FileUriType.Base64) { if (UriType == FileUriType.Base64) {
@@ -266,7 +277,7 @@ export async function uri2local(dir: string, uri: string, filename: string | und
fileExt = ext; fileExt = ext;
filename = filename + '.' + ext; filename = filename + '.' + ext;
} }
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: true }; return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
} }
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false }; return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '' };
} }

View File

@@ -25,29 +25,48 @@ export async function solveAsyncProblem<T extends (...args: any[]) => Promise<an
} }
export class FileNapCatOneBotUUID { export class FileNapCatOneBotUUID {
static encodeModelId(peer: Peer, modelId: string): string { static encodeModelId(peer: Peer, modelId: string, fileId: string, endString: string = ""): string {
return `NapCatOneBot-ModelIdFile-${peer.chatType}-${peer.peerUid}-${modelId}`; const data = `NapCatOneBot|ModelIdFile|${peer.chatType}|${peer.peerUid}|${modelId}|${fileId}`;
//前四个字节塞data长度
const length = Buffer.alloc(4 + data.length);
length.writeUInt32BE(data.length * 2, 0);//储存data的hex长度
length.write(data, 4);
return length.toString('hex') + endString;
} }
static decodeModelId(uuid: string): undefined | { static decodeModelId(uuid: string): undefined | {
peer: Peer, peer: Peer,
modelId: string modelId: string,
fileId: string
} { } {
if (!uuid.startsWith('NapCatOneBot-ModelIdFile-')) return undefined; //前四个字节是data长度
const data = uuid.split('-'); const length = Buffer.from(uuid.slice(0, 8), 'hex').readUInt32BE(0);
if (data.length !== 5) return undefined; //根据length计算需要读取的长度
const [, , chatType, peerUid, modelId] = data; const dataId = uuid.slice(8, 8 + length);
//hex还原为string
const realData = Buffer.from(dataId, 'hex').toString();
if (!realData.startsWith('NapCatOneBot|ModelIdFile|')) return undefined;
const data = realData.split('|');
if (data.length !== 6) return undefined;
const [, , chatType, peerUid, modelId, fileId] = data;
return { return {
peer: { peer: {
chatType: chatType as any, chatType: chatType as any,
peerUid: peerUid, peerUid: peerUid,
}, },
modelId, modelId,
fileId
}; };
} }
static encode(peer: Peer, msgId: string, elementId: string): string { static encode(peer: Peer, msgId: string, elementId: string, endString: string = ""): string {
return `NapCatOneBot-MsgFile-${peer.chatType}-${peer.peerUid}-${msgId}-${elementId}`; const data = `NapCatOneBot|MsgFile|${peer.chatType}|${peer.peerUid}|${msgId}|${elementId}`;
//前四个字节塞data长度
//一个字节8位 一个ascii字符1字节 一个hex字符4位 表示一个ascii字符需要两个hex字符
const length = Buffer.alloc(4 + data.length);
length.writeUInt32BE(data.length * 2, 0);
length.write(data, 4);
return length.toString('hex') + endString;
} }
static decode(uuid: string): undefined | { static decode(uuid: string): undefined | {
@@ -55,8 +74,14 @@ export class FileNapCatOneBotUUID {
msgId: string, msgId: string,
elementId: string elementId: string
} { } {
if (!uuid.startsWith('NapCatOneBot-MsgFile-')) return undefined; //前四个字节是data长度
const data = uuid.split('-'); const length = Buffer.from(uuid.slice(0, 8), 'hex').readUInt32BE(0);
//根据length计算需要读取的长度
const dataId = uuid.slice(8, 8 + length);
//hex还原为string
const realData = Buffer.from(dataId, 'hex').toString();
if (!realData.startsWith('NapCatOneBot|MsgFile|')) return undefined;
const data = realData.split('|');
if (data.length !== 6) return undefined; if (data.length !== 6) return undefined;
const [, , chatType, peerUid, msgId, elementId] = data; const [, , chatType, peerUid, msgId, elementId] = data;
return { return {
@@ -138,26 +163,38 @@ export function isEqual(obj1: any, obj2: any) {
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType { export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
if (os.platform() === 'linux') { if (os.platform() === 'linux') {
return { return {
baseVersion: '3.2.12-27254', baseVersion: '3.2.12-27597',
curVersion: '3.2.12-27254', curVersion: '3.2.12-27597',
prevVersion: '', prevVersion: '',
onErrorVersions: [], onErrorVersions: [],
buildId: '27254', buildId: '27597',
}; };
} }
return { return {
baseVersion: '9.9.15-27391', baseVersion: '9.9.15-27597',
curVersion: '9.9.15-27391', curVersion: '9.9.15-27597',
prevVersion: '', prevVersion: '',
onErrorVersions: [], onErrorVersions: [],
buildId: '27391', buildId: '27597',
}; };
} }
export function getQQPackageInfoPath(exePath: string = ''): string {
if (os.platform() === 'darwin') {
return path.join(path.dirname(exePath), '..', 'Resources', 'app', 'package.json');
} else {
return path.join(path.dirname(exePath), 'resources', 'app', 'package.json');
}
}
export function getQQVersionConfigPath(exePath: string = ''): string | undefined { export function getQQVersionConfigPath(exePath: string = ''): string | undefined {
let configVersionInfoPath; let configVersionInfoPath;
if (os.platform() !== 'linux') { if (os.platform() === 'win32') {
configVersionInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'versions', 'config.json'); configVersionInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'versions', 'config.json');
} else if (os.platform() === 'darwin') {
const userPath = os.homedir();
const appDataPath = path.resolve(userPath, './Library/Application Support/QQ');
configVersionInfoPath = path.resolve(appDataPath, './versions/config.json');
} else { } else {
const userPath = os.homedir(); const userPath = os.homedir();
const appDataPath = path.resolve(userPath, './.config/QQ'); const appDataPath = path.resolve(userPath, './.config/QQ');

View File

@@ -167,7 +167,8 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
function msgElementToText(element: MessageElement) { function msgElementToText(element: MessageElement) {
if (element.textElement) { if (element.textElement) {
if (element.textElement.atType === AtType.notAt) { if (element.textElement.atType === AtType.notAt) {
return element.textElement.content; const originalContentLines = element.textElement.content.split('\n');
return `${originalContentLines[0]}${originalContentLines.length > 1 ? ' ...' : ''}`;
} else if (element.textElement.atType === AtType.atAll) { } else if (element.textElement.atType === AtType.atAll) {
return `@全体成员`; return `@全体成员`;
} else if (element.textElement.atType === AtType.atUser) { } else if (element.textElement.atType === AtType.atUser) {
@@ -189,7 +190,7 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
} }
if (element.picElement) { if (element.picElement) {
return `[图片 ${element.picElement.fileName}]`; return '[图片]';
} }
if (element.fileElement) { if (element.fileElement) {
@@ -197,7 +198,7 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
} }
if (element.videoElement) { if (element.videoElement) {
return `[视频 ${element.videoElement.fileName}]`; return '[视频]';
} }
if (element.pttElement) { if (element.pttElement) {
@@ -205,7 +206,7 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
} }
if (element.arkElement) { if (element.arkElement) {
return `[卡片消息 ${element.arkElement.bytesData}]`; return '[卡片消息]';
} }
if (element.faceElement) { if (element.faceElement) {
@@ -213,19 +214,19 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
} }
if (element.marketFaceElement) { if (element.marketFaceElement) {
return `[商城表情 ${element.marketFaceElement.faceName}]`; return element.marketFaceElement.faceName;
} }
if (element.markdownElement) { if (element.markdownElement) {
return `[Markdown ${element.markdownElement.content}]`; return '[Markdown 消息]';
} }
if (element.multiForwardMsgElement) { if (element.multiForwardMsgElement) {
return `[转发消息]`; return '[转发消息]';
} }
if (element.elementType === ElementType.GreyTip) { if (element.elementType === ElementType.GreyTip) {
return `[灰条消息]`; // TODO: resolve the text return '[灰条消息]';
} }
return `[未实现 (ElementType = ${element.elementType})]`; return `[未实现 (ElementType = ${element.elementType})]`;

View File

@@ -1,6 +1,7 @@
import path, { dirname } from 'path'; import path, { dirname } from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import fs from 'fs'; import fs from 'fs';
import os from 'os';
export class NapCatPathWrapper { export class NapCatPathWrapper {
binaryPath: string; binaryPath: string;
@@ -11,17 +12,23 @@ export class NapCatPathWrapper {
constructor(mainPath: string = dirname(fileURLToPath(import.meta.url))) { constructor(mainPath: string = dirname(fileURLToPath(import.meta.url))) {
this.binaryPath = mainPath; this.binaryPath = mainPath;
this.logsPath = path.join(this.binaryPath, 'logs'); let writePath: string;
this.configPath = path.join(this.binaryPath, 'config'); if (os.platform() === 'darwin') {
this.cachePath = path.join(this.binaryPath, 'cache'); writePath = path.join(os.homedir(), 'Library', 'Application Support', 'QQ', 'NapCat');
} else {
writePath = this.binaryPath;
}
this.logsPath = path.join(writePath, 'logs');
this.configPath = path.join(writePath, 'config');
this.cachePath = path.join(writePath, 'cache');
this.staticPath = path.join(this.binaryPath, 'static'); this.staticPath = path.join(this.binaryPath, 'static');
if (fs.existsSync(this.logsPath)) { if (!fs.existsSync(this.logsPath)) {
fs.mkdirSync(this.logsPath, { recursive: true }); fs.mkdirSync(this.logsPath, { recursive: true });
} }
if (fs.existsSync(this.configPath)) { if (!fs.existsSync(this.configPath)) {
fs.mkdirSync(this.configPath, { recursive: true }); fs.mkdirSync(this.configPath, { recursive: true });
} }
if (fs.existsSync(this.cachePath)) { if (!fs.existsSync(this.cachePath)) {
fs.mkdirSync(this.cachePath, { recursive: true }); fs.mkdirSync(this.cachePath, { recursive: true });
} }
} }

View File

@@ -1,7 +1,6 @@
import path from 'node:path';
import fs from 'node:fs'; import fs from 'node:fs';
import { systemPlatform } from '@/common/system'; import { systemPlatform } from '@/common/system';
import { getDefaultQQVersionConfigInfo, getQQVersionConfigPath } from './helper'; import { getDefaultQQVersionConfigInfo, getQQPackageInfoPath, getQQVersionConfigPath } from './helper';
import AppidTable from '@/core/external/appid.json'; import AppidTable from '@/core/external/appid.json';
import { LogWrapper } from './log'; import { LogWrapper } from './log';
@@ -20,7 +19,7 @@ export class QQBasicInfoWrapper {
//基础目录获取 //基础目录获取
this.context = context; this.context = context;
this.QQMainPath = process.execPath; this.QQMainPath = process.execPath;
this.QQPackageInfoPath = path.join(path.dirname(this.QQMainPath), 'resources', 'app', 'package.json'); this.QQPackageInfoPath = getQQPackageInfoPath(this.QQMainPath);
this.QQVersionConfigPath = getQQVersionConfigPath(this.QQMainPath); this.QQVersionConfigPath = getQQVersionConfigPath(this.QQMainPath);
//基础信息获取 无快更则启用默认模板填充 //基础信息获取 无快更则启用默认模板填充
@@ -53,9 +52,25 @@ export class QQBasicInfoWrapper {
//此方法不要直接使用 //此方法不要直接使用
getQUAInternal() { getQUAInternal() {
return systemPlatform === 'linux' switch (systemPlatform) {
? `V1_LNX_NQ_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B` case 'linux':
: `V1_WIN_NQ_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`; return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
case 'darwin':
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
default:
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
}
}
getAppidInternal() {
switch (systemPlatform) {
case 'linux':
return '537243600';
case 'darwin':
return '537243441';
default:
return '537243538';
}
} }
getAppidV2(): { appid: string; qua: string } { getAppidV2(): { appid: string; qua: string } {
@@ -71,6 +86,6 @@ export class QQBasicInfoWrapper {
// else // else
this.context.logger.log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`); this.context.logger.log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`);
this.context.logger.log(`[QQ版本兼容性检测] ${fullVersion} 版本兼容性不佳,可能会导致一些功能无法正常使用`,); this.context.logger.log(`[QQ版本兼容性检测] ${fullVersion} 版本兼容性不佳,可能会导致一些功能无法正常使用`,);
return { appid: systemPlatform === 'linux' ? '537240795' : '537240709', qua: this.getQUAInternal() }; return { appid: this.getAppidInternal(), qua: this.getQUAInternal() };
} }
} }

View File

@@ -1 +1 @@
export const napCatVersion = '2.2.30'; export const napCatVersion = '2.4.9';

View File

@@ -1,9 +1,8 @@
import { MsfChangeReasonType, MsfStatusType } from "../entities/adapter";
export class NodeIDependsAdapter { export class NodeIDependsAdapter {
onMSFStatusChange(arg1: number, arg2: number) { onMSFStatusChange(statusType: MsfStatusType, changeReasonType: MsfChangeReasonType) {
// console.log(arg1, arg2);
// if (arg1 == 2 && arg2 == 2) {
// log("NapCat丢失网络连接,请检查网络")
// }
} }
onMSFSsoError(args: unknown) { onMSFSsoError(args: unknown) {

View File

@@ -1,63 +0,0 @@
import {
CacheFileListItem,
CacheFileType,
ChatCacheListItemBasic,
ChatType,
InstanceContext,
NapCatCore,
} from '@/core';
export class NTQQCacheApi {
context: InstanceContext;
core: NapCatCore;
constructor(context: InstanceContext, core: NapCatCore) {
this.context = context;
this.core = core;
}
async setCacheSilentScan(isSilent: boolean = true) {
return '';
}
getCacheSessionPathList() {
return '';
}
clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
// 参数未验证
return this.context.session.getStorageCleanService().clearCacheDataByKeys(cacheKeys);
}
addCacheScannedPaths(pathMap: object = {}) {
return this.context.session.getStorageCleanService().addCacheScanedPaths(pathMap);
}
scanCache() {
//return (await this.context.session.getStorageCleanService().scanCache()).size;
}
getHotUpdateCachePath() {
// 未实现
return '';
}
getDesktopTmpPath() {
// 未实现
return '';
}
getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) {
return this.context.session.getStorageCleanService().getChatCacheInfo(type, pageSize, 1, pageIndex);
}
getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
// const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
// 需要五个参数
// return napCatCore.session.getStorageCleanService().getFileCacheInfo();
}
async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
return this.context.session.getStorageCleanService().clearChatCacheInfo(chats, fileKeys);
}
}

View File

@@ -24,6 +24,7 @@ import pathLib from 'node:path';
import { defaultVideoThumbB64, getVideoInfo } from '@/common/video'; import { defaultVideoThumbB64, getVideoInfo } from '@/common/video';
import ffmpeg from 'fluent-ffmpeg'; import ffmpeg from 'fluent-ffmpeg';
import { encodeSilk } from '@/common/audio'; import { encodeSilk } from '@/common/audio';
import { MessageContext } from '@/onebot/api';
export class NTQQFileApi { export class NTQQFileApi {
context: InstanceContext; context: InstanceContext;
@@ -33,7 +34,7 @@ export class NTQQFileApi {
constructor(context: InstanceContext, core: NapCatCore) { constructor(context: InstanceContext, core: NapCatCore) {
this.context = context; this.context = context;
this.core = core; this.core = core;
this.rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey', this.context.logger); this.rkeyManager = new RkeyManager(['https://llob.linyuchen.net/rkey', 'http://napcat-sign.wumiao.wang:2082/rkey'], this.context.logger);
} }
async copyFile(filePath: string, destPath: string) { async copyFile(filePath: string, destPath: string) {
@@ -71,7 +72,7 @@ export class NTQQFileApi {
file_uuid: '', file_uuid: '',
}); });
await this.copyFile(filePath, mediaPath!); await this.copyFile(filePath, mediaPath);
const fileSize = await this.getFileSize(filePath); const fileSize = await this.getFileSize(filePath);
return { return {
md5: fileMd5, md5: fileMd5,
@@ -82,7 +83,7 @@ export class NTQQFileApi {
}; };
} }
async createValidSendFileElement(filePath: string, fileName: string = '', folderId: string = '',): Promise<SendFileElement> { async createValidSendFileElement(context: MessageContext, filePath: string, fileName: string = '', folderId: string = '',): Promise<SendFileElement> {
const { const {
fileName: _fileName, fileName: _fileName,
path, path,
@@ -91,6 +92,7 @@ export class NTQQFileApi {
if (fileSize === 0) { if (fileSize === 0) {
throw new Error('文件异常大小为0'); throw new Error('文件异常大小为0');
} }
context.deleteAfterSentFiles.push(path);
return { return {
elementType: ElementType.FILE, elementType: ElementType.FILE,
elementId: '', elementId: '',
@@ -103,12 +105,13 @@ export class NTQQFileApi {
}; };
} }
async createValidSendPicElement(picPath: string, summary: string = '', subType: 0 | 1 = 0,): Promise<SendPicElement> { async createValidSendPicElement(context: MessageContext, picPath: string, summary: string = '', subType: 0 | 1 = 0,): Promise<SendPicElement> {
const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType); const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType);
if (fileSize === 0) { if (fileSize === 0) {
throw new Error('文件异常大小为0'); throw new Error('文件异常大小为0');
} }
const imageSize = await this.core.apis.FileApi.getImageSize(picPath); const imageSize = await this.core.apis.FileApi.getImageSize(picPath);
context.deleteAfterSentFiles.push(path);
return { return {
elementType: ElementType.PIC, elementType: ElementType.PIC,
elementId: '', elementId: '',
@@ -130,26 +133,40 @@ export class NTQQFileApi {
}; };
} }
async createValidSendVideoElement(filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> { async createValidSendVideoElement(context: MessageContext, filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> {
const logger = this.core.context.logger; const logger = this.core.context.logger;
const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
if (fileSize === 0) {
throw new Error('文件异常大小为0');
}
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
thumb = pathLib.dirname(thumb);
let videoInfo = { let videoInfo = {
width: 1920, height: 1080, width: 1920, height: 1080,
time: 15, time: 15,
format: 'mp4', format: 'mp4',
size: fileSize, size: 0,
filePath, filePath,
}; };
try { try {
videoInfo = await getVideoInfo(path, logger); videoInfo = await getVideoInfo(filePath, logger);
} catch (e) { } catch (e) {
logger.logError('获取视频信息失败,将使用默认值', e); logger.logError('获取视频信息失败,将使用默认值', e);
} }
let fileExt = 'mp4'
try {
let tempExt = (await fileType.fileTypeFromFile(filePath))?.ext;
if (tempExt) fileExt = tempExt;
} catch (e) {
this.context.logger.logError('获取文件类型失败', e);
}
const newFilePath = filePath + '.'+fileExt;
fs.copyFileSync(filePath, newFilePath);
context.deleteAfterSentFiles.push(newFilePath);
filePath = newFilePath;
const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
if (fileSize === 0) {
throw new Error('文件异常大小为0');
}
videoInfo.size = fileSize;
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
thumb = pathLib.dirname(thumb);
const thumbPath = new Map(); const thumbPath = new Map();
const _thumbPath = await new Promise<string | undefined>((resolve, reject) => { const _thumbPath = await new Promise<string | undefined>((resolve, reject) => {
const thumbFileName = `${md5}_0.png`; const thumbFileName = `${md5}_0.png`;
@@ -179,6 +196,7 @@ export class NTQQFileApi {
const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0; const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0;
thumbPath.set(0, _thumbPath); thumbPath.set(0, _thumbPath);
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : ''; const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : '';
context.deleteAfterSentFiles.push(path);
return { return {
elementType: ElementType.VIDEO, elementType: ElementType.VIDEO,
elementId: '', elementId: '',
@@ -207,7 +225,9 @@ export class NTQQFileApi {
throw new Error('文件异常大小为0'); throw new Error('文件异常大小为0');
} }
if (converted) { if (converted) {
fsPromises.unlink(silkPath); fsPromises.unlink(silkPath).then().catch(
(e) => this.context.logger.logError('删除临时文件失败', e)
);
} }
return { return {
elementType: ElementType.PTT, elementType: ElementType.PTT,
@@ -246,7 +266,6 @@ export class NTQQFileApi {
} }
async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) { 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 (sourcePath && fs.existsSync(sourcePath)) {
if (force) { if (force) {
@@ -298,65 +317,6 @@ export class NTQQFileApi {
}); });
} }
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.KCHATTYPEGROUP) {
GroupData =
[{
groupCode: peer.peerUid,
isConf: false,
hasModifyConfGroupFace: true,
hasModifyConfGroupName: true,
groupName: 'NapCat.Cached',
remark: 'NapCat.Cached',
}];
} else if (peer.chatType === ChatType.KCHATTYPEC2C) {
BuddyData = [{
category_name: 'NapCat.Cached',
peerUid: peer.peerUid,
peerUin: peer.peerUid,
remark: 'NapCat.Cached',
}];
} else {
return undefined;
}
return this.context.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,
}],
},
],
});
}
async searchForFile(keys: string[]): Promise<SearchResultItem | undefined> { async searchForFile(keys: string[]): Promise<SearchResultItem | undefined> {
const randomResultId = 100000 + Math.floor(Math.random() * 10000); const randomResultId = 100000 + Math.floor(Math.random() * 10000);
let searchId = 0; let searchId = 0;
@@ -398,15 +358,15 @@ export class NTQQFileApi {
if (!element) { if (!element) {
return ''; return '';
} }
const url: string = element.originImageUrl!; // 没有域名 const url: string = element.originImageUrl ?? '';
const md5HexStr = element.md5HexStr; const md5HexStr = element.md5HexStr;
const fileMd5 = element.md5HexStr; const fileMd5 = element.md5HexStr;
if (url) { if (url) {
const parsedUrl = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接 const parsedUrl = new URL(IMAGE_HTTP_HOST + url);
const imageAppid = parsedUrl.searchParams.get('appid'); const imageAppid = parsedUrl.searchParams.get('appid');
const isNTFlavoredPic = imageAppid && ['1406', '1407'].includes(imageAppid); const isNTV2 = imageAppid && ['1406', '1407'].includes(imageAppid);
if (isNTFlavoredPic) { if (isNTV2) {
let rkey = parsedUrl.searchParams.get('rkey'); let rkey = parsedUrl.searchParams.get('rkey');
if (rkey) { if (rkey) {
return IMAGE_HTTP_HOST_NT + url; return IMAGE_HTTP_HOST_NT + url;
@@ -415,11 +375,9 @@ export class NTQQFileApi {
rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey; rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
return IMAGE_HTTP_HOST_NT + url + `${rkey}`; return IMAGE_HTTP_HOST_NT + url + `${rkey}`;
} else { } else {
// 老的图片url不需要rkey
return IMAGE_HTTP_HOST + url; return IMAGE_HTTP_HOST + url;
} }
} else if (fileMd5 || md5HexStr) { } else if (fileMd5 || md5HexStr) {
// 没有url需要自己拼接
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`; return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`;
} }
this.context.logger.logDebug('图片url获取失败', element); this.context.logger.logDebug('图片url获取失败', element);

View File

@@ -6,14 +6,9 @@ export class NTQQFriendApi {
context: InstanceContext; context: InstanceContext;
core: NapCatCore; core: NapCatCore;
// friends: Map<string, Friend> = new Map<string, FriendV2>();
constructor(context: InstanceContext, core: NapCatCore) { constructor(context: InstanceContext, core: NapCatCore) {
this.context = context; this.context = context;
this.core = core; this.core = core;
// if (!this.context.basicInfoWrapper.requireMinNTQQBuild('26702')) {
// this.getFriends(true);
// }
} }
async getBuddyV2SimpleInfoMap(refresh = false) { async getBuddyV2SimpleInfoMap(refresh = false) {

View File

@@ -1,5 +1,4 @@
import { import {
ChatType,
GeneralCallResult, GeneralCallResult,
Group, Group,
GroupMember, GroupMember,
@@ -10,8 +9,9 @@ import {
MemberExtSourceType, MemberExtSourceType,
NapCatCore, NapCatCore,
} from '@/core'; } from '@/core';
import { isNumeric, runAllWithTimeout } from '@/common/helper'; import { isNumeric, solveAsyncProblem } from '@/common/helper';
import { LimitedHashTable } from '@/common/message-unique'; import { LimitedHashTable } from '@/common/message-unique';
import { NTEventWrapper } from '@/common/event';
export class NTQQGroupApi { export class NTQQGroupApi {
context: InstanceContext; context: InstanceContext;
@@ -24,7 +24,7 @@ export class NTQQGroupApi {
constructor(context: InstanceContext, core: NapCatCore) { constructor(context: InstanceContext, core: NapCatCore) {
this.context = context; this.context = context;
this.core = core; this.core = core;
this.initCache().then().catch(context.logger.logError); this.initCache().then().catch(context.logger.logError.bind(context.logger));
} }
async initCache() { async initCache() {
@@ -44,8 +44,8 @@ export class NTQQGroupApi {
}, pskey); }, pskey);
} }
async clearGroupNotifiesUnreadCount(unk: boolean) { async clearGroupNotifiesUnreadCount(uk: boolean) {
return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(unk); return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(uk);
} }
async setGroupAvatar(gc: string, filePath: string) { async setGroupAvatar(gc: string, filePath: string) {
@@ -61,9 +61,9 @@ export class NTQQGroupApi {
return groupList; return groupList;
} }
async getGroupExtFE0Info(GroupCode: string[], forced = true) { async getGroupExtFE0Info(groupCode: string[], forced = true) {
return this.context.session.getGroupService().getGroupExt0xEF0Info( return this.context.session.getGroupService().getGroupExt0xEF0Info(
GroupCode, groupCode,
[], [],
{ {
bindGuildId: 1, bindGuildId: 1,
@@ -121,53 +121,8 @@ export class NTQQGroupApi {
return group; return group;
} }
async getGroupMemberLatestSendTimeCache(GroupCode: string, uids: string[]) { async getGroupMemberAll(groupCode: string, forced = false) {
return this.getGroupMemberLatestSendTime(GroupCode, uids); return this.context.session.getGroupService().getAllMemberList(groupCode, forced);
}
async getGroupMemberLatestSendTime(GroupCode: string, uids: string[]) {
const getData = async (uid: string) => {
const msgListWrapper = await this.getLatestMsgByUids(GroupCode, [uid]);
if (msgListWrapper.result !== 0 && msgListWrapper.msgList.length < 1) {
return undefined;
}
return { sendUin: msgListWrapper.msgList[0].senderUin, sendTime: msgListWrapper.msgList[0].msgTime };
};
const PromiseData: Promise<({
sendUin: string;
sendTime: string;
} | undefined)>[] = [];
const ret: Map<string, string> = new Map();
for (const uid of uids) {
PromiseData.push(getData(uid).catch(() => undefined));
}
const allRet = await runAllWithTimeout(PromiseData, 2500);
for (const PromiseDo of allRet) {
if (PromiseDo) {
ret.set(PromiseDo.sendUin, PromiseDo.sendTime);
}
}
return ret;
}
async getLatestMsgByUids(GroupCode: string, uids: string[]) {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
chatInfo: {
peerUid: GroupCode,
chatType: ChatType.KCHATTYPEGROUP,
},
filterMsgType: [],
filterSendersUid: uids,
filterMsgToTime: '0',
filterMsgFromTime: '0',
isReverseOrder: false,
isIncludeCurrent: true,
pageLimit: 1,
});
}
async getGroupMemberAll(GroupCode: string, forced = false) {
return this.context.session.getGroupService().getAllMemberList(GroupCode, forced);
} }
async getGroupMember(groupCode: string | number, memberUinOrUid: string | number) { async getGroupMember(groupCode: string | number, memberUinOrUid: string | number) {
@@ -202,32 +157,8 @@ export class NTQQGroupApi {
} }
return member; return member;
} }
async getGroupRecommendContactArkJson(groupCode: string) {
async getLatestMsg(GroupCode: string, uins: string[]) { return this.context.session.getGroupService().getGroupRecommendContactArkJson(groupCode);
const uids: Array<string> = [];
for (const uin of uins) {
const uid = await this.core.apis.UserApi.getUidByUinV2(uin);
if (uid) {
uids.push(uid);
}
}
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
chatInfo: {
peerUid: GroupCode,
chatType: ChatType.KCHATTYPEGROUP,
},
filterMsgType: [],
filterSendersUid: uids,
filterMsgToTime: '0',
filterMsgFromTime: '0',
isReverseOrder: false,
isIncludeCurrent: true,
pageLimit: 1,
});
}
async getGroupRecommendContactArkJson(GroupCode: string) {
return this.context.session.getGroupService().getGroupRecommendContactArkJson(GroupCode);
} }
async CreatGroupFileFolder(groupCode: string, folderName: string) { async CreatGroupFileFolder(groupCode: string, folderName: string) {
@@ -243,7 +174,6 @@ export class NTQQGroupApi {
} }
async addGroupEssence(GroupCode: string, msgId: string) { async addGroupEssence(GroupCode: string, msgId: string) {
// 需要 ob11msgId -> msgId + (peer) -> msgSeq + msgRandom
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({ const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
chatType: 2, chatType: 2,
guildId: '', guildId: '',
@@ -254,7 +184,6 @@ export class NTQQGroupApi {
msgRandom: parseInt(MsgData.msgList[0].msgRandom), msgRandom: parseInt(MsgData.msgList[0].msgRandom),
msgSeq: parseInt(MsgData.msgList[0].msgSeq), msgSeq: parseInt(MsgData.msgList[0].msgSeq),
}; };
// GetMsgByShortID(shortID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
return this.context.session.getGroupService().addGroupEssence(param); return this.context.session.getGroupService().addGroupEssence(param);
} }
@@ -272,7 +201,6 @@ export class NTQQGroupApi {
groupCode: GroupCode, groupCode: GroupCode,
needDeleteLocalMsg: needDeleteLocalMsg, needDeleteLocalMsg: needDeleteLocalMsg,
}; };
//应该是直接返回不需要Listener的 未经测试 需测试再发布
return this.context.session.getGroupService().quitGroupV2(param); return this.context.session.getGroupService().quitGroupV2(param);
} }
@@ -317,7 +245,7 @@ export class NTQQGroupApi {
'NodeIKernelGroupListener/onMemberInfoChange', 'NodeIKernelGroupListener/onMemberInfoChange',
1, 1,
forced ? 5000 : 250, forced ? 5000 : 250,
(params) => params === GroupCode, (params, _, members) => params === GroupCode && members.size > 0,
); );
const retData = await ( const retData = await (
this.core.eventWrapper this.core.eventWrapper
@@ -334,14 +262,51 @@ export class NTQQGroupApi {
} }
return member; return member;
} }
async searchGroup(groupCode: string) {
const [, ret] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelSearchService/searchGroup',
'NodeIKernelSearchListener/onSearchGroupResult',
[{
keyWords: groupCode,
groupNum: 25,
exactSearch: false,
penetrate: ''
}],
(ret) => ret.result === 0,
(params) => !!params.groupInfos.find(g => g.groupCode === groupCode),
1,
5000
);
return ret.groupInfos.find(g => g.groupCode === groupCode);
}
async getGroupMemberEx(GroupCode: string, uid: string, forced = false, retry = 2) {
const data = await solveAsyncProblem((eventWrapper: NTEventWrapper, GroupCode: string, uid: string, forced = false) => {
return eventWrapper.callNormalEventV2(
'NodeIKernelGroupService/getMemberInfo',
'NodeIKernelGroupListener/onMemberInfoChange',
[GroupCode, [uid], forced],
(ret) => ret.result === 0,
(params, _, members) => params === GroupCode && members.size > 0 && members.has(uid),
1,
forced ? 2500 : 250
);
}, this.core.eventWrapper, GroupCode, uid, forced);
if (data && data[3] instanceof Map && data[3].has(uid)) {
return data[3].get(uid);
}
if (retry > 0) {
const trydata = await this.getGroupMemberEx(GroupCode, uid, true, retry - 1) as GroupMember | undefined;
if (trydata) return trydata;
}
return undefined;
}
async getGroupMembersV2(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> { async getGroupMembersV2(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
const groupService = this.context.session.getGroupService(); const groupService = this.context.session.getGroupService();
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow'); const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
const listener = this.core.eventWrapper.registerListen( const listener = this.core.eventWrapper.registerListen(
'NodeIKernelGroupListener/onMemberListChange', 'NodeIKernelGroupListener/onMemberListChange',
1, 1,
500, 5000,
(params) => params.sceneId === sceneId, (params) => params.sceneId === sceneId,
); );
try { try {
@@ -374,8 +339,7 @@ export class NTQQGroupApi {
if (result.errCode !== 0) { if (result.errCode !== 0) {
throw new Error('获取群成员列表出错,' + result.errMsg); throw new Error('获取群成员列表出错,' + result.errMsg);
} }
this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`);
this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`); //, Array.from(result.result.infos.values()));
return result.result.infos; return result.result.infos;
} }
@@ -383,9 +347,6 @@ export class NTQQGroupApi {
return this.context.session.getRichMediaService().batchGetGroupFileCount(Gids); return this.context.session.getRichMediaService().batchGetGroupFileCount(Gids);
} }
async getGroupIgnoreNotifies() {
}
async getArkJsonGroupShare(GroupCode: string) { async getArkJsonGroupShare(GroupCode: string) {
const ret = await this.core.eventWrapper.callNoListenerEvent( const ret = await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelGroupService/getGroupRecommendContactArkJson', 'NodeIKernelGroupService/getGroupRecommendContactArkJson',
@@ -409,12 +370,12 @@ export class NTQQGroupApi {
return this.context.session.getGroupService().operateSysNotify( return this.context.session.getGroupService().operateSysNotify(
false, false,
{ {
'operateType': operateType, // 2 拒绝 operateType: operateType, // 2 拒绝
'targetMsg': { targetMsg: {
'seq': seq, // 通知序列号 seq: seq, // 通知序列号
'type': type, type: type,
'groupCode': groupCode, groupCode: groupCode,
'postscript': reason ?? ' ', // 仅传空值可能导致处理失败,故默认给个空格 postscript: reason ?? ' ', // 仅传空值可能导致处理失败,故默认给个空格
}, },
}); });
} }
@@ -470,7 +431,6 @@ export class NTQQGroupApi {
} }
async getMemberExtInfo(groupCode: string, uin: string) { async getMemberExtInfo(groupCode: string, uin: string) {
// 仅NTQQ 9.9.11 24568测试 容易炸开谨慎使用
return this.context.session.getGroupService().getMemberExtInfo( return this.context.session.getGroupService().getMemberExtInfo(
{ {
groupCode: groupCode, groupCode: groupCode,

View File

@@ -6,4 +6,3 @@ export * from './user';
export * from './webapi'; export * from './webapi';
export * from './sign'; export * from './sign';
export * from './system'; export * from './system';
export * from './cache';

View File

@@ -19,14 +19,6 @@ export class NTQQMsgApi {
return this.context.session.getMsgService().getAioFirstViewLatestMsgs(peer, MsgCount); return this.context.session.getMsgService().getAioFirstViewLatestMsgs(peer, MsgCount);
} }
async getLatestDbMsgs(peer: Peer, MsgCount: number) {
return this.context.session.getMsgService().getLatestDbMsgs(peer, MsgCount);
}
async FetchLongMsg(peer: Peer, msgId: string) {
return this.context.session.getMsgService().fetchLongMsg(peer, msgId);
}
async sendShowInputStatusReq(peer: Peer, eventType: number) { async sendShowInputStatusReq(peer: Peer, eventType: number) {
return this.context.session.getMsgService().sendShowInputStatusReq(peer.chatType, eventType, peer.peerUid); return this.context.session.getMsgService().sendShowInputStatusReq(peer.chatType, eventType, peer.peerUid);
} }
@@ -37,9 +29,6 @@ export class NTQQMsgApi {
} }
async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) { 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(); emojiId = emojiId.toString();
return this.context.session.getMsgService().setMsgEmojiLikes(peer, msgSeq, emojiId, emojiId.length > 3 ? '2' : '1', set); return this.context.session.getMsgService().setMsgEmojiLikes(peer, msgSeq, emojiId, emojiId.length > 3 ? '2' : '1', set);
} }
@@ -54,19 +43,6 @@ export class NTQQMsgApi {
return this.context.session.getMsgService().forwardMsg(msgIds, peer, [peer], new Map()); return this.context.session.getMsgService().forwardMsg(msgIds, peer, [peer], new Map());
} }
async getLatestMsgByUids(peer: Peer, count: number = 20, isReverseOrder: boolean = false) {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
chatInfo: peer,
filterMsgType: [],
filterSendersUid: [],
filterMsgToTime: '0',
filterMsgFromTime: '0',
isReverseOrder: isReverseOrder,//此参数有点离谱 注意不是本次查询的排序 而是全部消历史信息的排序 默认false 从新消息拉取到旧消息
isIncludeCurrent: true,
pageLimit: count,
});
}
async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) { async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) {
if (!peer) throw new Error('peer is not allowed'); if (!peer) throw new Error('peer is not allowed');
if (!msgIds) throw new Error('msgIds is not allowed'); if (!msgIds) throw new Error('msgIds is not allowed');
@@ -94,11 +70,33 @@ export class NTQQMsgApi {
pageLimit: 1, pageLimit: 1,
}); });
} }
async queryMsgsWithFilterExWithSeqV2(peer: Peer, msgSeq: string, MsgTime: string, SendersUid: string[]) {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
chatInfo: peer,
filterMsgType: [],
filterSendersUid: SendersUid,
filterMsgToTime: MsgTime,
filterMsgFromTime: MsgTime,
isReverseOrder: false,
isIncludeCurrent: true,
pageLimit: 1,
});
}
async queryFirstMsgBySeq(peer: Peer, msgSeq: string) {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
chatInfo: peer,
filterMsgType: [],
filterSendersUid: [],
filterMsgToTime: '0',
filterMsgFromTime: '0',
isReverseOrder: true,
isIncludeCurrent: true,
pageLimit: 1,
});
}
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) { async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z); return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
} }
async getMsgExBySeq(peer: Peer, msgSeq: string) { async getMsgExBySeq(peer: Peer, msgSeq: string) {
const DateNow = Math.floor(Date.now() / 1000); const DateNow = Math.floor(Date.now() / 1000);
const filterMsgFromTime = (DateNow - 300).toString(); const filterMsgFromTime = (DateNow - 300).toString();
@@ -140,11 +138,16 @@ export class NTQQMsgApi {
return this.context.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, isReverseOrder); return this.context.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, isReverseOrder);
} }
async recallMsg(peer: Peer, msgIds: string[]) { async recallMsg(peer: Peer, msgId: string) {
await this.context.session.getMsgService().recallMsg({ await this.core.eventWrapper.callNormalEventV2(
chatType: peer.chatType, 'NodeIKernelMsgService/recallMsg',
peerUid: peer.peerUid, 'NodeIKernelMsgListener/onMsgInfoListUpdate',
}, msgIds); [peer, [msgId]],
() => true,
(updatedList) => updatedList.find(m => m.msgId === msgId && m.recallTime !== '0') !== undefined,
1,
1000,
);
} }
async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) { async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) {
@@ -178,7 +181,7 @@ export class NTQQMsgApi {
await this.PrepareTempChat(peer.peerUid, peer.guildId, member.nick); await this.PrepareTempChat(peer.peerUid, peer.guildId, member.nick);
} }
} }
const msgId = await this.generateMsgUniqueId(peer.chatType, await this.getServerTime()); const msgId = await this.generateMsgUniqueId(peer.chatType);
peer.guildId = msgId; peer.guildId = msgId;
const [, msgList] = await this.core.eventWrapper.callNormalEventV2( const [, msgList] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelMsgService/sendMsg', 'NodeIKernelMsgService/sendMsg',
@@ -204,12 +207,8 @@ export class NTQQMsgApi {
return msgList.find(msgRecord => msgRecord.guildId === msgId); return msgList.find(msgRecord => msgRecord.guildId === msgId);
} }
async generateMsgUniqueId(chatType: number, time: string) { async generateMsgUniqueId(chatType: number) {
return this.context.session.getMsgService().generateMsgUniqueId(chatType, time); return this.context.session.getMsgService().generateMsgUniqueId(chatType, this.context.session.getMSFService().getServerTime());
}
async getServerTime() {
return this.context.session.getMSFService().getServerTime();
} }
async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) { async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {

View File

@@ -214,11 +214,6 @@ export class NTQQMusicSignApi {
//console.log(MusicReal); //console.log(MusicReal);
return { ...MusicReal.data, mid: signedMid }; return { ...MusicReal.data, mid: signedMid };
} }
async CreateMusicThirdWay1(id: string = '', mid: string = '') {
}
//转换外域名为 https://qq.ugcimg.cn/v1/cpqcbu4b8870i61bde6k7cbmjgejq8mr3in82qir4qi7ielffv5slv8ck8g42novtmev26i233ujtuab6tvu2l2sjgtupfr389191v00s1j5oh5325j5eqi40774jv1i/khovifoh7jrqd6eahoiv7koh8o //转换外域名为 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 //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

View File

@@ -22,7 +22,7 @@ export class NTQQSystemApi {
} }
async getOnlineDev() { async getOnlineDev() {
return this.context.session.getMsgService().getOnLineDev(); this.context.session.getMsgService().getOnLineDev();
} }
async getArkJsonCollection(cid: string) { async getArkJsonCollection(cid: string) {

View File

@@ -1,7 +1,6 @@
import type { ModifyProfileParams, User } from '@/core/entities'; import { ModifyProfileParams, User, UserDetailSource } from '@/core/entities';
import { RequestUtil } from '@/common/request'; import { RequestUtil } from '@/common/request';
import { ProfileBizType, UserDetailSource } from '@/core/services'; import { InstanceContext, NapCatCore, ProfileBizType } from '..';
import { InstanceContext, NapCatCore } from '..';
import { solveAsyncProblem } from '@/common/helper'; import { solveAsyncProblem } from '@/common/helper';
export class NTQQUserApi { export class NTQQUserApi {
@@ -75,7 +74,6 @@ export class NTQQUserApi {
(profile) => profile.uid === uid, (profile) => profile.uid === uid,
); );
const RetUser: User = { const RetUser: User = {
...profile.simpleInfo.coreInfo,
...profile.simpleInfo.status, ...profile.simpleInfo.status,
...profile.simpleInfo.vasInfo, ...profile.simpleInfo.vasInfo,
...profile.commonExt, ...profile.commonExt,
@@ -83,17 +81,22 @@ export class NTQQUserApi {
qqLevel: profile.commonExt?.qqLevel, qqLevel: profile.commonExt?.qqLevel,
age: profile.simpleInfo.baseInfo.age, age: profile.simpleInfo.baseInfo.age,
pendantId: '', pendantId: '',
...profile.simpleInfo.coreInfo
}; };
return RetUser; return RetUser;
} }
async getUserDetailInfo(uid: string): Promise<User> { async getUserDetailInfo(uid: string): Promise<User> {
const retUser = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, UserDetailSource.KDB), uid); let retUser = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, UserDetailSource.KDB), uid);
if (retUser && retUser.uin !== '0') { if (retUser && retUser.uin !== '0') {
return retUser; return retUser;
} }
this.context.logger.logDebug('[NapCat] [Mark] getUserDetailInfo Mode1 Failed.'); this.context.logger.logDebug('[NapCat] [Mark] getUserDetailInfo Mode1 Failed.');
return this.fetchUserDetailInfo(uid, UserDetailSource.KSERVER); retUser = await this.fetchUserDetailInfo(uid, UserDetailSource.KSERVER);
if (retUser && retUser.uin === '0') {
retUser.uin = await this.core.apis.UserApi.getUidByUinV2(uid) ?? '0';
}
return retUser;
} }
async modifySelfProfile(param: ModifyProfileParams) { async modifySelfProfile(param: ModifyProfileParams) {
@@ -156,7 +159,7 @@ export class NTQQUserApi {
if (uid) return uid; if (uid) return uid;
uid = (await this.context.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin); uid = (await this.context.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin);
if (uid) return uid; if (uid) return uid;
const unverifiedUid = (await this.getUserDetailInfoByUinV2(Uin)).detail.uid;//从QQ Native 特殊转换 const unverifiedUid = (await this.getUserDetailInfoByUin(Uin)).detail.uid;//从QQ Native 特殊转换
if (unverifiedUid.indexOf('*') == -1) uid = unverifiedUid; if (unverifiedUid.indexOf('*') == -1) uid = unverifiedUid;
//if (uid) return uid; //if (uid) return uid;
return uid; return uid;
@@ -192,7 +195,7 @@ export class NTQQUserApi {
return await this.context.session.getRecentContactService().getRecentContactList(); return await this.context.session.getRecentContactService().getRecentContactList();
} }
async getUserDetailInfoByUinV2(Uin: string) { async getUserDetailInfoByUin(Uin: string) {
return await this.core.eventWrapper.callNoListenerEvent( return await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getUserDetailInfoByUin', 'NodeIKernelProfileService/getUserDetailInfoByUin',
Uin Uin

View File

@@ -131,20 +131,53 @@ export class NTQQWebApi {
// return await res.json(); // return await res.json();
// } // }
async setGroupNotice(GroupCode: string, Content: string) { async setGroupNotice(
GroupCode: string,
Content: string,
pinned: number = 0,
type: number = 1,
is_show_edit_card: number = 1,
tip_window_type: number = 1,
confirm_required: number = 1,
picId: string = '',
imgWidth: number = 540,
imgHeight: number = 300,
) {
interface SetNoticeRetSuccess {
ec: number;
em: string;
id: number;
ltsm: number;
new_fid: string;
read_only: number;
role: number;
srv_code: number;
}
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com'); const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
let ret: any = undefined;
try { try {
ret = await RequestUtil.HttpGetJson<any>( const settings = JSON.stringify({
`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice${new URLSearchParams({ is_show_edit_card: is_show_edit_card,
tip_window_type: tip_window_type,
confirm_required: confirm_required
});
const externalParam = {
pic: picId,
imgWidth: imgWidth.toString(),
imgHeight: imgHeight.toString(),
};
const ret: SetNoticeRetSuccess = await RequestUtil.HttpGetJson<SetNoticeRetSuccess>(
`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?${new URLSearchParams({
bkn: this.getBknFromCookie(cookieObject), bkn: this.getBknFromCookie(cookieObject),
qid: GroupCode, qid: GroupCode,
text: Content, text: Content,
pinned: '0', pinned: pinned.toString(),
type: '1', type: type.toString(),
settings: '{"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}', settings: settings,
...(picId === '' ? {} : externalParam)
}).toString()}`, }).toString()}`,
'GET', 'POST',
'', '',
{ 'Cookie': this.cookieToString(cookieObject) } { 'Cookie': this.cookieToString(cookieObject) }
); );

View File

@@ -0,0 +1,11 @@
export enum MsfStatusType {
KUNKNOWN,
KDISCONNECTED,
KCONNECTED
}
export enum MsfChangeReasonType {
KUNKNOWN,
KUSERLOGININ,
KUSERLOGINOUT,
KAUTO
}

View File

@@ -0,0 +1,12 @@
export interface FSABRecentContactParams {
anchorPointContact: {
contactId: string;
sortField: string;
pos: number;
};
relativeMoveCount: number;
listType: number;
count: number;
fetchOld: boolean;
}

View File

@@ -370,7 +370,8 @@ export interface ReplyElement {
replayMsgSeq: string; replayMsgSeq: string;
replayMsgId: string; replayMsgId: string;
senderUin: string; senderUin: string;
senderUinStr: string; senderUidStr?: string;
replyMsgTime?: string;
} }
export interface SendReplyElement { export interface SendReplyElement {
@@ -933,3 +934,28 @@ export interface RawMessage {
elements: MessageElement[]; elements: MessageElement[];
} }
export interface QueryMsgsParams {
chatInfo: Peer;
filterMsgType: [];
filterSendersUid: string[];
filterMsgFromTime: string;
filterMsgToTime: string;
pageLimit: number;
isReverseOrder: boolean;
isIncludeCurrent: boolean;
}
export interface TmpChatInfoApi {
errMsg: string;
result: number;
tmpChatInfo?: TmpChatInfo;
}
export interface TmpChatInfo {
chatType: number;
fromNick: string;
groupCode: string;
peerUid: string;
sessionType: number;
sig: string;
}

View File

@@ -153,7 +153,10 @@ interface CommonExt {
labels: any[]; labels: any[];
qqLevel: QQLevel; qqLevel: QQLevel;
} }
export enum BuddyListReqType {
KNOMAL,
KLETTER
}
interface Pic { interface Pic {
picId: string; picId: string;
picTime: number; picTime: number;
@@ -294,7 +297,7 @@ export enum BizKey {
KPHOTOWALL KPHOTOWALL
} }
export interface UserDetailInfoByUinV2 { export interface UserDetailInfoByUin {
result: number, result: number,
errMsg: string, errMsg: string,
detail: { detail: {
@@ -305,62 +308,15 @@ export interface UserDetailInfoByUinV2 {
photoWall: null photoWall: null
} }
} }
export enum UserDetailSource {
KDB,
KSERVER
}
export interface UserDetailInfoByUin { export enum ProfileBizType {
result: number, KALL,
errMsg: string, KBASEEXTEND,
info: { KVAS,
uid: string,//这个没办法用 KQZONE,
qid: string, KOTHER
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
}
} }

View File

@@ -1,42 +1,14 @@
{ {
"3.2.12-27187": { "3.2.12-27597": {
"appid": 537240645,
"qua": "V1_LNX_NQ_3.2.12_27187_GW_B"
},
"3.2.12-27206": {
"appid": 537240645,
"qua": "V1_LNX_NQ_3.2.12_27206_GW_B"
},
"3.2.12-27254": {
"appid": 537240795,
"qua": "V1_LNX_NQ_3.2.12_27254_GW_B"
},
"3.2.12-27556": {
"appid": 537243600, "appid": 537243600,
"qua": "V1_LNX_NQ_3.2.12_27556_GW_B" "qua": "V1_LNX_NQ_3.2.12_27597_GW_B"
},
"9.9.15-27187": {
"appid": 537240610,
"qua": "V1_WIN_NQ_9.9.15_27187_GW_B"
},
"9.9.15-27206": {
"appid": 537240610,
"qua": "V1_WIN_NQ_9.9.15_27206_GW_B"
},
"9.9.15-27254": {
"appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27254_GW_B"
},
"9.9.15-27333": {
"appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27333_GW_B"
},
"9.9.15-27391": {
"appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27333_GW_B"
}, },
"9.9.15-27597": { "9.9.15-27597": {
"appid": 537243441, "appid": 537243441,
"qua": "V1_WIN_NQ_9.9.15_27597_GW_B" "qua": "V1_WIN_NQ_9.9.15_27597_GW_B"
},
"6.9.53-27597": {
"appid": 537243538,
"qua": "V1_MAC_NQ_6.9.53_27597_GW_B"
} }
} }

View File

@@ -0,0 +1,18 @@
syntax = "proto3";
package SysMessage;
message likeDetail {
string txt = 1;
int64 uin = 3;
string nickname = 5;
}
message likeMsg {
int32 times = 1;
int32 time = 2;
likeDetail detail = 3;
}
message profileLikeTip {
likeMsg msg = 14;
}

View File

@@ -8,7 +8,7 @@ interface ServerRkeyData {
} }
export class RkeyManager { export class RkeyManager {
serverUrl: string = ''; serverUrl: string[] = [];
logger: LogWrapper; logger: LogWrapper;
private rkeyData: ServerRkeyData = { private rkeyData: ServerRkeyData = {
group_rkey: '', group_rkey: '',
@@ -16,7 +16,7 @@ export class RkeyManager {
expired_time: 0, expired_time: 0,
}; };
constructor(serverUrl: string, logger: LogWrapper) { constructor(serverUrl: string[], logger: LogWrapper) {
this.logger = logger; this.logger = logger;
this.serverUrl = serverUrl; this.serverUrl = serverUrl;
} }
@@ -40,6 +40,13 @@ export class RkeyManager {
async refreshRkey(): Promise<any> { async refreshRkey(): Promise<any> {
//刷新rkey //刷新rkey
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(this.serverUrl, 'GET'); for (const url of this.serverUrl) {
try {
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET');
} catch (e) {
this.logger.logError(`[Rkey] Get Rkey ${url} Error `, e);
}
}
} }
} }

View File

@@ -24,7 +24,7 @@ import path from 'node:path';
import fs from 'node:fs'; import fs from 'node:fs';
import { getMachineId, hostname, systemName, systemVersion } from '@/common/system'; import { getMachineId, hostname, systemName, systemVersion } from '@/common/system';
import { NTEventWrapper } from '@/common/event'; import { NTEventWrapper } from '@/common/event';
import { DataSource, GroupMember, SelfInfo } from '@/core/entities'; import { DataSource, GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/entities';
import { NapCatConfigLoader } from '@/core/helper/config'; import { NapCatConfigLoader } from '@/core/helper/config';
import os from 'node:os'; import os from 'node:os';
import { NodeIKernelGroupListener, NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners'; import { NodeIKernelGroupListener, NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners';
@@ -42,9 +42,15 @@ export enum NapCatCoreWorkingEnv {
} }
export function loadQQWrapper(QQVersion: string): WrapperNodeApi { export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
let wrapperNodePath = path.resolve(path.dirname(process.execPath), './resources/app/wrapper.node'); let appPath;
if (os.platform() === 'darwin') {
appPath = path.resolve(path.dirname(process.execPath), '../Resources/app');
} else {
appPath = path.resolve(path.dirname(process.execPath), './resources/app');
}
let wrapperNodePath = path.resolve(appPath, 'wrapper.node');
if (!fs.existsSync(wrapperNodePath)) { if (!fs.existsSync(wrapperNodePath)) {
wrapperNodePath = path.join(path.dirname(process.execPath), `resources/app/versions/${QQVersion}/wrapper.node`); wrapperNodePath = path.join(appPath, `versions/${QQVersion}/wrapper.node`);
} }
const nativemodule: any = { exports: {} }; const nativemodule: any = { exports: {} };
process.dlopen(nativemodule, wrapperNodePath); process.dlopen(nativemodule, wrapperNodePath);
@@ -113,6 +119,11 @@ export class NapCatCore {
// Renamed from 'InitDataListener' // Renamed from 'InitDataListener'
async initNapCatCoreListeners() { async initNapCatCoreListeners() {
const msgListener = new NodeIKernelMsgListener(); const msgListener = new NodeIKernelMsgListener();
msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => {
// 下线通知
this.context.logger.logError('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc);
this.selfInfo.online = false;
};
msgListener.onRecvMsg = (msgs) => { msgListener.onRecvMsg = (msgs) => {
msgs.forEach(msg => this.context.logger.logMessage(msg, this.selfInfo)); msgs.forEach(msg => this.context.logger.logMessage(msg, this.selfInfo));
}; };
@@ -130,10 +141,13 @@ export class NapCatCore {
Object.assign(this.selfInfo, profile); Object.assign(this.selfInfo, profile);
} }
}; };
profileListener.onSelfStatusChanged = (/* Info: SelfStatusInfo */) => { profileListener.onSelfStatusChanged = (Info: SelfStatusInfo) => {
// if (Info.status == 20) { if (Info.status == 20) {
// log("账号状态变更为离线") this.selfInfo.online = false;
// } this.context.logger.log("账号状态变更为离线");
} else {
this.selfInfo.online = true;
}
}; };
this.context.session.getProfileService().addKernelProfileListener( this.context.session.getProfileService().addKernelProfileListener(
proxiedListenerOf(profileListener, this.context.logger), proxiedListenerOf(profileListener, this.context.logger),

View File

@@ -0,0 +1,97 @@
import { ChatType } from '@/core';
export interface SearchGroupInfo {
groupCode: string;
ownerUid: string;
groupFlag: number;
groupFlagExt: number;
maxMemberNum: number;
memberNum: number;
groupOption: number;
classExt: number;
groupName: string;
fingerMemo: string;
groupQuestion: string;
certType: number;
shutUpAllTimestamp: number;
shutUpMeTimestamp: number;
groupTypeFlag: number;
privilegeFlag: number;
groupSecLevel: number;
groupFlagExt3: number;
isConfGroup: number;
isModifyConfGroupFace: number;
isModifyConfGroupName: number;
noFigerOpenFlag: number;
noCodeFingerOpenFlag: number;
groupFlagExt4: number;
groupMemo: string;
cmdUinMsgSeq: number;
cmdUinJoinTime: number;
cmdUinUinFlag: number;
cmdUinMsgMask: number;
groupSecLevelInfo: number;
cmdUinPrivilege: number;
cmdUinFlagEx2: number;
appealDeadline: number;
remarkName: string;
isTop: boolean;
richFingerMemo: string;
groupAnswer: string;
joinGroupAuth: string;
isAllowModifyConfGroupName: number;
}
export interface GroupInfo {
groupCode: string;
searchGroupInfo: SearchGroupInfo;
privilege: number;
}
export interface GroupSearchResult {
keyWord: string;
errorCode: number;
groupInfos: GroupInfo[];
penetrate: string;
isEnd: boolean;
nextPos: number;
}
export interface NodeIKernelSearchListener {
onSearchGroupResult(params: GroupSearchResult): void;
onSearchFileKeywordsResult(params: {
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
}[]
}[]
}): void;
}

View File

@@ -1,39 +0,0 @@
import { ChatType } from '@/core';
export interface NodeIKernelSearchListener_Polyfill {
onSearchFileKeywordsResult(params: {
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
}[]
}[]
}): void;
}

View File

@@ -9,7 +9,7 @@ export * from './NodeIKernelProfileListener';
export * from './NodeIKernelTicketListener'; export * from './NodeIKernelTicketListener';
export * from './NodeIKernelStorageCleanListener'; export * from './NodeIKernelStorageCleanListener';
export * from './NodeIKernelFileAssistantListener'; export * from './NodeIKernelFileAssistantListener';
export * from './NodeIKernelSearchListener_Polyfill'; export * from './NodeIKernelSearchListener';
import type { import type {
NodeIKernelBuddyListener, NodeIKernelBuddyListener,
@@ -19,11 +19,11 @@ import type {
NodeIKernelMsgListener, NodeIKernelMsgListener,
NodeIKernelProfileListener, NodeIKernelProfileListener,
NodeIKernelRobotListener, NodeIKernelRobotListener,
NodeIKernelSearchListener_Polyfill,
NodeIKernelSessionListener, NodeIKernelSessionListener,
NodeIKernelStorageCleanListener, NodeIKernelStorageCleanListener,
NodeIKernelTicketListener, NodeIKernelTicketListener,
} from '.'; } from '.';
import { NodeIKernelSearchListener } from './NodeIKernelSearchListener';
export type ListenerNamingMapping = { export type ListenerNamingMapping = {
NodeIKernelSessionListener: NodeIKernelSessionListener; NodeIKernelSessionListener: NodeIKernelSessionListener;
@@ -36,5 +36,5 @@ export type ListenerNamingMapping = {
NodeIKernelTicketListener: NodeIKernelTicketListener; NodeIKernelTicketListener: NodeIKernelTicketListener;
NodeIKernelStorageCleanListener: NodeIKernelStorageCleanListener; NodeIKernelStorageCleanListener: NodeIKernelStorageCleanListener;
NodeIKernelFileAssistantListener: NodeIKernelFileAssistantListener; NodeIKernelFileAssistantListener: NodeIKernelFileAssistantListener;
NodeIKernelSearchListener: NodeIKernelSearchListener_Polyfill; NodeIKernelSearchListener: NodeIKernelSearchListener;
}; };

View File

@@ -1,341 +0,0 @@
// @generated by protobuf-ts 2.9.4
// @generated from protobuf file "EmojiLikeToOthers.proto" (package "SysMessage", syntax proto3)
// tslint:disable
import type {
BinaryReadOptions,
BinaryWriteOptions,
IBinaryReader,
IBinaryWriter,
PartialMessage,
} from '@protobuf-ts/runtime';
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
/**
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper1
*/
export interface EmojiLikeToOthersWrapper1 {
/**
* @generated from protobuf field: SysMessage.EmojiLikeToOthersWrapper2 wrapper = 1;
*/
wrapper?: EmojiLikeToOthersWrapper2;
}
/**
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper2
*/
export interface EmojiLikeToOthersWrapper2 {
/**
* @generated from protobuf field: SysMessage.EmojiLikeToOthersWrapper3 body = 1;
*/
body?: EmojiLikeToOthersWrapper3;
}
/**
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper3
*/
export interface EmojiLikeToOthersWrapper3 {
/**
* @generated from protobuf field: SysMessage.EmojiLikeToOthersMsgSpec msgSpec = 2;
*/
msgSpec?: EmojiLikeToOthersMsgSpec;
/**
* @generated from protobuf field: SysMessage.EmojiLikeToOthersAttributes attributes = 3;
*/
attributes?: EmojiLikeToOthersAttributes;
}
/**
* @generated from protobuf message SysMessage.EmojiLikeToOthersMsgSpec
*/
export interface EmojiLikeToOthersMsgSpec {
/**
* @generated from protobuf field: uint32 msgSeq = 1;
*/
msgSeq: number;
}
/**
* @generated from protobuf message SysMessage.EmojiLikeToOthersAttributes
*/
export interface EmojiLikeToOthersAttributes {
/**
* @generated from protobuf field: string emojiId = 1;
*/
emojiId: string;
/**
* @generated from protobuf field: string senderUid = 4;
*/
senderUid: string;
/**
* @generated from protobuf field: SysMessage.EmojiLikeToOthersAttributes.Operation operation = 5;
*/
operation: EmojiLikeToOthersAttributes_Operation;
}
/**
* @generated from protobuf enum SysMessage.EmojiLikeToOthersAttributes.Operation
*/
export enum EmojiLikeToOthersAttributes_Operation {
/**
* @generated from protobuf enum value: FALLBACK = 0;
*/
FALLBACK = 0,
/**
* @generated from protobuf enum value: LIKE = 1;
*/
LIKE = 1,
/**
* @generated from protobuf enum value: UNLIKE = 2;
*/
UNLIKE = 2
}
// @generated message type with reflection information, may provide speed optimized methods
class EmojiLikeToOthersWrapper1$Type extends MessageType<EmojiLikeToOthersWrapper1> {
constructor() {
super("SysMessage.EmojiLikeToOthersWrapper1", [
{ no: 1, name: "wrapper", kind: "message", T: () => EmojiLikeToOthersWrapper2 }
]);
}
create(value?: PartialMessage<EmojiLikeToOthersWrapper1>): EmojiLikeToOthersWrapper1 {
const message = globalThis.Object.create((this.messagePrototype!));
if (value !== undefined)
reflectionMergePartial<EmojiLikeToOthersWrapper1>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersWrapper1): EmojiLikeToOthersWrapper1 {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* SysMessage.EmojiLikeToOthersWrapper2 wrapper */ 1:
message.wrapper = EmojiLikeToOthersWrapper2.internalBinaryRead(reader, reader.uint32(), options, message.wrapper);
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: EmojiLikeToOthersWrapper1, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* SysMessage.EmojiLikeToOthersWrapper2 wrapper = 1; */
if (message.wrapper)
EmojiLikeToOthersWrapper2.internalBinaryWrite(message.wrapper, writer.tag(1, 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.EmojiLikeToOthersWrapper1
*/
export const EmojiLikeToOthersWrapper1 = new EmojiLikeToOthersWrapper1$Type();
// @generated message type with reflection information, may provide speed optimized methods
class EmojiLikeToOthersWrapper2$Type extends MessageType<EmojiLikeToOthersWrapper2> {
constructor() {
super("SysMessage.EmojiLikeToOthersWrapper2", [
{ no: 1, name: "body", kind: "message", T: () => EmojiLikeToOthersWrapper3 }
]);
}
create(value?: PartialMessage<EmojiLikeToOthersWrapper2>): EmojiLikeToOthersWrapper2 {
const message = globalThis.Object.create((this.messagePrototype!));
if (value !== undefined)
reflectionMergePartial<EmojiLikeToOthersWrapper2>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersWrapper2): EmojiLikeToOthersWrapper2 {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* SysMessage.EmojiLikeToOthersWrapper3 body */ 1:
message.body = EmojiLikeToOthersWrapper3.internalBinaryRead(reader, reader.uint32(), options, message.body);
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: EmojiLikeToOthersWrapper2, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* SysMessage.EmojiLikeToOthersWrapper3 body = 1; */
if (message.body)
EmojiLikeToOthersWrapper3.internalBinaryWrite(message.body, writer.tag(1, 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.EmojiLikeToOthersWrapper2
*/
export const EmojiLikeToOthersWrapper2 = new EmojiLikeToOthersWrapper2$Type();
// @generated message type with reflection information, may provide speed optimized methods
class EmojiLikeToOthersWrapper3$Type extends MessageType<EmojiLikeToOthersWrapper3> {
constructor() {
super("SysMessage.EmojiLikeToOthersWrapper3", [
{ no: 2, name: "msgSpec", kind: "message", T: () => EmojiLikeToOthersMsgSpec },
{ no: 3, name: "attributes", kind: "message", T: () => EmojiLikeToOthersAttributes }
]);
}
create(value?: PartialMessage<EmojiLikeToOthersWrapper3>): EmojiLikeToOthersWrapper3 {
const message = globalThis.Object.create((this.messagePrototype!));
if (value !== undefined)
reflectionMergePartial<EmojiLikeToOthersWrapper3>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersWrapper3): EmojiLikeToOthersWrapper3 {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* SysMessage.EmojiLikeToOthersMsgSpec msgSpec */ 2:
message.msgSpec = EmojiLikeToOthersMsgSpec.internalBinaryRead(reader, reader.uint32(), options, message.msgSpec);
break;
case /* SysMessage.EmojiLikeToOthersAttributes attributes */ 3:
message.attributes = EmojiLikeToOthersAttributes.internalBinaryRead(reader, reader.uint32(), options, message.attributes);
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: EmojiLikeToOthersWrapper3, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* SysMessage.EmojiLikeToOthersMsgSpec msgSpec = 2; */
if (message.msgSpec)
EmojiLikeToOthersMsgSpec.internalBinaryWrite(message.msgSpec, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
/* SysMessage.EmojiLikeToOthersAttributes attributes = 3; */
if (message.attributes)
EmojiLikeToOthersAttributes.internalBinaryWrite(message.attributes, 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.EmojiLikeToOthersWrapper3
*/
export const EmojiLikeToOthersWrapper3 = new EmojiLikeToOthersWrapper3$Type();
// @generated message type with reflection information, may provide speed optimized methods
class EmojiLikeToOthersMsgSpec$Type extends MessageType<EmojiLikeToOthersMsgSpec> {
constructor() {
super("SysMessage.EmojiLikeToOthersMsgSpec", [
{ no: 1, name: "msgSeq", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
]);
}
create(value?: PartialMessage<EmojiLikeToOthersMsgSpec>): EmojiLikeToOthersMsgSpec {
const message = globalThis.Object.create((this.messagePrototype!));
message.msgSeq = 0;
if (value !== undefined)
reflectionMergePartial<EmojiLikeToOthersMsgSpec>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersMsgSpec): EmojiLikeToOthersMsgSpec {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* uint32 msgSeq */ 1:
message.msgSeq = 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: EmojiLikeToOthersMsgSpec, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* uint32 msgSeq = 1; */
if (message.msgSeq !== 0)
writer.tag(1, WireType.Varint).uint32(message.msgSeq);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersMsgSpec
*/
export const EmojiLikeToOthersMsgSpec = new EmojiLikeToOthersMsgSpec$Type();
// @generated message type with reflection information, may provide speed optimized methods
class EmojiLikeToOthersAttributes$Type extends MessageType<EmojiLikeToOthersAttributes> {
constructor() {
super("SysMessage.EmojiLikeToOthersAttributes", [
{ no: 1, name: "emojiId", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 4, name: "senderUid", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 5, name: "operation", kind: "enum", T: () => ["SysMessage.EmojiLikeToOthersAttributes.Operation", EmojiLikeToOthersAttributes_Operation] }
]);
}
create(value?: PartialMessage<EmojiLikeToOthersAttributes>): EmojiLikeToOthersAttributes {
const message = globalThis.Object.create((this.messagePrototype!));
message.emojiId = "";
message.senderUid = "";
message.operation = 0;
if (value !== undefined)
reflectionMergePartial<EmojiLikeToOthersAttributes>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersAttributes): EmojiLikeToOthersAttributes {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string emojiId */ 1:
message.emojiId = reader.string();
break;
case /* string senderUid */ 4:
message.senderUid = reader.string();
break;
case /* SysMessage.EmojiLikeToOthersAttributes.Operation operation */ 5:
message.operation = reader.int32();
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: EmojiLikeToOthersAttributes, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string emojiId = 1; */
if (message.emojiId !== "")
writer.tag(1, WireType.LengthDelimited).string(message.emojiId);
/* string senderUid = 4; */
if (message.senderUid !== "")
writer.tag(4, WireType.LengthDelimited).string(message.senderUid);
/* SysMessage.EmojiLikeToOthersAttributes.Operation operation = 5; */
if (message.operation !== 0)
writer.tag(5, WireType.Varint).int32(message.operation);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersAttributes
*/
export const EmojiLikeToOthersAttributes = new EmojiLikeToOthersAttributes$Type();

View File

@@ -1,104 +0,0 @@
// @generated by protobuf-ts 2.9.4
// @generated from protobuf file "GreyTipWrapper.proto" (package "SysMessage", syntax proto3)
// tslint:disable
import type {
BinaryReadOptions,
BinaryWriteOptions,
IBinaryReader,
IBinaryWriter,
PartialMessage,
} from '@protobuf-ts/runtime';
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
/**
* @generated from protobuf message SysMessage.GreyTipWrapper
*/
export interface GreyTipWrapper {
/**
* @generated from protobuf field: uint32 subTypeId = 1;
*/
subTypeId: number;
/**
* @generated from protobuf field: uint32 groupCode = 4;
*/
groupCode: number;
/**
* @generated from protobuf field: uint32 subTypeIdMinusOne = 13;
*/
subTypeIdMinusOne: number;
/**
* @generated from protobuf field: bytes rest = 44;
*/
rest: Uint8Array;
}
// @generated message type with reflection information, may provide speed optimized methods
class GreyTipWrapper$Type extends MessageType<GreyTipWrapper> {
constructor() {
super("SysMessage.GreyTipWrapper", [
{ no: 1, name: "subTypeId", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 4, name: "groupCode", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 13, name: "subTypeIdMinusOne", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 44, name: "rest", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
]);
}
create(value?: PartialMessage<GreyTipWrapper>): GreyTipWrapper {
const message = globalThis.Object.create((this.messagePrototype!));
message.subTypeId = 0;
message.groupCode = 0;
message.subTypeIdMinusOne = 0;
message.rest = new Uint8Array(0);
if (value !== undefined)
reflectionMergePartial<GreyTipWrapper>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GreyTipWrapper): GreyTipWrapper {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* uint32 subTypeId */ 1:
message.subTypeId = reader.uint32();
break;
case /* uint32 groupCode */ 4:
message.groupCode = reader.uint32();
break;
case /* uint32 subTypeIdMinusOne */ 13:
message.subTypeIdMinusOne = reader.uint32();
break;
case /* bytes rest */ 44:
message.rest = reader.bytes();
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: GreyTipWrapper, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* uint32 subTypeId = 1; */
if (message.subTypeId !== 0)
writer.tag(1, WireType.Varint).uint32(message.subTypeId);
/* uint32 groupCode = 4; */
if (message.groupCode !== 0)
writer.tag(4, WireType.Varint).uint32(message.groupCode);
/* uint32 subTypeIdMinusOne = 13; */
if (message.subTypeIdMinusOne !== 0)
writer.tag(13, WireType.Varint).uint32(message.subTypeIdMinusOne);
/* bytes rest = 44; */
if (message.rest.length)
writer.tag(44, WireType.LengthDelimited).bytes(message.rest);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message SysMessage.GreyTipWrapper
*/
export const GreyTipWrapper = new GreyTipWrapper$Type();

View File

@@ -0,0 +1,83 @@
import * as pb from 'protobufjs';
// Proto: from src/core/proto/ProfileLike.proto
// Author: Mlikiowa
export interface LikeDetailType {
txt: string;
uin: pb.Long;
nickname: string;
}
export interface LikeMsgType {
times: number;
time: number;
detail: LikeDetailType;
}
export interface ProfileLikeTipType {
msg: LikeMsgType;
}
export interface SysMessageHeaderType {
id: string;
timestamp: number;
sender: string;
}
export interface SysMessageMsgSpecType {
msgType: number;
subType: number;
subSubType: number;
msgSeq: number;
time: number;
msgId: pb.Long;
other: number;
}
export interface SysMessageBodyWrapperType {
wrappedBody: Uint8Array;
}
export interface SysMessageType {
header: SysMessageHeaderType[];
msgSpec: SysMessageMsgSpecType[];
bodyWrapper: SysMessageBodyWrapperType;
}
export const SysMessageHeader = new pb.Type("SysMessageHeader")
.add(new pb.Field("PeerNumber", 1, "uint32"))
.add(new pb.Field("PeerString", 2, "string"))
.add(new pb.Field("Uin", 5, "uint32"))
.add(new pb.Field("Uid", 6, "string", "optional"));
export const SysMessageMsgSpec = new pb.Type("SysMessageMsgSpec")
.add(new pb.Field("msgType", 1, "uint32"))
.add(new pb.Field("subType", 2, "uint32"))
.add(new pb.Field("subSubType", 3, "uint32"))
.add(new pb.Field("msgSeq", 5, "uint32"))
.add(new pb.Field("time", 6, "uint32"))
.add(new pb.Field("msgId", 12, "uint64"))
.add(new pb.Field("other", 13, "uint32"));
export const SysMessageBodyWrapper = new pb.Type("SysMessageBodyWrapper")
.add(new pb.Field("wrappedBody", 2, "bytes"));
export const SysMessage = new pb.Type("SysMessage")
.add(SysMessageHeader)
.add(SysMessageMsgSpec)
.add(SysMessageBodyWrapper)
.add(new pb.Field("header", 1, "SysMessageHeader", "repeated"))
.add(new pb.Field("msgSpec", 2, "SysMessageMsgSpec", "repeated"))
.add(new pb.Field("bodyWrapper", 3, "SysMessageBodyWrapper"));
export const likeDetail = new pb.Type("likeDetail")
.add(new pb.Field("txt", 1, "string"))
.add(new pb.Field("uin", 3, "int64"))
.add(new pb.Field("nickname", 5, "string"));
export const likeMsg = new pb.Type("likeMsg")
.add(likeDetail)
.add(new pb.Field("times", 1, "int32"))
.add(new pb.Field("time", 2, "int32"))
.add(new pb.Field("detail", 3, "likeDetail"));
export const profileLikeTip = new pb.Type("profileLikeTip")
.add(likeMsg)
.add(new pb.Field("msg", 14, "likeMsg"));

View File

@@ -1,435 +0,0 @@
// @generated by protobuf-ts 2.9.4
// @generated from protobuf file "SysMessage.proto" (package "SysMessage", syntax proto3)
// tslint:disable
import type {
BinaryReadOptions,
BinaryWriteOptions,
IBinaryReader,
IBinaryWriter,
PartialMessage,
} from '@protobuf-ts/runtime';
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
/**
* @generated from protobuf message SysMessage.SysMessage
*/
export interface SysMessage {
/**
* @generated from protobuf field: repeated SysMessage.SysMessageHeader header = 1;
*/
header: SysMessageHeader[];
/**
* @generated from protobuf field: repeated SysMessage.SysMessageMsgSpec msgSpec = 2;
*/
msgSpec: SysMessageMsgSpec[];
/**
* @generated from protobuf field: SysMessage.SysMessageBodyWrapper bodyWrapper = 3;
*/
bodyWrapper?: SysMessageBodyWrapper;
}
/**
* @generated from protobuf message SysMessage.SysMessageHeader
*/
export interface SysMessageHeader {
/**
* @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.SysMessageMsgSpec
*/
export interface SysMessageMsgSpec {
/**
* @generated from protobuf field: uint32 msgType = 1;
*/
msgType: number;
/**
* @generated from protobuf field: uint32 subType = 2;
*/
subType: number;
/**
* @generated from protobuf field: uint32 subSubType = 3;
*/
subSubType: number;
/**
* @generated from protobuf field: uint32 msgSeq = 5;
*/
msgSeq: number;
/**
* @generated from protobuf field: uint32 time = 6;
*/
time: number;
/**
* @generated from protobuf field: uint64 msgId = 12;
*/
msgId: bigint;
/**
* @generated from protobuf field: uint32 other = 13;
*/
other: number;
}
/**
* @generated from protobuf message SysMessage.SysMessageBodyWrapper
*/
export interface SysMessageBodyWrapper {
/**
* @generated from protobuf field: bytes wrappedBody = 2;
*/
wrappedBody: Uint8Array; // Find the first [08], or ignore the first 7 bytes?
// And it becomes another ProtoBuf message.
}
/**
* @generated from protobuf message SysMessage.KeyValuePair
*/
export interface KeyValuePair {
/**
* @generated from protobuf field: string key = 1;
*/
key: string;
/**
* @generated from protobuf field: string value = 2;
*/
value: string;
}
// @generated message type with reflection information, may provide speed optimized methods
class SysMessage$Type extends MessageType<SysMessage> {
constructor() {
super("SysMessage.SysMessage", [
{ no: 1, name: "header", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => SysMessageHeader },
{ no: 2, name: "msgSpec", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => SysMessageMsgSpec },
{ no: 3, name: "bodyWrapper", kind: "message", T: () => SysMessageBodyWrapper }
]);
}
create(value?: PartialMessage<SysMessage>): SysMessage {
const message = globalThis.Object.create((this.messagePrototype!));
message.header = [];
message.msgSpec = [];
if (value !== undefined)
reflectionMergePartial<SysMessage>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessage): SysMessage {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* repeated SysMessage.SysMessageHeader header */ 1:
message.header.push(SysMessageHeader.internalBinaryRead(reader, reader.uint32(), options));
break;
case /* repeated SysMessage.SysMessageMsgSpec msgSpec */ 2:
message.msgSpec.push(SysMessageMsgSpec.internalBinaryRead(reader, reader.uint32(), options));
break;
case /* SysMessage.SysMessageBodyWrapper bodyWrapper */ 3:
message.bodyWrapper = SysMessageBodyWrapper.internalBinaryRead(reader, reader.uint32(), options, message.bodyWrapper);
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: SysMessage, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* repeated SysMessage.SysMessageHeader header = 1; */
for (let i = 0; i < message.header.length; i++)
SysMessageHeader.internalBinaryWrite(message.header[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join();
/* repeated SysMessage.SysMessageMsgSpec msgSpec = 2; */
for (let i = 0; i < message.msgSpec.length; i++)
SysMessageMsgSpec.internalBinaryWrite(message.msgSpec[i], writer.tag(2, WireType.LengthDelimited).fork(), options).join();
/* SysMessage.SysMessageBodyWrapper bodyWrapper = 3; */
if (message.bodyWrapper)
SysMessageBodyWrapper.internalBinaryWrite(message.bodyWrapper, 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.SysMessage
*/
export const SysMessage = new SysMessage$Type();
// @generated message type with reflection information, may provide speed optimized methods
class SysMessageHeader$Type extends MessageType<SysMessageHeader> {
constructor() {
super("SysMessage.SysMessageHeader", [
{ 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<SysMessageHeader>): SysMessageHeader {
const message = globalThis.Object.create((this.messagePrototype!));
message.peerNumber = 0;
message.peerString = "";
message.uin = 0;
if (value !== undefined)
reflectionMergePartial<SysMessageHeader>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessageHeader): SysMessageHeader {
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: SysMessageHeader, 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.SysMessageHeader
*/
export const SysMessageHeader = new SysMessageHeader$Type();
// @generated message type with reflection information, may provide speed optimized methods
class SysMessageMsgSpec$Type extends MessageType<SysMessageMsgSpec> {
constructor() {
super("SysMessage.SysMessageMsgSpec", [
{ no: 1, name: "msgType", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 2, name: "subType", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 3, name: "subSubType", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 5, name: "msgSeq", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 6, name: "time", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 12, name: "msgId", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
{ no: 13, name: "other", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
]);
}
create(value?: PartialMessage<SysMessageMsgSpec>): SysMessageMsgSpec {
const message = globalThis.Object.create((this.messagePrototype!));
message.msgType = 0;
message.subType = 0;
message.subSubType = 0;
message.msgSeq = 0;
message.time = 0;
message.msgId = 0n;
message.other = 0;
if (value !== undefined)
reflectionMergePartial<SysMessageMsgSpec>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessageMsgSpec): SysMessageMsgSpec {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* uint32 msgType */ 1:
message.msgType = reader.uint32();
break;
case /* uint32 subType */ 2:
message.subType = reader.uint32();
break;
case /* uint32 subSubType */ 3:
message.subSubType = reader.uint32();
break;
case /* uint32 msgSeq */ 5:
message.msgSeq = reader.uint32();
break;
case /* uint32 time */ 6:
message.time = reader.uint32();
break;
case /* uint64 msgId */ 12:
message.msgId = reader.uint64().toBigInt();
break;
case /* uint32 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: SysMessageMsgSpec, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* uint32 msgType = 1; */
if (message.msgType !== 0)
writer.tag(1, WireType.Varint).uint32(message.msgType);
/* uint32 subType = 2; */
if (message.subType !== 0)
writer.tag(2, WireType.Varint).uint32(message.subType);
/* uint32 subSubType = 3; */
if (message.subSubType !== 0)
writer.tag(3, WireType.Varint).uint32(message.subSubType);
/* uint32 msgSeq = 5; */
if (message.msgSeq !== 0)
writer.tag(5, WireType.Varint).uint32(message.msgSeq);
/* uint32 time = 6; */
if (message.time !== 0)
writer.tag(6, WireType.Varint).uint32(message.time);
/* uint64 msgId = 12; */
if (message.msgId !== 0n)
writer.tag(12, WireType.Varint).uint64(message.msgId);
/* uint32 other = 13; */
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.SysMessageMsgSpec
*/
export const SysMessageMsgSpec = new SysMessageMsgSpec$Type();
// @generated message type with reflection information, may provide speed optimized methods
class SysMessageBodyWrapper$Type extends MessageType<SysMessageBodyWrapper> {
constructor() {
super("SysMessage.SysMessageBodyWrapper", [
{ no: 2, name: "wrappedBody", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
]);
}
create(value?: PartialMessage<SysMessageBodyWrapper>): SysMessageBodyWrapper {
const message = globalThis.Object.create((this.messagePrototype!));
message.wrappedBody = new Uint8Array(0);
if (value !== undefined)
reflectionMergePartial<SysMessageBodyWrapper>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessageBodyWrapper): SysMessageBodyWrapper {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* bytes wrappedBody */ 2:
message.wrappedBody = reader.bytes();
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: SysMessageBodyWrapper, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* bytes wrappedBody = 2; */
if (message.wrappedBody.length)
writer.tag(2, WireType.LengthDelimited).bytes(message.wrappedBody);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message SysMessage.SysMessageBodyWrapper
*/
export const SysMessageBodyWrapper = new SysMessageBodyWrapper$Type();
// @generated message type with reflection information, may provide speed optimized methods
class KeyValuePair$Type extends MessageType<KeyValuePair> {
constructor() {
super("SysMessage.KeyValuePair", [
{ no: 1, name: "key", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "value", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
]);
}
create(value?: PartialMessage<KeyValuePair>): KeyValuePair {
const message = globalThis.Object.create((this.messagePrototype!));
message.key = "";
message.value = "";
if (value !== undefined)
reflectionMergePartial<KeyValuePair>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: KeyValuePair): KeyValuePair {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string key */ 1:
message.key = reader.string();
break;
case /* string value */ 2:
message.value = 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: KeyValuePair, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string key = 1; */
if (message.key !== "")
writer.tag(1, WireType.LengthDelimited).string(message.key);
/* string value = 2; */
if (message.value !== "")
writer.tag(2, WireType.LengthDelimited).string(message.value);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message SysMessage.KeyValuePair
*/
export const KeyValuePair = new KeyValuePair$Type();

View File

@@ -1,4 +1,5 @@
export interface NodeIKernelAlbumService { export interface NodeIKernelAlbumService {
setAlbumServiceInfo(...args: any[]): unknown;// needs 3 arguments setAlbumServiceInfo(...args: any[]): unknown;// needs 3 arguments
getMainPage(...args: any[]): unknown;// needs 2 arguments getMainPage(...args: any[]): unknown;// needs 2 arguments

View File

@@ -1,7 +1,7 @@
export interface NodeIKernelAvatarService { export interface NodeIKernelAvatarService {
addAvatarListener(arg: unknown): unknown; addAvatarListener(listener: unknown): void;
removeAvatarListener(arg: unknown): unknown; removeAvatarListener(listenerId: number): void;
getAvatarPath(arg1: unknown, arg2: unknown): unknown; getAvatarPath(arg1: unknown, arg2: unknown): unknown;

View File

@@ -1,13 +1,8 @@
import { GeneralCallResult } from '@/core/services/common'; import { GeneralCallResult } from '@/core/services/common';
import { NodeIKernelBuddyListener } from '@/core/listeners'; import { NodeIKernelBuddyListener } from '@/core/listeners';
import { BuddyListReqType } from '../entities/user';
export enum BuddyListReqType {
KNOMAL,
KLETTER
}
export interface NodeIKernelBuddyService { export interface NodeIKernelBuddyService {
// 26702 以上
getBuddyListV2(callFrom: string, reqType: BuddyListReqType): Promise<GeneralCallResult & { getBuddyListV2(callFrom: string, reqType: BuddyListReqType): Promise<GeneralCallResult & {
data: Array<{ data: Array<{
categoryId: number, categoryId: number,
@@ -19,8 +14,7 @@ export interface NodeIKernelBuddyService {
}> }>
}>; }>;
//26702 以上 getBuddyListFromCache(reqType: BuddyListReqType): Promise<Array<
getBuddyListFromCache(callFrom: string): Promise<Array<
{ {
categoryId: number,//9999应该跳过 那是兜底数据吧 categoryId: number,//9999应该跳过 那是兜底数据吧
categorySortId: number,//排序方式 categorySortId: number,//排序方式
@@ -30,18 +24,13 @@ export interface NodeIKernelBuddyService {
buddyUids: Array<string>//Uids buddyUids: Array<string>//Uids
}>>; }>>;
// 以下为原生方法
addKernelBuddyListener(listener: NodeIKernelBuddyListener): number; addKernelBuddyListener(listener: NodeIKernelBuddyListener): number;
getAllBuddyCount(): number; getAllBuddyCount(): number;
removeKernelBuddyListener(listener: unknown): void; removeKernelBuddyListener(listenerId: number): void;
/** //getBuddyList(nocache: boolean): Promise<GeneralCallResult>;
* @deprecated
* @param nocache 使用缓存
*/
getBuddyList(nocache: boolean): Promise<GeneralCallResult>;
getBuddyNick(uid: number): string; getBuddyNick(uid: number): string;

View File

@@ -1,9 +1,9 @@
import { GeneralCallResult } from './common'; import { GeneralCallResult } from './common';
export interface NodeIKernelCollectionService { export interface NodeIKernelCollectionService {
addKernelCollectionListener(...args: any[]): unknown;//needs 1 arguments addKernelCollectionListener(...args: any[]): void;//needs 1 arguments
removeKernelCollectionListener(...args: any[]): unknown;//needs 1 arguments removeKernelCollectionListener(listenerId: number): void;
getCollectionItemList(param: { getCollectionItemList(param: {
category: number, category: number,
@@ -53,7 +53,7 @@ export interface NodeIKernelCollectionService {
bottomTimeStamp: string bottomTimeStamp: string
} }
} }
>;//needs 1 arguments >;
getCollectionContent(...args: any[]): unknown;//needs 5 arguments getCollectionContent(...args: any[]): unknown;//needs 5 arguments

View File

@@ -1,7 +1,9 @@
export interface NodeIKernelDbToolsService { export interface NodeIKernelDbToolsService {
depositDatabase(...args: unknown[]): unknown; depositDatabase(...args: unknown[]): unknown;
backupDatabase(...args: unknown[]): unknown; backupDatabase(...args: unknown[]): unknown;
retrieveDatabase(...args: unknown[]): unknown; retrieveDatabase(...args: unknown[]): unknown;
} }

View File

@@ -1,3 +1,2 @@
export interface NodeIKernelECDHService { export interface NodeIKernelECDHService {
} }

View File

@@ -11,8 +11,6 @@ import {
} from '@/core/entities'; } from '@/core/entities';
import { GeneralCallResult } from '@/core/services/common'; import { GeneralCallResult } from '@/core/services/common';
//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底
export interface NodeIKernelGroupService { export interface NodeIKernelGroupService {
getGroupExt0xEF0Info(enableGroupCodes: string[], bannedGroupCodes: string[], filter: GroupExt0xEF0InfoFilter, forceFetch: boolean): getGroupExt0xEF0Info(enableGroupCodes: string[], bannedGroupCodes: string[], filter: GroupExt0xEF0InfoFilter, forceFetch: boolean):
Promise<GeneralCallResult & { result: { groupExtInfos: Map<string, any> } }>; Promise<GeneralCallResult & { result: { groupExtInfos: Map<string, any> } }>;
@@ -82,11 +80,11 @@ export interface NodeIKernelGroupService {
}): Promise<unknown>; }): Promise<unknown>;
isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>; isEssenceMsg(req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>; queryCachedEssenceMsg(req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
fetchGroupEssenceList(Req: { fetchGroupEssenceList(req: {
groupCode: string, groupCode: string,
pageStart: number, pageStart: number,
pageLimit: number pageLimit: number
@@ -110,13 +108,12 @@ export interface NodeIKernelGroupService {
addKernelGroupListener(listener: NodeIKernelGroupListener): number; addKernelGroupListener(listener: NodeIKernelGroupListener): number;
removeKernelGroupListener(listenerId: unknown): void; removeKernelGroupListener(listenerId: number): void;
createMemberListScene(groupCode: string, scene: string): string; createMemberListScene(groupCode: string, scene: string): string;
destroyMemberListScene(SceneId: string): void; destroyMemberListScene(SceneId: string): void;
//About Arg (a) name: lastId 根据手Q来看为object {index:?(number),uid:string}
getNextMemberList(sceneId: string, a: undefined, num: number): Promise<{ getNextMemberList(sceneId: string, a: undefined, num: number): Promise<{
errCode: number, errMsg: string, errCode: number, errMsg: string,
result: { ids: string[], infos: Map<string, GroupMember>, finish: boolean, hasRobot: boolean } result: { ids: string[], infos: Map<string, GroupMember>, finish: boolean, hasRobot: boolean }
@@ -247,14 +244,12 @@ export interface NodeIKernelGroupService {
modifyGroupExtInfo(groupCode: string, arg: unknown): void; modifyGroupExtInfo(groupCode: string, arg: unknown): void;
//需要提前判断是否存在 高版本新增
addGroupEssence(param: { addGroupEssence(param: {
groupCode: string groupCode: string
msgRandom: number, msgRandom: number,
msgSeq: number msgSeq: number
}): Promise<unknown>; }): Promise<unknown>;
//需要提前判断是否存在 高版本新增
removeGroupEssence(param: { removeGroupEssence(param: {
groupCode: string groupCode: string
msgRandom: number, msgRandom: number,

View File

@@ -59,6 +59,7 @@ export interface QuickLoginResult {
} }
export interface NodeIKernelLoginService { export interface NodeIKernelLoginService {
connect(): boolean;
// eslint-disable-next-line @typescript-eslint/no-misused-new // eslint-disable-next-line @typescript-eslint/no-misused-new
new(): NodeIKernelLoginService; new(): NodeIKernelLoginService;

View File

@@ -1,7 +1,7 @@
export interface NodeIKernelMsgBackupService { export interface NodeIKernelMsgBackupService {
addKernelMsgBackupListener(...args: any[]): unknown;// needs 1 arguments addKernelMsgBackupListener(listener: unknown): number;
removeKernelMsgBackupListener(...args: any[]): unknown;// needs 1 arguments removeKernelMsgBackupListener(listenerId: number): void;
getMsgBackupLocation(...args: any[]): unknown;// needs 0 arguments getMsgBackupLocation(...args: any[]): unknown;// needs 0 arguments

View File

@@ -1,32 +1,7 @@
import { ElementType, MessageElement, Peer, RawMessage, SendMessageElement } from '@/core/entities'; import { ElementType, MessageElement, Peer, RawMessage, SendMessageElement } from '@/core/entities';
import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener'; import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener';
import { GeneralCallResult } from '@/core/services/common'; import { GeneralCallResult } from '@/core/services/common';
import { QueryMsgsParams, TmpChatInfoApi } from '../entities/msg';
export interface QueryMsgsParams {
chatInfo: Peer,
filterMsgType: [],
filterSendersUid: string[],
filterMsgFromTime: string,
filterMsgToTime: string,
pageLimit: number,
isReverseOrder: boolean,
isIncludeCurrent: boolean
}
export interface TmpChatInfoApi {
errMsg: string;
result: number;
tmpChatInfo?: TmpChatInfo;
}
export interface TmpChatInfo {
chatType: number;
fromNick: string;
groupCode: string;
peerUid: string;
sessionType: number;
sig: string;
}
export interface NodeIKernelMsgService { export interface NodeIKernelMsgService {
@@ -76,18 +51,12 @@ export interface NodeIKernelMsgService {
downloadOnlineStatusCommonByUrl(arg0: string, arg1: string): unknown; downloadOnlineStatusCommonByUrl(arg0: string, arg1: string): unknown;
// this.tokenType = i2;
// this.apnsToken = bArr;
// this.voipToken = bArr2;
// this.profileId = str;
setToken(arg: unknown): unknown; setToken(arg: unknown): unknown;
switchForeGround(): unknown; switchForeGround(): unknown;
switchBackGround(arg: unknown): unknown; switchBackGround(arg: unknown): unknown;
//hex
setTokenForMqq(token: string): unknown; setTokenForMqq(token: string): unknown;
switchForeGroundForMqq(...args: unknown[]): unknown; switchForeGroundForMqq(...args: unknown[]): unknown;
@@ -124,7 +93,6 @@ export interface NodeIKernelMsgService {
forwardFile(...args: unknown[]): unknown; forwardFile(...args: unknown[]): unknown;
//Array<Msg>, Peer from, Peer to
multiForwardMsg(...args: unknown[]): unknown; multiForwardMsg(...args: unknown[]): unknown;
multiForwardMsgWithComment(...args: unknown[]): unknown; multiForwardMsgWithComment(...args: unknown[]): unknown;
@@ -185,11 +153,6 @@ export interface NodeIKernelMsgService {
msgList: RawMessage[] msgList: RawMessage[]
}>; }>;
// this.$peer = contact;
// this.$msgTime = j2;
// this.$clientSeq = j3;
// this.$cnt = i2;
getMsgsWithMsgTimeAndClientSeqForC2C(...args: unknown[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>; getMsgsWithMsgTimeAndClientSeqForC2C(...args: unknown[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
getMsgsWithStatus(params: { getMsgsWithStatus(params: {
@@ -226,7 +189,6 @@ export interface NodeIKernelMsgService {
getSourceOfReplyMsgByClientSeqAndTime(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: { getMsgsByTypeFilter(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilter: {
type: number, type: number,
subtype: Array<number> subtype: Array<number>
@@ -241,49 +203,15 @@ export interface NodeIKernelMsgService {
queryMsgsWithFilter(...args: unknown[]): unknown; queryMsgsWithFilter(...args: unknown[]): unknown;
/** //queryMsgsWithFilterVer2(MsgId: string, MsgTime: string, param: QueryMsgsParams): Promise<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<unknown>;
// 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<GeneralCallResult & { queryMsgsWithFilterEx(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): Promise<GeneralCallResult & {
msgList: RawMessage[] msgList: RawMessage[]
}>; }>;
//queryMsgsWithFilterEx(this.$msgId, this.$msgTime, this.$msgSeq, this.$param) queryFileMsgsDesktop(msgId: string, msgTime: string, msgSeq: string, param: QueryMsgsParams): Promise<GeneralCallResult & {
queryFileMsgsDesktop(...args: unknown[]): unknown; msgList: RawMessage[]
}>;
setMsgRichInfoFlag(...args: unknown[]): unknown; setMsgRichInfoFlag(...args: unknown[]): unknown;
@@ -390,17 +318,11 @@ export interface NodeIKernelMsgService {
getFileThumbSavePath(...args: unknown[]): unknown; getFileThumbSavePath(...args: unknown[]): unknown;
//猜测居多 translatePtt2Text(msgId: string, peer: Peer, msgElement: unknown): unknown;
translatePtt2Text(MsgId: string, Peer: Peer, MsgElement: unknown): unknown;
setPttPlayedState(...args: unknown[]): unknown; setPttPlayedState(...args: unknown[]): unknown;
// NodeIQQNTWrapperSession fetchFavEmojiList [ //uk1 uk2 true
// "",
// 48,
// true,
// true
// ]
fetchFavEmojiList(str: string, num: number, uk1: boolean, uk2: boolean): Promise<GeneralCallResult & { fetchFavEmojiList(str: string, num: number, uk1: boolean, uk2: boolean): Promise<GeneralCallResult & {
emojiInfoList: Array<{ emojiInfoList: Array<{
uin: string, uin: string,
@@ -496,7 +418,7 @@ export interface NodeIKernelMsgService {
getFirstUnreadMsgSeq(args: { getFirstUnreadMsgSeq(args: {
peerUid: string peerUid: string
guildId: string guildId: string
}): unknown; }): Promise<unknown>;
getFirstUnreadCommonMsg(...args: unknown[]): unknown; getFirstUnreadCommonMsg(...args: unknown[]): unknown;
@@ -590,7 +512,7 @@ export interface NodeIKernelMsgService {
getFirstUnreadAtMsg(peer: Peer): unknown; getFirstUnreadAtMsg(peer: Peer): unknown;
clearMsgRecords(...args: unknown[]): unknown;//设置已读后调用我觉得比较好 清理记录 现在别了 clearMsgRecords(...args: unknown[]): unknown;
IsExistOldDb(...args: unknown[]): unknown; IsExistOldDb(...args: unknown[]): unknown;
@@ -626,25 +548,10 @@ export interface NodeIKernelMsgService {
enterOrExitAio(...args: unknown[]): unknown; enterOrExitAio(...args: unknown[]): unknown;
// this.peerUid = ""; prepareTempChat(args: unknown): unknown;
// 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<unknown>; sendSsoCmdReqByContend(cmd: string, param: string): Promise<unknown>;
//chattype,uid->Promise<any>
getTempChatInfo(ChatType: number, Uid: string): Promise<TmpChatInfoApi>; getTempChatInfo(ChatType: number, Uid: string): Promise<TmpChatInfoApi>;
setContactLocalTop(...args: unknown[]): unknown; setContactLocalTop(...args: unknown[]): unknown;
@@ -708,7 +615,6 @@ export interface NodeIKernelMsgService {
dataMigrationStopOperation(...args: unknown[]): unknown; dataMigrationStopOperation(...args: unknown[]): unknown;
//新的希望
dataMigrationImportMsgPbRecord(DataMigrationMsgInfo: Array<{ dataMigrationImportMsgPbRecord(DataMigrationMsgInfo: Array<{
extensionData: string//"Hex" extensionData: string//"Hex"
extraData: string //"" extraData: string //""
@@ -760,6 +666,6 @@ export interface NodeIKernelMsgService {
getGuildMsgAbFlag(...args: unknown[]): unknown; getGuildMsgAbFlag(...args: unknown[]): unknown;
getGroupMsgStorageTime(): unknown;//这是嘛啊 getGroupMsgStorageTime(): unknown;
} }

View File

@@ -1,6 +1,5 @@
import { GeneralCallResult } from './common'; import { GeneralCallResult } from './common';
//没扒干净 因为用不着
export interface NodeIKernelNodeMiscService { export interface NodeIKernelNodeMiscService {
getMiniAppPath(): unknown; getMiniAppPath(): unknown;
@@ -11,7 +10,4 @@ export interface NodeIKernelNodeMiscService {
SendMiniAppMsg(arg1: string, arg2: string, arg3: string): unknown; SendMiniAppMsg(arg1: string, arg2: string, arg3: string): unknown;
startNewMiniApp(appfile: string, params: string): unknown; startNewMiniApp(appfile: string, params: string): unknown;
// 我的计划是转发给一个新程序避免吃掉Electron_AS_Node的环境 然后重写启动MiniApp 挂载相应JS脚本 这样有个问题
// 需要自己转发ipc参数 然后必须处在gui环境 且完成校验破解 才能实现发包 有点抽象了
} }

View File

@@ -1,8 +1,8 @@
export interface NodeIKernelOnlineStatusService { export interface NodeIKernelOnlineStatusService {
addKernelOnlineStatusListener(listener: unknown): void; addKernelOnlineStatusListener(listener: unknown): number;
removeKernelOnlineStatusListener(listenerId: unknown): void; removeKernelOnlineStatusListener(listenerId: number): void;
getShouldShowAIOStatusAnimation(arg: unknown): unknown; getShouldShowAIOStatusAnimation(arg: unknown): unknown;

View File

@@ -1,17 +1,17 @@
import { BuddyProfileLikeReq, GeneralCallResult } from '@/core'; import { BuddyProfileLikeReq, GeneralCallResult } from '@/core';
export interface NodeIKernelProfileLikeService { export interface NodeIKernelProfileLikeService {
addKernelProfileLikeListener(listener: NodeIKernelProfileLikeService): void; addKernelProfileLikeListener(listener: unknown): number;
removeKernelProfileLikeListener(listener: unknown): void; removeKernelProfileLikeListener(listenerId: unknown): void;
setBuddyProfileLike(...args: unknown[]): { result: number, errMsg: string, succCounts: number }; setBuddyProfileLike(...args: unknown[]): { result: number, errMsg: string, succCounts: number };
getBuddyProfileLike(req: BuddyProfileLikeReq): Promise<GeneralCallResult & { getBuddyProfileLike(req: BuddyProfileLikeReq): Promise<GeneralCallResult & {
'info': { info: {
'userLikeInfos': Array<any>, userLikeInfos: Array<any>,
'friendMaxVotes': number, friendMaxVotes: number,
'start': number start: number
} }
}>; }>;

View File

@@ -1,38 +1,21 @@
import { AnyCnameRecord } from 'node:dns'; import { AnyCnameRecord } from 'node:dns';
import { BizKey, ModifyProfileParams, NodeIKernelProfileListener, SimpleInfo, UserDetailInfoByUinV2 } from '@/core'; import { BizKey, ModifyProfileParams, NodeIKernelProfileListener, ProfileBizType, SimpleInfo, UserDetailInfoByUin, UserDetailSource } from '@/core';
import { GeneralCallResult } from '@/core/services/common'; import { GeneralCallResult } from '@/core/services/common';
export enum UserDetailSource {
KDB,
KSERVER
}
export enum ProfileBizType {
KALL,
KBASEEXTEND,
KVAS,
KQZONE,
KOTHER
}
export interface NodeIKernelProfileService { export interface NodeIKernelProfileService {
getOtherFlag(callfrom: string, uids: string[]): Promise<Map<string, any>>;
getUidByUin(callfrom: string, uin: Array<string>): Promise<Map<string, string>>;//uin->uid getVasInfo(callfrom: string, uids: string[]): Promise<Map<string, any>>;
getRelationFlag(callfrom: string, uids: string[]): Promise<Map<string, any>>;
getUidByUin(callfrom: string, uin: Array<string>): Promise<Map<string, string>>;
getUinByUid(callfrom: string, uid: Array<string>): Promise<Map<string, string>>; getUinByUid(callfrom: string, uid: Array<string>): Promise<Map<string, string>>;
// {
// coreInfo: CoreInfo,
// baseInfo: BaseInfo,
// status: null,
// vasInfo: null,
// relationFlags: null,
// otherFlags: null,
// intimate: null
// }
getCoreAndBaseInfo(callfrom: string, uids: string[]): Promise<Map<string, SimpleInfo>>; getCoreAndBaseInfo(callfrom: string, uids: string[]): Promise<Map<string, SimpleInfo>>;
fetchUserDetailInfo(trace: string, uids: string[], arg2: number, arg3: number[]): Promise<unknown>; fetchUserDetailInfo(trace: string, uids: string[], source: UserDetailSource, bizType: ProfileBizType[]): Promise<GeneralCallResult>;
addKernelProfileListener(listener: NodeIKernelProfileListener): number; addKernelProfileListener(listener: NodeIKernelProfileListener): number;
@@ -44,30 +27,17 @@ export interface NodeIKernelProfileService {
enumCountryOptions(): Array<string>; enumCountryOptions(): Array<string>;
enumProvinceOptions(Country: string): Array<string>; enumProvinceOptions(country: string): Array<string>;
enumCityOptions(Country: string, Province: string): unknown; enumCityOptions(country: string, province: string): unknown;
enumAreaOptions(...args: unknown[]): 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<unknown>; modifySelfProfile(...args: unknown[]): Promise<unknown>;
modifyDesktopMiniProfile(param: ModifyProfileParams): Promise<GeneralCallResult>; modifyDesktopMiniProfile(param: ModifyProfileParams): Promise<GeneralCallResult>;
setNickName(NickName: string): Promise<unknown>; setNickName(nickName: string): Promise<unknown>;
setLongNick(longNick: string): Promise<unknown>; setLongNick(longNick: string): Promise<unknown>;
@@ -85,7 +55,7 @@ export interface NodeIKernelProfileService {
getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise<GeneralCallResult>; getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise<GeneralCallResult>;
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUinV2>; getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUin>;
getZplanAvatarInfos(args: string[]): Promise<unknown>; getZplanAvatarInfos(args: string[]): Promise<unknown>;
@@ -95,14 +65,12 @@ export interface NodeIKernelProfileService {
getSelfStatus(): Promise<unknown>; getSelfStatus(): Promise<unknown>;
//
setdisableEmojiShortCuts(...args: unknown[]): unknown; setdisableEmojiShortCuts(...args: unknown[]): unknown;
getProfileQzonePicInfo(uid: string, type: number, force: boolean): Promise<unknown>; getProfileQzonePicInfo(uid: string, type: number, force: boolean): Promise<unknown>;
//profileService.getCoreInfo("UserRemarkServiceImpl::getStrangerRemarkByUid", arrayList); // UserRemarkServiceImpl::getStrangerRemarkByUid []
getCoreInfo(name: string, arg: any[]): unknown; getCoreInfo(sceneId: string, arg: any[]): unknown;
//m429253e12.getOtherFlag("FriendListInfoCache_getKernelDataAndPutCache", new ArrayList<>());
isNull(): boolean; isNull(): boolean;
} }

View File

@@ -1,30 +1,8 @@
import { ChatType, Peer } from '../entities'; import { ChatType, Peer } from '../entities';
import { NodeIKernelRecentContactListener } from '../listeners/NodeIKernelRecentContactListener'; import { NodeIKernelRecentContactListener } from '../listeners/NodeIKernelRecentContactListener';
import { GeneralCallResult } from './common'; import { GeneralCallResult } from './common';
import { FSABRecentContactParams } from '../entities/contact';
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 { export interface NodeIKernelRecentContactService {
setGuildDisplayStatus(...args: unknown[]): unknown; // 2 arguments setGuildDisplayStatus(...args: unknown[]): unknown; // 2 arguments
@@ -36,7 +14,6 @@ export interface NodeIKernelRecentContactService {
enterOrExitMsgList(...args: unknown[]): unknown; // 1 arguments enterOrExitMsgList(...args: unknown[]): unknown; // 1 arguments
/*!---!*/
getRecentContactListSnapShot(count: number): Promise<GeneralCallResult & { getRecentContactListSnapShot(count: number): Promise<GeneralCallResult & {
info: { info: {
errCode: number, errCode: number,
@@ -58,7 +35,6 @@ export interface NodeIKernelRecentContactService {
jumpToSpecifyRecentContact(...args: unknown[]): unknown; // 1 arguments jumpToSpecifyRecentContact(...args: unknown[]): unknown; // 1 arguments
/*!---!*/
fetchAndSubscribeABatchOfRecentContact(params: FSABRecentContactParams): unknown; // 1 arguments fetchAndSubscribeABatchOfRecentContact(params: FSABRecentContactParams): unknown; // 1 arguments
addRecentContact(peer: Peer): unknown; addRecentContact(peer: Peer): unknown;

View File

@@ -99,23 +99,6 @@ export interface NodeIKernelRichMediaService {
getRichMediaFileDir(elementType: number, downType: number, isTemp: boolean): unknown; 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: { getVideoPlayUrlInVisit(arg: {
downloadType: number, downloadType: number,
thumbSize: number, thumbSize: number,
@@ -131,7 +114,6 @@ export interface NodeIKernelRichMediaService {
useHttps: boolean useHttps: boolean
}): Promise<unknown>; }): Promise<unknown>;
//arg双端number
isFileExpired(arg: number): unknown; isFileExpired(arg: number): unknown;
deleteGroupFolder(GroupCode: string, FolderId: string): Promise<GeneralCallResult & { deleteGroupFolder(GroupCode: string, FolderId: string): Promise<GeneralCallResult & {
@@ -154,7 +136,6 @@ export interface NodeIKernelRichMediaService {
useHttps: boolean useHttps: boolean
}): unknown; }): unknown;
//arg3为“”
downloadFileForModelId(peer: Peer, ModelId: string[], unknown: string): Promise<unknown>; downloadFileForModelId(peer: Peer, ModelId: string[], unknown: string): Promise<unknown>;
//第三个参数 Array<Type> //第三个参数 Array<Type>

View File

@@ -1,13 +1,20 @@
import { ChatType } from '../entities'; import { ChatType } from '../entities';
import { GeneralCallResult } from './common';
export interface NodeIKernelSearchService { export interface NodeIKernelSearchService {
addKernelSearchListener(...args: any[]): unknown;// needs 1 arguments
removeKernelSearchListener(...args: any[]): unknown;// needs 1 arguments addKernelSearchListener(listener: unknown): number;
searchStranger(...args: any[]): unknown;// needs 3 arguments removeKernelSearchListener(listenerId: number): void;
searchGroup(...args: any[]): unknown;// needs 1 arguments searchStranger(unknown: string, searchStranger: unknown, searchParams: unknown): Promise<unknown>;
searchGroup(param: {
keyWords: string,
groupNum: number,
exactSearch: boolean,
penetrate: string
}): Promise<GeneralCallResult>;// needs 1 arguments
searchLocalInfo(keywords: string, unknown: number/*4*/): unknown; searchLocalInfo(keywords: string, unknown: number/*4*/): unknown;
@@ -125,4 +132,5 @@ export interface NodeIKernelSearchService {
searchCache(...args: any[]): unknown;// needs 3 arguments searchCache(...args: any[]): unknown;// needs 3 arguments
clearSearchCache(...args: any[]): unknown;// needs 1 arguments clearSearchCache(...args: any[]): unknown;// needs 1 arguments
} }

View File

@@ -3,9 +3,9 @@ import { GeneralCallResult } from './common';
export interface NodeIKernelStorageCleanService { export interface NodeIKernelStorageCleanService {
addKernelStorageCleanListener(Listener: NodeIKernelStorageCleanListener): number; addKernelStorageCleanListener(listener: NodeIKernelStorageCleanListener): number;
removeKernelStorageCleanListener(ListenerId: number): void; removeKernelStorageCleanListener(listenerId: number): void;
addCacheScanedPaths(arg: unknown): unknown; addCacheScanedPaths(arg: unknown): unknown;

View File

@@ -1,9 +1,7 @@
export interface NodeIKernelTianShuService { export interface NodeIKernelTianShuService {
addKernelTianShuListener(...args: any[]): unknown;// needs 1 arguments addKernelTianShuListener(listener:unknown): number;
removeKernelTianShuListener(...args: any[]): unknown;// needs 1 arguments removeKernelTianShuListener(listenerId:number): void;
requesTianShuNumeralRe(...args: any[]): unknown;//d needs 1 arguments
reportTianShuNumeralRed(...args: any[]): unknown;// needs 1 arguments reportTianShuNumeralRed(...args: any[]): unknown;// needs 1 arguments

View File

@@ -2,9 +2,9 @@ import { ForceFetchClientKeyRetType } from './common';
export interface NodeIKernelTicketService { export interface NodeIKernelTicketService {
addKernelTicketListener(listener: unknown): void; addKernelTicketListener(listener: unknown): number;
removeKernelTicketListener(listenerId: unknown): void; removeKernelTicketListener(listenerId: number): void;
forceFetchClientKey(arg: string): Promise<ForceFetchClientKeyRetType>; forceFetchClientKey(arg: string): Promise<ForceFetchClientKeyRetType>;

View File

@@ -2,7 +2,7 @@ import { GeneralCallResult } from './common';
export interface NodeIKernelTipOffService { export interface NodeIKernelTipOffService {
addKernelTipOffListener(listener: unknown): void; addKernelTipOffListener(listener: unknown): number;
removeKernelTipOffListener(listenerId: unknown): void; removeKernelTipOffListener(listenerId: unknown): void;
@@ -10,7 +10,7 @@ export interface NodeIKernelTipOffService {
getPskey(domainList: string[], nocache: boolean): Promise<GeneralCallResult & { getPskey(domainList: string[], nocache: boolean): Promise<GeneralCallResult & {
domainPskeyMap: Map<string, string> domainPskeyMap: Map<string, string>
}>;//2 }>;
tipOffSendJsData(args: unknown[]): Promise<unknown>;//2 tipOffSendJsData(args: unknown[]): Promise<unknown>;//2

View File

@@ -1,7 +1,8 @@
export interface NodeIKernelUnitedConfigService { export interface NodeIKernelUnitedConfigService {
addKernelUnitedConfigListener(...args: any[]): unknown;// needs 1 arguments
removeKernelUnitedConfigListener(...args: any[]): unknown;// needs 1 arguments addKernelUnitedConfigListener(listener:unknown): number;
removeKernelUnitedConfigListener(listenerId:number): void;
fetchUnitedCommendConfig(...args: any[]): unknown;// needs 1 arguments fetchUnitedCommendConfig(...args: any[]): unknown;// needs 1 arguments
@@ -12,4 +13,5 @@ export interface NodeIKernelUnitedConfigService {
isUnitedConfigSwitchOn(...args: any[]): unknown;// needs 1 arguments isUnitedConfigSwitchOn(...args: any[]): unknown;// needs 1 arguments
registerUnitedConfigPushGroupList(...args: any[]): unknown;// needs 1 arguments registerUnitedConfigPushGroupList(...args: any[]): unknown;// needs 1 arguments
} }

View File

@@ -1,5 +1,5 @@
// public interface IYellowFaceForManagerService extends QRouteApi { export interface NodeIYellowFaceService {
// void download(@NotNull String resourceConfigJson, @NotNull String resourceDir, @NotNull String cacheDir, boolean force, @NotNull IKernelYellowFaceDownloadCallback callback); download(resourceConfigJson: string, resourceDir: string, cacheDir: string, force: boolean): void;
// void setHistory(@NotNull String fullMd5, @NotNull IOperateCallback callback); setHistory(fullMd5: string): void;
// } }

View File

@@ -1,6 +1,7 @@
import { MessageElement, Peer } from '../entities'; import { MessageElement, Peer } from '../entities';
export interface NodeIkernelTestPerformanceService { export interface NodeIkernelTestPerformanceService {
insertMsg(MsgParam: { insertMsg(MsgParam: {
peer: Peer peer: Peer
msgTime: string msgTime: string

View File

@@ -1,6 +1,5 @@
export enum GeneralCallResultStatus { export enum GeneralCallResultStatus {
OK = 0, OK = 0
// ERROR = 1,
} }
export interface GeneralCallResult { export interface GeneralCallResult {

View File

@@ -54,7 +54,7 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
public async websocketHandle(payload: PayloadType, echo: any): Promise<OB11Return<ReturnDataType | null>> { public async websocketHandle(payload: PayloadType, echo: any): Promise<OB11Return<ReturnDataType | null>> {
const result = await this.check(payload); const result = await this.check(payload);
if (!result.valid) { if (!result.valid) {
return OB11Response.error(result.message, 1400); return OB11Response.error(result.message, 1400, echo);
} }
try { try {
const resData = await this._handle(payload); const resData = await this._handle(payload);

View File

@@ -1,6 +1,6 @@
import { OB11Return } from '../types'; import { OB11Return } from '../types';
import { isNull } from '../../common/helper'; import { isNull } from '@/common/helper';
export class OB11Response { export class OB11Response {
static res<T>(data: T, status: string, retcode: number, message: string = ''): OB11Return<T> { static res<T>(data: T, status: string, retcode: number, message: string = ''): OB11Return<T> {

View File

@@ -11,7 +11,7 @@ export default class GetGroupAddRequest extends BaseAction<null, OB11GroupReques
actionName = ActionName.GetGroupIgnoreAddRequest; actionName = ActionName.GetGroupIgnoreAddRequest;
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> { async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies(); // const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies();
// log(data); // log(data);
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE); // const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE);
// const returnData: OB11GroupRequestNotify[] = []; // const returnData: OB11GroupRequestNotify[] = [];

View File

@@ -19,26 +19,21 @@ export class OCRImage extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.image)); const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.image));
if (!success) { if (!success) {
throw `OCR ${payload.image}失败,image字段可能格式不正确`; throw `OCR ${payload.image}失败,image字段可能格式不正确`;
} }
if (path) { if (path) {
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断 await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断
const ret = await this.core.apis.SystemApi.ocrImage(path); const ret = await this.core.apis.SystemApi.ocrImage(path);
if (!isLocal) { fs.unlink(path, () => { });
fs.unlink(path, () => {
});
}
if (!ret) { if (!ret) {
throw `OCR ${payload.file}失败`; throw `OCR ${payload.file}失败`;
} }
return ret.result; return ret.result;
} }
if (!isLocal) { fs.unlink(path, () => { });
fs.unlink(path, () => {
});
}
throw `OCR ${payload.file}失败,文件可能不存在`; throw `OCR ${payload.file}失败,文件可能不存在`;
} }
} }

View File

@@ -24,17 +24,16 @@ export default class SetAvatar extends BaseAction<Payload, null> {
} }
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.file)); const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
if (!success) { if (!success) {
throw `头像${payload.file}设置失败,file字段可能格式不正确`; throw `头像${payload.file}设置失败,file字段可能格式不正确`;
} }
if (path) { if (path) {
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断 await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断
const ret = await this.core.apis.UserApi.setQQAvatar(path); const ret = await this.core.apis.UserApi.setQQAvatar(path);
if (!isLocal) {
fs.unlink(path, () => { fs.unlink(path, () => {
}); });
}
if (!ret) { if (!ret) {
throw `头像${payload.file}设置失败,api无返回`; throw `头像${payload.file}设置失败,api无返回`;
} }
@@ -45,10 +44,8 @@ export default class SetAvatar extends BaseAction<Payload, null> {
throw `头像${payload.file}设置失败,未知的错误,${ret['result']}:${ret['errMsg']}`; throw `头像${payload.file}设置失败,未知的错误,${ret['result']}:${ret['errMsg']}`;
} }
} else { } else {
if (!isLocal) { fs.unlink(path, () => { });
fs.unlink(path, () => {
});
}
throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`; throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`;
} }
return null; return null;

View File

@@ -1,23 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
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<typeof SchemaData>;
export class DelGroupFile extends BaseAction<Payload, any> {
actionName = ActionName.DelGroupFile;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
return await this.core.apis.GroupApi.DelGroupFile(payload.group_id.toString(), [payload.file_id]);
}
}

View File

@@ -1,24 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
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<typeof SchemaData>;
export class DelGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.DelGroupFileFolder;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
return (await this.core.apis.GroupApi.DelGroupFileFolder(
payload.group_id.toString(), payload.folder_id)).groupFileCommonResult;
}
}

View File

@@ -3,6 +3,7 @@ import fs from 'fs/promises';
import { FileNapCatOneBotUUID } from '@/common/helper'; import { FileNapCatOneBotUUID } from '@/common/helper';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types';
export interface GetFilePayload { export interface GetFilePayload {
file: string; // 文件名或者fileUuid file: string; // 文件名或者fileUuid
@@ -33,16 +34,27 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
if (contextMsgFile) { if (contextMsgFile) {
const { peer, msgId, elementId } = contextMsgFile; const { peer, msgId, elementId } = contextMsgFile;
const downloadPath = await this.core.apis.FileApi.downloadMedia(msgId, peer.chatType, peer.peerUid, elementId, '', ''); const downloadPath = await this.core.apis.FileApi.downloadMedia(msgId, peer.chatType, peer.peerUid, elementId, '', '');
const mixElement = (await this.core.apis.MsgApi.getMsgsByMsgId(peer, [msgId]))?.msgList const rawMessage = (await this.core.apis.MsgApi.getMsgsByMsgId(peer, [msgId]))?.msgList
.find(msg => msg.msgId === msgId)?.elements.find(e => e.elementId === elementId); .find(msg => msg.msgId === msgId);
const mixElement = rawMessage?.elements.find(e => e.elementId === elementId);
const mixElementInner = mixElement?.videoElement ?? mixElement?.fileElement ?? mixElement?.pttElement ?? mixElement?.picElement; const mixElementInner = mixElement?.videoElement ?? mixElement?.fileElement ?? mixElement?.pttElement ?? mixElement?.picElement;
if (!mixElementInner) throw new Error('element not found'); if (!mixElementInner) throw new Error('element not found');
const fileSize = mixElementInner.fileSize?.toString() ?? ''; const fileSize = mixElementInner.fileSize?.toString() ?? '';
const fileName = mixElementInner.fileName ?? ''; const fileName = mixElementInner.fileName ?? '';
let url = '';
if (mixElement?.picElement && rawMessage) {
const tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.picElement?.(mixElement?.picElement, rawMessage, mixElement) as OB11MessageImage | undefined;
url = tempData?.data.url ?? '';
}
if (mixElement?.videoElement && rawMessage) {
const tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.videoElement?.(mixElement?.videoElement, rawMessage, mixElement) as OB11MessageVideo | undefined;
url = tempData?.data.url ?? '';
}
const res: GetFileResponse = { const res: GetFileResponse = {
file: downloadPath, file: downloadPath,
url: downloadPath, url: url !== '' ? url : downloadPath,
file_size: fileSize, file_size: fileSize,
file_name: fileName, file_name: fileName,
}; };

View File

@@ -1,23 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFileCount extends BaseAction<Payload, { count: number }> {
actionName = ActionName.GetGroupFileCount;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const ret = await this.core.apis.GroupApi.getGroupFileCount([payload.group_id?.toString()]);
return { count: ret.groupFileCounts[0] };
}
}

View File

@@ -1,50 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FileNapCatOneBotUUID } from '@/common/helper';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
start_index: { type: ['string', 'number'] },
file_count: { type: ['string', 'number'] },
folder_id: { type: ['string', 'number'] },
},
required: ['group_id', 'start_index', 'file_count'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFileList extends BaseAction<Payload, { FileList: Array<any> }> {
actionName = ActionName.GetGroupFileList;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
let param = {};
if (payload.folder_id) {
param = {
folderId: payload.folder_id.toString(),
};
}
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1,
fileCount: +payload.file_count,
startIndex: +payload.start_index,
sortOrder: 2,
showOnlinedocFolder: 0,
...param
}).catch(() => {
return [];
});
ret.forEach((e) => {
const fileModelId = e?.fileInfo?.fileModelId;
if (fileModelId)
e.fileInfo!.fileId = FileNapCatOneBotUUID.encodeModelId({
chatType: 2,
peerUid: payload.group_id.toString()
}, fileModelId);
});
return { FileList: ret };
}
}

View File

@@ -1,23 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
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<typeof SchemaData>;
export class SetGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.SetGroupFileFolder;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
return (await this.core.apis.GroupApi.CreatGroupFileFolder(payload.group_id.toString(), payload.folder_name)).resultWithGroupItem;
}
}

View File

@@ -1,9 +1,6 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatOneBot11Adapter } from '@/onebot';
import { NapCatCore } from '@/core';
import { SetGroupFileFolder } from '@/onebot/action/file/SetGroupFileFolder';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@@ -16,17 +13,10 @@ const SchemaData = {
type Payload = FromSchema<typeof SchemaData>; type Payload = FromSchema<typeof SchemaData>;
export class CreateGroupFileFolder extends BaseAction<Payload, null> { export class CreateGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_CreateGroupFileFolder; actionName = ActionName.GoCQHTTP_CreateGroupFileFolder;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncSetGroupFileFolderImpl: SetGroupFileFolder) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
await this.ncSetGroupFileFolderImpl._handle(payload); return (await this.core.apis.GroupApi.CreatGroupFileFolder(payload.group_id.toString(), payload.folder_name)).resultWithGroupItem;
return null;
} }
} }

View File

@@ -1,9 +1,7 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatCore } from '@/core'; import { FileNapCatOneBotUUID } from '@/common/helper';
import { NapCatOneBot11Adapter } from '@/onebot';
import { DelGroupFile } from '@/onebot/action/file/DelGroupFile';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@@ -16,17 +14,12 @@ const SchemaData = {
type Payload = FromSchema<typeof SchemaData>; type Payload = FromSchema<typeof SchemaData>;
export class DeleteGroupFile extends BaseAction<Payload, null> { export class DeleteGroupFile extends BaseAction<Payload, any> {
actionName = ActionName.GOCQHTTP_DeleteGroupFile; actionName = ActionName.GOCQHTTP_DeleteGroupFile;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncDelGroupFileImpl: DelGroupFile) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
await this.ncDelGroupFileImpl._handle(payload); const data = FileNapCatOneBotUUID.decodeModelId(payload.file_id);
return null; if (!data) throw new Error('Invalid file_id');
return await this.core.apis.GroupApi.DelGroupFile(payload.group_id.toString(), [data.fileId]);
} }
} }

View File

@@ -1,9 +1,6 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatCore } from '@/core'; import BaseAction from '../BaseAction';
import { NapCatOneBot11Adapter } from '@/onebot';
import { DelGroupFileFolder } from '@/onebot/action/file/DelGroupFileFolder';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@@ -16,17 +13,11 @@ const SchemaData = {
type Payload = FromSchema<typeof SchemaData>; type Payload = FromSchema<typeof SchemaData>;
export class DeleteGroupFileFolder extends BaseAction<Payload, null> { export class DeleteGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder; actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncDelGroupFileFolderImpl: DelGroupFileFolder) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
await this.ncDelGroupFileFolderImpl._handle(payload); return (await this.core.apis.GroupApi.DelGroupFileFolder(
return null; payload.group_id.toString(), payload.folder_id)).groupFileCommonResult;
} }
} }

View File

@@ -1,9 +1,6 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatOneBot11Adapter, OB11GroupFile } from '@/onebot';
import { NapCatCore } from '@/core';
import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
import { OB11Entities } from '@/onebot/entities'; import { OB11Entities } from '@/onebot/entities';
const SchemaData = { const SchemaData = {
@@ -11,33 +8,21 @@ const SchemaData = {
properties: { properties: {
group_id: { type: ['string', 'number'] }, group_id: { type: ['string', 'number'] },
folder_id: { type: 'string' }, folder_id: { type: 'string' },
file_count: { type: ['string', 'number'] },
}, },
required: ['group_id', 'folder_id'], required: ['group_id', 'folder_id'],
} as const satisfies JSONSchema; } as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFilesByFolder extends BaseAction<Payload, { export class GetGroupFilesByFolder extends BaseAction<any, any> {
files: OB11GroupFile[],
folders: [] // QQ does not allow nested folders
}> {
actionName = ActionName.GoCQHTTP_GetGroupFilesByFolder; actionName = ActionName.GoCQHTTP_GetGroupFilesByFolder;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private getGroupRootFilesImpl: GetGroupRootFiles) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
const folder = (await this.getGroupRootFilesImpl._handle({ group_id: payload.group_id }))
.folders.find(folder => folder.folder_id === payload.folder_id);
if (!folder) {
throw new Error('Folder not found');
}
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), { const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1, sortType: 1,
fileCount: folder.total_file_count, fileCount: +(payload.file_count ?? 50),
startIndex: 0, startIndex: 0,
sortOrder: 2, sortOrder: 2,
showOnlinedocFolder: 0, showOnlinedocFolder: 0,

View File

@@ -1,15 +1,14 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatOneBot11Adapter, OB11GroupFile, OB11GroupFileFolder } from '@/onebot'; import { OB11GroupFile, OB11GroupFileFolder } from '@/onebot';
import { NapCatCore } from '@/core';
import { GetGroupFileCount } from '@/onebot/action/file/GetGroupFileCount';
import { OB11Entities } from '@/onebot/entities'; import { OB11Entities } from '@/onebot/entities';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
properties: { properties: {
group_id: { type: ['string', 'number'] }, group_id: { type: ['string', 'number'] },
file_count: { type: ['string', 'number'] },
}, },
required: ['group_id'], required: ['group_id'],
} as const satisfies JSONSchema; } as const satisfies JSONSchema;
@@ -22,16 +21,10 @@ export class GetGroupRootFiles extends BaseAction<Payload, {
}> { }> {
actionName = ActionName.GoCQHTTP_GetGroupRootFiles; actionName = ActionName.GoCQHTTP_GetGroupRootFiles;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncGetGroupFileCountImpl: GetGroupFileCount) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), { const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1, sortType: 1,
fileCount: (await this.ncGetGroupFileCountImpl._handle({ group_id: payload.group_id.toString() })).count, fileCount: +(payload.file_count ?? 50),
startIndex: 0, startIndex: 0,
sortOrder: 2, sortOrder: 2,
showOnlinedocFolder: 0, showOnlinedocFolder: 0,

View File

@@ -20,7 +20,7 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
async _handle(payload: Payload): Promise<OB11User> { async _handle(payload: Payload): Promise<OB11User> {
const user_id = payload.user_id.toString(); const user_id = payload.user_id.toString();
const extendData = await this.core.apis.UserApi.getUserDetailInfoByUinV2(user_id); const extendData = await this.core.apis.UserApi.getUserDetailInfoByUin(user_id);
const uid = (await this.core.apis.UserApi.getUidByUinV2(user_id))!; const uid = (await this.core.apis.UserApi.getUidByUinV2(user_id))!;
if (!uid || uid.indexOf('*') != -1) { if (!uid || uid.indexOf('*') != -1) {
return { return {
@@ -28,6 +28,7 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
...extendData.detail.commonExt, ...extendData.detail.commonExt,
...extendData.detail.simpleInfo.baseInfo, ...extendData.detail.simpleInfo.baseInfo,
...extendData.detail.simpleInfo.relationFlags, ...extendData.detail.simpleInfo.relationFlags,
...extendData.detail.simpleInfo.status,
user_id: parseInt(extendData.detail.uin) || 0, user_id: parseInt(extendData.detail.uin) || 0,
nickname: extendData.detail.simpleInfo.coreInfo.nick, nickname: extendData.detail.simpleInfo.coreInfo.nick,
sex: OB11UserSex.unknown, sex: OB11UserSex.unknown,

View File

@@ -11,7 +11,10 @@ const SchemaData = {
content: { type: 'string' }, content: { type: 'string' },
image: { type: 'string' }, image: { type: 'string' },
pinned: { type: ['number', 'string'] }, pinned: { type: ['number', 'string'] },
type: { type: ['number', 'string'] },
confirm_required: { type: ['number', 'string'] }, confirm_required: { type: ['number', 'string'] },
is_show_edit_card: { type: ['number', 'string'] },
tip_window_type: { type: ['number', 'string'] },
}, },
required: ['group_id', 'content'], required: ['group_id', 'content'],
} as const satisfies JSONSchema; } as const satisfies JSONSchema;
@@ -22,12 +25,12 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_SendGroupNotice; actionName = ActionName.GoCQHTTP_SendGroupNotice;
async _handle(payload: Payload) { async _handle(payload: Payload) {
let UploadImage: { id: string, width: number, height: number } | undefined = undefined; let UploadImage: { id: string, width: number, height: number } | undefined = undefined;
if (payload.image) { if (payload.image) {
//公告图逻辑 //公告图逻辑
const { const {
path, path,
isLocal,
success, success,
} = (await uri2local(this.core.NapCatTempPath, payload.image)); } = (await uri2local(this.core.NapCatTempPath, payload.image));
if (!success) { if (!success) {
@@ -41,18 +44,33 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
if (ImageUploadResult.errCode != 0) { if (ImageUploadResult.errCode != 0) {
throw `群公告${payload.image}设置失败,图片上传失败`; throw `群公告${payload.image}设置失败,图片上传失败`;
} }
if (!isLocal) {
unlink(path, () => { unlink(path, () => {
}); });
}
UploadImage = ImageUploadResult.picInfo; UploadImage = ImageUploadResult.picInfo;
} }
const noticePinned = +(payload.pinned ?? 0);
const noticeConfirmRequired = +(payload.confirm_required ?? 0);
const publishGroupBulletinResult = await this.core.apis.GroupApi.publishGroupBulletin(payload.group_id.toString(), payload.content, UploadImage, noticePinned, noticeConfirmRequired);
if (publishGroupBulletinResult.result != 0) { const noticeType = +(payload.type ?? 1);
throw `设置群公告失败,错误信息:${publishGroupBulletinResult.errMsg}`; const noticePinned = +(payload.pinned ?? 0);
const noticeShowEditCard = +(payload.is_show_edit_card ?? 0);
const noticeTipWindowType = +(payload.tip_window_type ?? 0);
const noticeConfirmRequired = +(payload.confirm_required ?? 1);
const publishGroupBulletinResult = await this.core.apis.WebApi.setGroupNotice(
payload.group_id.toString(),
payload.content,
noticePinned,
noticeType,
noticeShowEditCard,
noticeTipWindowType,
noticeConfirmRequired,
UploadImage?.id,
UploadImage?.width,
UploadImage?.height
);
if (!publishGroupBulletinResult || publishGroupBulletinResult.ec != 0) {
throw new Error(`设置群公告失败,错误信息:${publishGroupBulletinResult?.em}`);
} }
return null; return null;
} }

View File

@@ -25,17 +25,14 @@ export default class SetGroupPortrait extends BaseAction<Payload, any> {
} }
async _handle(payload: Payload): Promise<any> { async _handle(payload: Payload): Promise<any> {
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.file)); const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
if (!success) { if (!success) {
throw `头像${payload.file}设置失败,file字段可能格式不正确`; throw `头像${payload.file}设置失败,file字段可能格式不正确`;
} }
if (path) { if (path) {
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断 await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断
const ret = await this.core.apis.GroupApi.setGroupAvatar(payload.group_id.toString(), path) as any; const ret = await this.core.apis.GroupApi.setGroupAvatar(payload.group_id.toString(), path) as any;
if (!isLocal) { fs.unlink(path, () => { });
fs.unlink(path, () => {
});
}
if (!ret) { if (!ret) {
throw `头像${payload.file}设置失败,api无返回`; throw `头像${payload.file}设置失败,api无返回`;
} }
@@ -46,10 +43,7 @@ export default class SetGroupPortrait extends BaseAction<Payload, any> {
} }
return ret; return ret;
} else { } else {
if (!isLocal) { fs.unlink(path, () => {});
fs.unlink(path, () => {
});
}
throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`; throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`;
} }
} }

View File

@@ -1,9 +1,10 @@
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { ChatType } from '@/core/entities'; import { ChatType, Peer } from '@/core/entities';
import fs from 'fs'; import fs from 'fs';
import { uri2local } from '@/common/file'; import { uri2local } from '@/common/file';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageContext } from '@/onebot/api';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@@ -29,14 +30,19 @@ export default class GoCQHTTPUploadGroupFile extends BaseAction<Payload, null> {
file = `file://${file}`; file = `file://${file}`;
} }
const downloadResult = await uri2local(this.core.NapCatTempPath, file); const downloadResult = await uri2local(this.core.NapCatTempPath, file);
const peer: Peer = {
chatType: ChatType.KCHATTYPEGROUP,
peerUid: payload.group_id.toString(),
};
if (!downloadResult.success) { if (!downloadResult.success) {
throw new Error(downloadResult.errMsg); throw new Error(downloadResult.errMsg);
} }
const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name, payload.folder_id); const msgContext: MessageContext = {
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId({ peer: peer,
chatType: ChatType.KCHATTYPEGROUP, deleteAfterSentFiles: []
peerUid: payload.group_id.toString(), };
}, [sendFileEle], [], true); const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name, payload.folder_id);
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, [sendFileEle], [], true);
return null; return null;
} }
} }

View File

@@ -4,6 +4,8 @@ import { ChatType, Peer, SendFileElement } from '@/core/entities';
import fs from 'fs'; import fs from 'fs';
import { uri2local } from '@/common/file'; import { uri2local } from '@/common/file';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageContext } from '@/onebot/api';
import { ContextMode, createContext } from '../msg/SendMsg';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@@ -42,7 +44,15 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
if (!downloadResult.success) { if (!downloadResult.success) {
throw new Error(downloadResult.errMsg); throw new Error(downloadResult.errMsg);
} }
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name);
const msgContext: MessageContext = {
peer: await createContext(this.core, {
user_id: payload.user_id.toString(),
group_id: undefined,
}, ContextMode.Private),
deleteAfterSentFiles: []
};
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name);
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(await this.getPeer(payload), [sendFileEle], [], true); await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(await this.getPeer(payload), [sendFileEle], [], true);
return null; return null;
} }

View File

@@ -51,7 +51,7 @@ export class GetGroupEssence extends BaseAction<Payload, any> {
operator_nick: msg.add_digest_nick, operator_nick: msg.add_digest_nick,
message_id: message_id, message_id: message_id,
operator_time: msg.add_digest_time, operator_time: msg.add_digest_time,
content: (await this.obContext.apis.MsgApi.parseMessage(rawMessage, 'array'))?.message content: (await this.obContext.apis.MsgApi.parseMessage(rawMessage))?.message
}; };
} }
const msgTempData = JSON.stringify({ const msgTempData = JSON.stringify({

View File

@@ -20,7 +20,17 @@ class GetGroupInfo extends BaseAction<Payload, OB11Group> {
async _handle(payload: Payload) { async _handle(payload: Payload) {
const group = (await this.core.apis.GroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString()); const group = (await this.core.apis.GroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString());
if (!group) throw `${payload.group_id}不存在`; if (!group) {
const data = await this.core.apis.GroupApi.searchGroup(payload.group_id.toString());
if (!data) throw new Error('Group not found');
return {
...data.searchGroupInfo,
group_id: +payload.group_id,
group_name: data.searchGroupInfo.groupName,
member_count: data.searchGroupInfo.memberNum,
max_member_count: data.searchGroupInfo.maxMemberNum,
}
}
return OB11Entities.group(group); return OB11Entities.group(group);
} }
} }

View File

@@ -26,7 +26,7 @@ class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString()); const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error(`Uin2Uid Error ${payload.user_id}不存在`); if (!uid) throw new Error(`Uin2Uid Error ${payload.user_id}不存在`);
const [member, info] = await Promise.allSettled([ const [member, info] = await Promise.allSettled([
this.core.apis.GroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache), this.core.apis.GroupApi.getGroupMemberEx(payload.group_id.toString(), uid, isNocache),
this.core.apis.UserApi.getUserDetailInfo(uid), this.core.apis.UserApi.getUserDetailInfo(uid),
]); ]);
if (member.status !== 'fulfilled') throw new Error(`群(${payload.group_id})成员${payload.user_id}获取失败 ${member.reason}`); if (member.status !== 'fulfilled') throw new Error(`群(${payload.group_id})成员${payload.user_id}获取失败 ${member.reason}`);

View File

@@ -55,12 +55,7 @@ import { GoCQHTTPHandleQuickAction } from './go-cqhttp/QuickAction';
import { GetGroupIgnoredNotifies } from './group/GetGroupIgnoredNotifies'; import { GetGroupIgnoredNotifies } from './group/GetGroupIgnoredNotifies';
import { GetOnlineClient } from './go-cqhttp/GetOnlineClient'; import { GetOnlineClient } from './go-cqhttp/GetOnlineClient';
import { IOCRImage, OCRImage } from './extends/OCRImage'; import { IOCRImage, OCRImage } from './extends/OCRImage';
import { GetGroupFileCount } from './file/GetGroupFileCount';
import { GetGroupFileList } from './file/GetGroupFileList';
import { TranslateEnWordToZn } from './extends/TranslateEnWordToZn'; import { TranslateEnWordToZn } from './extends/TranslateEnWordToZn';
import { SetGroupFileFolder } from './file/SetGroupFileFolder';
import { DelGroupFile } from './file/DelGroupFile';
import { DelGroupFileFolder } from './file/DelGroupFileFolder';
import { SetQQProfile } from './go-cqhttp/SetQQProfile'; import { SetQQProfile } from './go-cqhttp/SetQQProfile';
import { ShareGroupEx, SharePeer } from './extends/ShareContact'; import { ShareGroupEx, SharePeer } from './extends/ShareContact';
import { CreateCollection } from './extends/CreateCollection'; import { CreateCollection } from './extends/CreateCollection';
@@ -88,15 +83,11 @@ import { DeleteGroupFileFolder } from '@/onebot/action/go-cqhttp/DeleteGroupFile
import { GetGroupFileSystemInfo } from '@/onebot/action/go-cqhttp/GetGroupFileSystemInfo'; import { GetGroupFileSystemInfo } from '@/onebot/action/go-cqhttp/GetGroupFileSystemInfo';
import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles'; import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesByFolder'; import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesByFolder';
import { GetGroupSystemMsg } from './system/GetSystemMsg';
export type ActionMap = Map<string, BaseAction<any, any>>; export type ActionMap = Map<string, BaseAction<any, any>>;
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap { export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap {
const ncDelGroupFile = new DelGroupFile(obContext, core);
const ncSetGroupFileFolder = new SetGroupFileFolder(obContext, core);
const ncDelGroupFileFolder = new DelGroupFileFolder(obContext, core);
const ncGetGroupFileCount = new GetGroupFileCount(obContext, core);
const goCqHttpGetGroupRootFiles = new GetGroupRootFiles(obContext, core, ncGetGroupFileCount);
const actionHandlers = [ const actionHandlers = [
new GetGroupInfoEx(obContext, core), new GetGroupInfoEx(obContext, core),
@@ -113,11 +104,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new MarkPrivateMsgAsRead(obContext, core), new MarkPrivateMsgAsRead(obContext, core),
new SetQQAvatar(obContext, core), new SetQQAvatar(obContext, core),
new TranslateEnWordToZn(obContext, core), new TranslateEnWordToZn(obContext, core),
ncGetGroupFileCount, new GetGroupRootFiles(obContext, core),
new GetGroupFileList(obContext, core),
ncSetGroupFileFolder,
ncDelGroupFile,
ncDelGroupFileFolder,
// onebot11 // onebot11
new SendLike(obContext, core), new SendLike(obContext, core),
new GetMsg(obContext, core), new GetMsg(obContext, core),
@@ -185,12 +172,12 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new SetInputStatus(obContext, core), new SetInputStatus(obContext, core),
new GetCSRF(obContext, core), new GetCSRF(obContext, core),
new DelGroupNotice(obContext, core), new DelGroupNotice(obContext, core),
new DeleteGroupFile(obContext, core, ncDelGroupFile), new DeleteGroupFile(obContext, core),
new CreateGroupFileFolder(obContext, core, ncSetGroupFileFolder), new CreateGroupFileFolder(obContext, core),
new DeleteGroupFileFolder(obContext, core, ncDelGroupFileFolder), new DeleteGroupFileFolder(obContext, core),
new GetGroupFileSystemInfo(obContext, core), new GetGroupFileSystemInfo(obContext, core),
goCqHttpGetGroupRootFiles, new GetGroupFilesByFolder(obContext, core),
new GetGroupFilesByFolder(obContext, core, goCqHttpGetGroupRootFiles), new GetGroupSystemMsg(obContext, core),
]; ];
const actionMap = new Map(); const actionMap = new Map();
for (const action of actionHandlers) { for (const action of actionHandlers) {

Some files were not shown because too many files have changed in this diff Show More