mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
134 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6f6b258f22 | ||
![]() |
717b246cb6 | ||
![]() |
827df80ec8 | ||
![]() |
7117fae2b2 | ||
![]() |
15e9462140 | ||
![]() |
9203fa3df2 | ||
![]() |
c771d75a00 | ||
![]() |
7b10d75aeb | ||
![]() |
b46459de5f | ||
![]() |
ac7f025223 | ||
![]() |
05b77b5042 | ||
![]() |
d6cfe11d97 | ||
![]() |
dd4d59e4e7 | ||
![]() |
7cb8626e16 | ||
![]() |
89b5202adb | ||
![]() |
40ae0c1449 | ||
![]() |
81a8115c56 | ||
![]() |
0ddd26bd51 | ||
![]() |
69e2133a27 | ||
![]() |
b04f85949b | ||
![]() |
667dba01ae | ||
![]() |
85a8cef628 | ||
![]() |
3099acfd00 | ||
![]() |
b00fe0b5f8 | ||
![]() |
9a64b8bdb6 | ||
![]() |
c01e493bd2 | ||
![]() |
890236af23 | ||
![]() |
ea678d805d | ||
![]() |
29699418ff | ||
![]() |
87bb36c39f | ||
![]() |
7cb85ed73c | ||
![]() |
c647771a6d | ||
![]() |
6c3d737219 | ||
![]() |
a1f38fed7a | ||
![]() |
c36bb77286 | ||
![]() |
1a1acdc3c9 | ||
![]() |
ef8e60c405 | ||
![]() |
31c1cc47bf | ||
![]() |
351fed7359 | ||
![]() |
f49e7cbe57 | ||
![]() |
7da8ea5e99 | ||
![]() |
8fa6a12a7c | ||
![]() |
1070278eaf | ||
![]() |
16b1a6b153 | ||
![]() |
096a7534e0 | ||
![]() |
b0897187d2 | ||
![]() |
885d94882d | ||
![]() |
11a3341e13 | ||
![]() |
231890f78a | ||
![]() |
a272feda6a | ||
![]() |
bc936a0ca7 | ||
![]() |
28030c2d13 | ||
![]() |
7fe9176286 | ||
![]() |
1105f9b8d6 | ||
![]() |
e4653defa8 | ||
![]() |
1c62a1e839 | ||
![]() |
3a3bbfe201 | ||
![]() |
1c38833998 | ||
![]() |
38894177ee | ||
![]() |
dce8416942 | ||
![]() |
14219e9b42 | ||
![]() |
7b459e7502 | ||
![]() |
31824c0504 | ||
![]() |
e203abae85 | ||
![]() |
faf83b680b | ||
![]() |
67dcbcb842 | ||
![]() |
6533a25404 | ||
![]() |
4dc760b0e9 | ||
![]() |
25933b9043 | ||
![]() |
a53aaa456e | ||
![]() |
e8a7ea07a5 | ||
![]() |
8817dc6b10 | ||
![]() |
491ec04b46 | ||
![]() |
8a5d4a683b | ||
![]() |
dfc7c7357a | ||
![]() |
690a2f7d34 | ||
![]() |
58f22b24e4 | ||
![]() |
3cce9f528b | ||
![]() |
20fd5ac8cb | ||
![]() |
9e05e086eb | ||
![]() |
056e0adddf | ||
![]() |
b36388200d | ||
![]() |
9793e5741a | ||
![]() |
143380c012 | ||
![]() |
4b92254945 | ||
![]() |
f9c1d8b4a6 | ||
![]() |
c0c469339b | ||
![]() |
0ca6343ed7 | ||
![]() |
3db74c3427 | ||
![]() |
48d5cb53bd | ||
![]() |
fd7d2dbf53 | ||
![]() |
6609697752 | ||
![]() |
dcd6e1973e | ||
![]() |
3614a6e932 | ||
![]() |
931a0210e5 | ||
![]() |
f9e7de4b42 | ||
![]() |
8e0b79594e | ||
![]() |
17122c4360 | ||
![]() |
154f7b6a30 | ||
![]() |
52e5543d0b | ||
![]() |
3c304bd2ae | ||
![]() |
26609bb8fd | ||
![]() |
de3fa9aaa4 | ||
![]() |
788665f84c | ||
![]() |
3943782971 | ||
![]() |
8f899c40f2 | ||
![]() |
a1f582399e | ||
![]() |
440b63f662 | ||
![]() |
7d2cc3b56b | ||
![]() |
5fe3422469 | ||
![]() |
6c02cedb1e | ||
![]() |
3cc2f1dcad | ||
![]() |
773cdc5877 | ||
![]() |
361a7329d7 | ||
![]() |
29910f1236 | ||
![]() |
4a164016f5 | ||
![]() |
cebd3e62a4 | ||
![]() |
2562a38fa1 | ||
![]() |
d46c922bbf | ||
![]() |
66b59982f7 | ||
![]() |
ad397ccf7f | ||
![]() |
bdef80ede7 | ||
![]() |
385dcbc75a | ||
![]() |
74cf501c8f | ||
![]() |
0c200d6748 | ||
![]() |
e65a36c517 | ||
![]() |
126b54ad40 | ||
![]() |
78637751af | ||
![]() |
f96526ee3a | ||
![]() |
b3c7a91f3d | ||
![]() |
b8daeef0c4 | ||
![]() |
2b662944cf | ||
![]() |
3d516df01e | ||
![]() |
26b4a9b15b |
37
LICENSE
37
LICENSE
@@ -1,21 +1,24 @@
|
|||||||
MIT License
|
BSD 2-Clause License
|
||||||
|
|
||||||
Copyright (c) 2024 NapCatQQ
|
Copyright (c) 2024, NapNeko
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Redistribution and use in source and binary forms, with or without
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
modification, are permitted provided that the following conditions are met:
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
copies or substantial portions of the Software.
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
this list of conditions and the following disclaimer in the documentation
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
and/or other materials provided with the distribution.
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
SOFTWARE.
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
@@ -1,32 +0,0 @@
|
|||||||
# v1.6.8
|
|
||||||
|
|
||||||
QQ Version: Windows 9.9.12-26000 / Linux 3.2.9-26000
|
|
||||||
## 使用前警告
|
|
||||||
1. 在最近版本由于QQ本体大幅变动,为了保证NapCat可用性,NapCat近期启动与安装方式将将大幅变动,请关注文档和社群获取。
|
|
||||||
2. 在Core上完全执行开源,请不要用于违法用途,如此可能造成NapCat完全停止更新。
|
|
||||||
3. 针对原启动方式的围堵,NapCat研发了多种方式,除此其余理论与扩展的分析和思路将部分展示于Docs,以便各位参与开发与维护NapCat。
|
|
||||||
## 其余·备注
|
|
||||||
启动方式: WayBoot.03 (Electron Main进程为Node 直接注入代码 同理项目: LiteLoader)
|
|
||||||
|
|
||||||
## 修复与优化
|
|
||||||
1. 移除数据库文件读写 ~ 优化性能
|
|
||||||
2. 重构消息发送 极限速度优化 ~ 优化性能
|
|
||||||
3. WebUi配置热重载优化 ~ 修复问题
|
|
||||||
4. 修复偶现崩溃问题 ~ 修复问题
|
|
||||||
5. 修复群邀请通知事件多次推送问题 ~ 修复问题
|
|
||||||
6. 尝试修复因缓存引起的字段不全问题 ~ 修复问题
|
|
||||||
7. 修复在非常非常高并发的情况 上报自身消息 回复回错问题 ~ 修复问题
|
|
||||||
8. 修复图片SubType字段位置错误问题 ~ 修复问题
|
|
||||||
9. 修复Uid/Uin转换问题 ~ 修复问题
|
|
||||||
|
|
||||||
## 新增与调整
|
|
||||||
1. 最后发言时间重构 入群时间失效 ~ 替换功能
|
|
||||||
2. 重构文件发送/获取 ~ 优化性能
|
|
||||||
3. 支持GOCQ私聊上传接口 ~ 新增功能
|
|
||||||
4. 悄悄告诉你ws http可以同一个端口 ~ 新增功能
|
|
||||||
5. 根据config目录的默认配置初始化新的配置文件 ~ 新增功能
|
|
||||||
6. WebUi可以部署在nginx代理二级目录 配置端口设置为0可关闭WebUi ~ 新增功能
|
|
||||||
7. 新增收藏表情拉取接口 ~ 新增功能
|
|
||||||
8. 新增群头像设置接口 ~ 新增功能
|
|
||||||
|
|
||||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
|
13
docs/changelogs/CHANGELOG.v1.8.3.md
Normal file
13
docs/changelogs/CHANGELOG.v1.8.3.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# v1.8.3
|
||||||
|
|
||||||
|
QQ Version: Windows 9.9.15-26702 / Linux 3.2.12-26702
|
||||||
|
|
||||||
|
## 启动的方式
|
||||||
|
Way03/Way05
|
||||||
|
|
||||||
|
## 新增与调整
|
||||||
|
1. 输入状态变更事件加入
|
||||||
|
2. Way05 支持Bat启动
|
||||||
|
|
||||||
|
|
||||||
|
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.7.2",
|
"version": "1.8.6",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch:dev": "vite --mode development",
|
"watch:dev": "vite --mode development",
|
||||||
"watch:prod": "vite --mode production",
|
"watch:prod": "vite --mode production",
|
||||||
|
90
script/BootWay05.bat
Normal file
90
script/BootWay05.bat
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
@echo off
|
||||||
|
REM 检查当前会话是否具有管理员权限
|
||||||
|
openfiles >nul 2>&1
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
REM 如果不是管理员,则重新启动脚本以管理员模式运行
|
||||||
|
echo 请求管理员权限...
|
||||||
|
powershell -Command "Start-Process cmd -ArgumentList '/c %~f0 %*' -Verb RunAs"
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 设置当前工作目录
|
||||||
|
cd /d %~dp0
|
||||||
|
|
||||||
|
REM 获取当前目录路径
|
||||||
|
set currentPath=%cd%
|
||||||
|
set currentPath=%currentPath:\=/%
|
||||||
|
|
||||||
|
REM 生成JavaScript代码
|
||||||
|
set "jsCode=(async () =^>await import('file:///%currentPath%/napcat.mjs'))();"
|
||||||
|
|
||||||
|
REM 将JavaScript代码保存到文件中
|
||||||
|
echo %jsCode% > loadScript.js
|
||||||
|
echo JavaScript code has been generated and saved to loadScript.js
|
||||||
|
|
||||||
|
REM 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址
|
||||||
|
set NAPCAT_PATH=%cd%\loadScript.js
|
||||||
|
|
||||||
|
REM 获取QQ路径
|
||||||
|
|
||||||
|
|
||||||
|
:loop_read
|
||||||
|
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
|
||||||
|
set RetString=%%b
|
||||||
|
goto :napcat_boot
|
||||||
|
)
|
||||||
|
|
||||||
|
:napcat_boot
|
||||||
|
for %%a in (%RetString%) do (
|
||||||
|
set "pathWithoutUninstall=%%~dpa"
|
||||||
|
)
|
||||||
|
|
||||||
|
SET QQPath=%pathWithoutUninstall%QQ.exe
|
||||||
|
|
||||||
|
REM 拿不到QQ路径则退出
|
||||||
|
if not exist "%QQpath%" (
|
||||||
|
echo provided QQ path is invalid: %QQpath%
|
||||||
|
pause
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 收集dbghelp.dll路径和HASH信息
|
||||||
|
set QQdir=%~dp0
|
||||||
|
set oldDllPath=%QQdir%dbghelp.dll
|
||||||
|
set newDllPath=%currentPath%\dbghelp.dll
|
||||||
|
|
||||||
|
for /f "tokens=*" %%A in ('certutil -hashfile "%oldDllPath%" MD5') do (
|
||||||
|
if not defined oldDllHash set oldDllHash=%%A
|
||||||
|
)
|
||||||
|
for /f "tokens=*" %%A in ('certutil -hashfile "%newDllPath%" MD5') do (
|
||||||
|
if not defined newDllHash set newDllHash=%%A
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 如果文件一致则跳过
|
||||||
|
if "%oldDllHash%" neq "%newDllHash%" (
|
||||||
|
tasklist /fi "imagename eq QQ.exe" 2>nul | find /i "QQ.exe" >nul
|
||||||
|
if %errorlevel% equ 0 (
|
||||||
|
REM 文件占用则退出
|
||||||
|
echo dbghelp.dll is in use, cannot continue.
|
||||||
|
) else (
|
||||||
|
REM 文件未占用则尝试覆盖
|
||||||
|
copy /y "%newDllPath%" "%oldDllPath%"
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo Failed to copy dbghelp.dll
|
||||||
|
pause
|
||||||
|
exit /b
|
||||||
|
) else (
|
||||||
|
echo dbghelp.dll has been copied to %QQdir%
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 带参数启动QQ
|
||||||
|
REM 判断wt是否存在,存在则通过wt启动,不存在则通过cmd启动
|
||||||
|
REM %QQPath% --enable-logging %*
|
||||||
|
where wt >nul 2>nul
|
||||||
|
if %errorlevel% equ 0 (
|
||||||
|
wt "cmd" /c "%QQPath%" --enable-logging %*
|
||||||
|
) else (
|
||||||
|
"%QQPath%" --enable-logging %*
|
||||||
|
)
|
93
script/BootWay05.utf8.bat
Normal file
93
script/BootWay05.utf8.bat
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
@echo off
|
||||||
|
REM 检查当前会话是否具有管理员权限
|
||||||
|
openfiles >nul 2>&1
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
REM 如果不是管理员,则重新启动脚本以管理员模式运行
|
||||||
|
echo 请求管理员权限...
|
||||||
|
where wt >nul 2>nul
|
||||||
|
if %errorlevel% equ 0 (
|
||||||
|
powershell -Command "Start-Process cmd -ArgumentList ' /c %~f0 %*' -Verb RunAs"
|
||||||
|
) else (
|
||||||
|
powershell -Command "Start-Process wt -ArgumentList 'cmd /c %~f0 %*' -Verb RunAs"
|
||||||
|
)
|
||||||
|
|
||||||
|
REM wt "cmd" /c "%~f0 %*"
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 设置当前工作目录
|
||||||
|
cd /d %~dp0
|
||||||
|
|
||||||
|
REM 获取当前目录路径
|
||||||
|
set currentPath=%cd%
|
||||||
|
set currentPath=%currentPath:\=/%
|
||||||
|
|
||||||
|
REM 生成JavaScript代码
|
||||||
|
set "jsCode=(async () =^>await import('file:///%currentPath%/napcat.mjs'))();"
|
||||||
|
|
||||||
|
REM 将JavaScript代码保存到文件中
|
||||||
|
echo %jsCode% > loadScript.js
|
||||||
|
echo JavaScript code has been generated and saved to loadScript.js
|
||||||
|
|
||||||
|
REM 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址
|
||||||
|
set NAPCAT_PATH=%cd%\loadScript.js
|
||||||
|
|
||||||
|
REM 获取QQ路径
|
||||||
|
|
||||||
|
|
||||||
|
:loop_read
|
||||||
|
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
|
||||||
|
set RetString=%%b
|
||||||
|
goto :napcat_boot
|
||||||
|
)
|
||||||
|
|
||||||
|
:napcat_boot
|
||||||
|
for %%a in (%RetString%) do (
|
||||||
|
set "pathWithoutUninstall=%%~dpa"
|
||||||
|
)
|
||||||
|
|
||||||
|
SET QQPath=%pathWithoutUninstall%QQ.exe
|
||||||
|
|
||||||
|
REM 拿不到QQ路径则退出
|
||||||
|
if not exist "%QQpath%" (
|
||||||
|
echo provided QQ path is invalid: %QQpath%
|
||||||
|
pause
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 收集dbghelp.dll路径和HASH信息
|
||||||
|
set QQdir=%~dp0
|
||||||
|
set oldDllPath=%QQdir%dbghelp.dll
|
||||||
|
set newDllPath=%currentPath%\dbghelp.dll
|
||||||
|
|
||||||
|
for /f "tokens=*" %%A in ('certutil -hashfile "%oldDllPath%" MD5') do (
|
||||||
|
if not defined oldDllHash set oldDllHash=%%A
|
||||||
|
)
|
||||||
|
for /f "tokens=*" %%A in ('certutil -hashfile "%newDllPath%" MD5') do (
|
||||||
|
if not defined newDllHash set newDllHash=%%A
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 如果文件一致则跳过
|
||||||
|
if "%oldDllHash%" neq "%newDllHash%" (
|
||||||
|
tasklist /fi "imagename eq QQ.exe" 2>nul | find /i "QQ.exe" >nul
|
||||||
|
if %errorlevel% equ 0 (
|
||||||
|
REM 文件占用则退出
|
||||||
|
echo dbghelp.dll is in use, cannot continue.
|
||||||
|
) else (
|
||||||
|
REM 文件未占用则尝试覆盖
|
||||||
|
copy /y "%newDllPath%" "%oldDllPath%"
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo Failed to copy dbghelp.dll
|
||||||
|
pause
|
||||||
|
exit /b
|
||||||
|
) else (
|
||||||
|
echo dbghelp.dll has been copied to %QQdir%
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
REM 带参数启动QQ
|
||||||
|
REM 判断wt是否存在,存在则通过wt启动,不存在则通过cmd启动
|
||||||
|
REM %QQPath% --enable-logging %*
|
||||||
|
chcp 65001
|
||||||
|
"%QQPath%" --enable-logging %*
|
@@ -1,6 +1,6 @@
|
|||||||
// --------------------
|
// --------------------
|
||||||
// 2024.7.3 9.9.12 BootWay.03 其余方法暂不公开(此方案为临时方案 Win平台已验证)
|
// 2024.7.3 9.9.12 BootWay.03 其余方法暂不公开(此方案为临时方案 Win平台已验证)
|
||||||
// 缺陷 (已知)
|
|
||||||
// 1.与非入侵式不同 现在破坏本体代码
|
// 1.与非入侵式不同 现在破坏本体代码
|
||||||
// 2.重启代码与正常启动代码失效
|
// 2.重启代码与正常启动代码失效
|
||||||
// 3.Win需要补丁
|
// 3.Win需要补丁
|
||||||
|
@@ -86,7 +86,7 @@ export abstract class HttpServerBase {
|
|||||||
this.start(port, host);
|
this.start(port, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract handleFailed(res: Response, payload: any, err: any): void
|
abstract handleFailed(res: Response, payload: any, err: Error): void
|
||||||
|
|
||||||
registerRouter(method: 'post' | 'get' | string, url: string, handler: RegisterHandler) {
|
registerRouter(method: 'post' | 'get' | string, url: string, handler: RegisterHandler) {
|
||||||
if (!url.startsWith('/')) {
|
if (!url.startsWith('/')) {
|
||||||
@@ -111,7 +111,7 @@ export abstract class HttpServerBase {
|
|||||||
try {
|
try {
|
||||||
res.send(await handler(res, payload));
|
res.send(await handler(res, payload));
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.handleFailed(res, payload, e.stack.toString());
|
this.handleFailed(res, payload, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -84,7 +84,7 @@ export class NTEventWrapper {
|
|||||||
}
|
}
|
||||||
//统一回调清理事件
|
//统一回调清理事件
|
||||||
async DispatcherListener(ListenerMainName: string, ListenerSubName: string, ...args: any[]) {
|
async DispatcherListener(ListenerMainName: string, ListenerSubName: string, ...args: any[]) {
|
||||||
//console.log(ListenerMainName, ListenerSubName, ...args,this.EventTask.get(ListenerMainName)?.get(ListenerSubName));
|
//console.log("[EventDispatcher]",ListenerMainName, ListenerSubName, ...args);
|
||||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.forEach((task, uuid) => {
|
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.forEach((task, uuid) => {
|
||||||
//console.log(task.func, uuid, task.createtime, task.timeout);
|
//console.log(task.func, uuid, task.createtime, task.timeout);
|
||||||
if (task.createtime + task.timeout < Date.now()) {
|
if (task.createtime + task.timeout < Date.now()) {
|
||||||
@@ -150,7 +150,7 @@ export class NTEventWrapper {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async CallNormalEvent<EventType extends (...args: any[]) => Promise<any>, ListenerType extends (...args: any[]) => void>
|
async CallNormalEvent<EventType extends (...args: any[]) => Promise<any>, ListenerType extends (...args: any[]) => void>
|
||||||
(EventName = '', ListenerName = '', waitTimes = 1, timeout: number = 3000, checker: (...args: Parameters<ListenerType>) => boolean, ...args: Parameters<EventType>) {
|
(EventName = '', ListenerName = '', waitTimes = 1, timeout: number = 3000, checker: (...args: Parameters<ListenerType>) => boolean, ...args: Parameters<EventType>) {
|
||||||
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(async (resolve, reject) => {
|
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(async (resolve, reject) => {
|
||||||
const id = randomUUID();
|
const id = randomUUID();
|
||||||
let complete = 0;
|
let complete = 0;
|
||||||
|
@@ -2,7 +2,7 @@ import { Peer } from '@/core';
|
|||||||
import crypto, { randomInt, randomUUID } from 'crypto';
|
import crypto, { randomInt, randomUUID } from 'crypto';
|
||||||
import { logError } from './log';
|
import { logError } from './log';
|
||||||
|
|
||||||
class LimitedHashTable<K, V> {
|
export class LimitedHashTable<K, V> {
|
||||||
private keyToValue: Map<K, V> = new Map();
|
private keyToValue: Map<K, V> = new Map();
|
||||||
private valueToKey: Map<V, K> = new Map();
|
private valueToKey: Map<V, K> = new Map();
|
||||||
private maxSize: number;
|
private maxSize: number;
|
||||||
@@ -99,8 +99,10 @@ class MessageUniqueWrapper {
|
|||||||
}
|
}
|
||||||
createMsg(peer: Peer, msgId: string): number | undefined {
|
createMsg(peer: Peer, msgId: string): number | undefined {
|
||||||
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
||||||
const hash = crypto.createHash('md5').update(key);
|
const hash = crypto.createHash('md5').update(key).digest();
|
||||||
const shortId = hash.digest().readInt32BE(0);
|
//设置第一个bit为0 保证shortId为正数
|
||||||
|
hash[0] &= 0x7f;
|
||||||
|
const shortId = hash.readInt32BE(0);
|
||||||
//减少性能损耗
|
//减少性能损耗
|
||||||
// const isExist = this.msgIdMap.getKey(shortId);
|
// const isExist = this.msgIdMap.getKey(shortId);
|
||||||
// if (isExist && isExist === msgId) {
|
// if (isExist && isExist === msgId) {
|
||||||
|
@@ -1,62 +1,50 @@
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import os from 'node:os';
|
|
||||||
import { systemPlatform } from '@/common/utils/system';
|
import { systemPlatform } from '@/common/utils/system';
|
||||||
import { logError } from '@/common/utils/log';
|
import { getDefaultQQVersionConfigInfo, getQQVersionConfigPath } from './helper';
|
||||||
|
import AppidTable from '@/core/external/appid.json';
|
||||||
|
import { log } from './log';
|
||||||
|
|
||||||
export const exePath = process.execPath;
|
//基础目录获取
|
||||||
|
export const QQMainPath = process.execPath;
|
||||||
|
export const QQPackageInfoPath: string = path.join(path.dirname(QQMainPath), 'resources', 'app', 'package.json');
|
||||||
|
export const QQVersionConfigPath: string | undefined = getQQVersionConfigPath(QQMainPath);
|
||||||
|
|
||||||
export const pkgInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'package.json');
|
//基础信息获取 无快更则启用默认模板填充
|
||||||
let configVersionInfoPath;
|
export const isQuickUpdate: boolean = !!QQVersionConfigPath;
|
||||||
|
export const QQVersionConfig: QQVersionConfigType = isQuickUpdate ? JSON.parse(fs.readFileSync(QQVersionConfigPath!).toString()) : getDefaultQQVersionConfigInfo();
|
||||||
|
export const QQPackageInfo: QQPackageInfoType = JSON.parse(fs.readFileSync(QQPackageInfoPath).toString());
|
||||||
|
export const { appid: QQVersionAppid, qua: QQVersionQua } = getAppidV2();
|
||||||
|
|
||||||
if (os.platform() !== 'linux') {
|
//基础函数
|
||||||
configVersionInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'versions', 'config.json');
|
export function getQQBuildStr() {
|
||||||
} else {
|
return isQuickUpdate ? QQVersionConfig.buildId : QQPackageInfo.buildVersion;
|
||||||
const userPath = os.homedir();
|
|
||||||
const appDataPath = path.resolve(userPath, './.config/QQ');
|
|
||||||
configVersionInfoPath = path.resolve(appDataPath, './versions/config.json');
|
|
||||||
}
|
}
|
||||||
|
export function getFullQQVesion() {
|
||||||
if (typeof configVersionInfoPath !== 'string') {
|
return isQuickUpdate ? QQVersionConfig.curVersion : QQPackageInfo.version;
|
||||||
throw new Error('Something went wrong when load QQ info path');
|
|
||||||
}
|
}
|
||||||
|
export function requireMinNTQQBuild(buildStr: string) {
|
||||||
export { configVersionInfoPath };
|
return parseInt(getQQBuildStr()) >= parseInt(buildStr);
|
||||||
|
|
||||||
type QQPkgInfo = {
|
|
||||||
version: string;
|
|
||||||
buildVersion: string;
|
|
||||||
platform: string;
|
|
||||||
eleArch: string;
|
|
||||||
}
|
}
|
||||||
type QQVersionConfigInfo = {
|
//此方法不要直接使用
|
||||||
baseVersion: string;
|
export function getQUAInternal() {
|
||||||
curVersion: string;
|
return systemPlatform === 'linux' ? `V1_LNX_NQ_${getFullQQVesion()}_${getQQBuildStr()}_GW_B` : `V1_WIN_NQ_${getFullQQVesion()}_${getQQBuildStr()}_GW_B`;
|
||||||
prevVersion: string;
|
|
||||||
onErrorVersions: Array<any>;
|
|
||||||
buildId: string;
|
|
||||||
}
|
}
|
||||||
|
export function getAppidV2(): { appid: string, qua: string } {
|
||||||
let _qqVersionConfigInfo: QQVersionConfigInfo = {
|
const appidTbale = AppidTable as unknown as QQAppidTableType;
|
||||||
'baseVersion': '9.9.12-25765',
|
|
||||||
'curVersion': '9.9.12-25765',
|
|
||||||
'prevVersion': '',
|
|
||||||
'onErrorVersions': [],
|
|
||||||
'buildId': '25765'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (fs.existsSync(configVersionInfoPath)) {
|
|
||||||
try {
|
try {
|
||||||
const _ =JSON.parse(fs.readFileSync(configVersionInfoPath).toString());
|
const data = appidTbale[getFullQQVesion()];
|
||||||
_qqVersionConfigInfo = Object.assign(_qqVersionConfigInfo, _);
|
if (data) {
|
||||||
} catch (e) {
|
return data;
|
||||||
logError('Load QQ version config info failed, Use default version', e);
|
}
|
||||||
}
|
}
|
||||||
|
catch (e) {
|
||||||
|
log('[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常');
|
||||||
|
}
|
||||||
|
// 以下是兜底措施
|
||||||
|
log(`[QQ版本兼容性检测] ${getFullQQVesion()} 版本兼容性不佳,可能会导致一些功能无法正常使用`);
|
||||||
|
return { appid: systemPlatform === 'linux' ? '537237950' : '537237765', qua: getQUAInternal() };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const qqVersionConfigInfo: QQVersionConfigInfo = _qqVersionConfigInfo;
|
|
||||||
//V1_WIN_NQ_9.9.12_25765_GW_B
|
|
||||||
export const qqPkgInfo: QQPkgInfo = JSON.parse(fs.readFileSync(pkgInfoPath).toString());
|
|
||||||
// platform_type: 3,
|
// platform_type: 3,
|
||||||
// app_type: 4,
|
// app_type: 4,
|
||||||
// app_version: '9.9.12-25765',
|
// app_version: '9.9.12-25765',
|
||||||
@@ -64,14 +52,6 @@ export const qqPkgInfo: QQPkgInfo = JSON.parse(fs.readFileSync(pkgInfoPath).toSt
|
|||||||
// appid: '537234702',
|
// appid: '537234702',
|
||||||
// platVer: '10.0.26100',
|
// platVer: '10.0.26100',
|
||||||
// clientVer: '9.9.9-25765',
|
// clientVer: '9.9.9-25765',
|
||||||
|
|
||||||
// Linux
|
// Linux
|
||||||
// app_version: '3.2.9-25765',
|
// app_version: '3.2.9-25765',
|
||||||
// qua: 'V1_LNX_NQ_3.2.10_25765_GW_B',
|
// qua: 'V1_LNX_NQ_3.2.10_25765_GW_B',
|
||||||
|
|
||||||
let _appid: string = '537234702'; // 默认为 Windows 平台的 appid
|
|
||||||
if (systemPlatform === 'linux') {
|
|
||||||
_appid = '537234773';
|
|
||||||
}
|
|
||||||
// todo: mac 平台的 appid
|
|
||||||
export const appid = _appid;
|
|
@@ -181,7 +181,7 @@ type Uri2LocalRes = {
|
|||||||
isLocal: boolean
|
isLocal: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function uri2local(uri: string, fileName: string | null = null): Promise<Uri2LocalRes> {
|
export async function uri2local(UriOrPath: string, fileName: string | null = null): Promise<Uri2LocalRes> {
|
||||||
const res = {
|
const res = {
|
||||||
success: false,
|
success: false,
|
||||||
errMsg: '',
|
errMsg: '',
|
||||||
@@ -190,26 +190,29 @@ export async function uri2local(uri: string, fileName: string | null = null): Pr
|
|||||||
path: '',
|
path: '',
|
||||||
isLocal: false
|
isLocal: false
|
||||||
};
|
};
|
||||||
if (!fileName) {
|
if (!fileName) fileName = randomUUID();
|
||||||
fileName = randomUUID();
|
let filePath = path.join(getTempDir(), fileName);//临时目录
|
||||||
}
|
|
||||||
let filePath = path.join(getTempDir(), fileName);
|
|
||||||
let url = null;
|
let url = null;
|
||||||
|
//区分path和uri
|
||||||
try {
|
try {
|
||||||
url = new URL(uri);
|
if (fs.existsSync(UriOrPath)) url = new URL('file://' + UriOrPath);
|
||||||
} catch (e: any) {
|
} catch (error: any) { }
|
||||||
res.errMsg = `uri ${uri} 解析失败,` + e.toString() + ` 可能${uri}不存在`;
|
try {
|
||||||
|
url = new URL(UriOrPath);
|
||||||
|
} catch (error: any) { }
|
||||||
|
|
||||||
|
//验证url
|
||||||
|
if (!url) {
|
||||||
|
res.errMsg = `UriOrPath ${UriOrPath} 解析失败,可能${UriOrPath}不存在`;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// log("uri protocol", url.protocol, uri);
|
|
||||||
if (url.protocol == 'base64:') {
|
if (url.protocol == 'base64:') {
|
||||||
// base64转成文件
|
// base64转成文件
|
||||||
const base64Data = uri.split('base64://')[1];
|
const base64Data = UriOrPath.split('base64://')[1];
|
||||||
try {
|
try {
|
||||||
const buffer = Buffer.from(base64Data, 'base64');
|
const buffer = Buffer.from(base64Data, 'base64');
|
||||||
fs.writeFileSync(filePath, buffer);
|
fs.writeFileSync(filePath, buffer);
|
||||||
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
res.errMsg = 'base64文件下载失败,' + e.toString();
|
res.errMsg = 'base64文件下载失败,' + e.toString();
|
||||||
return res;
|
return res;
|
||||||
@@ -218,7 +221,7 @@ export async function uri2local(uri: string, fileName: string | null = null): Pr
|
|||||||
// 下载文件
|
// 下载文件
|
||||||
let buffer: Buffer | null = null;
|
let buffer: Buffer | null = null;
|
||||||
try {
|
try {
|
||||||
buffer = await httpDownload(uri);
|
buffer = await httpDownload(UriOrPath);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
res.errMsg = `${url}下载失败,` + e.toString();
|
res.errMsg = `${url}下载失败,` + e.toString();
|
||||||
return res;
|
return res;
|
||||||
@@ -252,6 +255,7 @@ export async function uri2local(uri: string, fileName: string | null = null): Pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// 26702执行forword file文件操作 不应该在这里乱来
|
||||||
// const cache = await dbUtil.getFileCacheByName(uri);
|
// const cache = await dbUtil.getFileCacheByName(uri);
|
||||||
// if (cache) {
|
// if (cache) {
|
||||||
// filePath = cache.path;
|
// filePath = cache.path;
|
||||||
@@ -259,7 +263,6 @@ export async function uri2local(uri: string, fileName: string | null = null): Pr
|
|||||||
// filePath = uri;
|
// filePath = uri;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
res.isLocal = true;
|
res.isLocal = true;
|
||||||
}
|
}
|
||||||
// else{
|
// else{
|
||||||
|
@@ -1,13 +1,35 @@
|
|||||||
import crypto from 'node:crypto';
|
import crypto from 'node:crypto';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs';
|
||||||
import { log, logDebug } from './log';
|
import { log, logDebug } from './log';
|
||||||
import { dirname } from 'node:path';
|
import { dirname } from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import * as fsPromise from 'node:fs/promises';
|
import * as fsPromise from 'node:fs/promises';
|
||||||
|
import os from 'node:os';
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
//下面这个类是用于将uid+msgid合并的类
|
||||||
|
export class UUIDConverter {
|
||||||
|
static encode(highStr: string, lowStr: string): string {
|
||||||
|
const high = BigInt(highStr);
|
||||||
|
const low = BigInt(lowStr);
|
||||||
|
const highHex = high.toString(16).padStart(16, '0');
|
||||||
|
const lowHex = low.toString(16).padStart(16, '0');
|
||||||
|
const combinedHex = highHex + lowHex;
|
||||||
|
const uuid = `${combinedHex.substring(0, 8)}-${combinedHex.substring(8, 12)}-${combinedHex.substring(12, 16)}-${combinedHex.substring(16, 20)}-${combinedHex.substring(20)}`;
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
static decode(uuid: string): { high: string, low: string } {
|
||||||
|
const hex = uuid.replace(/-/g, '');
|
||||||
|
const high = BigInt('0x' + hex.substring(0, 16));
|
||||||
|
const low = BigInt('0x' + hex.substring(16));
|
||||||
|
return { high: high.toString(), low: low.toString() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function sleep(ms: number): Promise<void> {
|
export function sleep(ms: number): Promise<void> {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
@@ -283,14 +305,14 @@ export function migrateConfig(oldConfig: any) {
|
|||||||
}
|
}
|
||||||
// 升级旧的配置到新的
|
// 升级旧的配置到新的
|
||||||
export async function UpdateConfig() {
|
export async function UpdateConfig() {
|
||||||
const configFiles = await fs.readdir(path.join(__dirname, 'config'));
|
const configFiles = await fsPromise.readdir(path.join(__dirname, 'config'));
|
||||||
for (const file of configFiles) {
|
for (const file of configFiles) {
|
||||||
if (file.match(/^onebot11_\d+.json$/)) {
|
if (file.match(/^onebot11_\d+.json$/)) {
|
||||||
const CurrentConfig = JSON.parse(await fs.readFile(path.join(__dirname, 'config', file), 'utf8'));
|
const CurrentConfig = JSON.parse(await fsPromise.readFile(path.join(__dirname, 'config', file), 'utf8'));
|
||||||
if (isValidOldConfig(CurrentConfig)) {
|
if (isValidOldConfig(CurrentConfig)) {
|
||||||
log('正在迁移旧配置到新配置 File:', file);
|
log('正在迁移旧配置到新配置 File:', file);
|
||||||
const NewConfig = migrateConfig(CurrentConfig);
|
const NewConfig = migrateConfig(CurrentConfig);
|
||||||
await fs.writeFile(path.join(__dirname, 'config', file), JSON.stringify(NewConfig, null, 2));
|
await fsPromise.writeFile(path.join(__dirname, 'config', file), JSON.stringify(NewConfig, null, 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,7 +332,56 @@ export function isEqual(obj1: any, obj2: any) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
||||||
|
if (os.platform() === 'linux') {
|
||||||
|
return {
|
||||||
|
baseVersion: '3.2.12-26702',
|
||||||
|
curVersion: '3.2.12-26702',
|
||||||
|
prevVersion: '',
|
||||||
|
onErrorVersions: [],
|
||||||
|
buildId: '26702'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
baseVersion: '9.9.15-26702',
|
||||||
|
curVersion: '9.9.15-26702',
|
||||||
|
prevVersion: '',
|
||||||
|
onErrorVersions: [],
|
||||||
|
buildId: '26702'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export async function promisePipeline(promises: Promise<any>[], callback: (result: any) => boolean): Promise<void> {
|
||||||
|
let callbackCalled = false;
|
||||||
|
for (const promise of promises) {
|
||||||
|
if (callbackCalled) break;
|
||||||
|
try {
|
||||||
|
const result = await promise;
|
||||||
|
if (!callbackCalled) {
|
||||||
|
callbackCalled = callback(result);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error in promise pipeline:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getQQVersionConfigPath(exePath: string = ''): string | undefined {
|
||||||
|
let configVersionInfoPath;
|
||||||
|
if (os.platform() !== 'linux') {
|
||||||
|
configVersionInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'versions', 'config.json');
|
||||||
|
} else {
|
||||||
|
const userPath = os.homedir();
|
||||||
|
const appDataPath = path.resolve(userPath, './.config/QQ');
|
||||||
|
configVersionInfoPath = path.resolve(appDataPath, './versions/config.json');
|
||||||
|
}
|
||||||
|
if (typeof configVersionInfoPath !== 'string') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(configVersionInfoPath)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return configVersionInfoPath;
|
||||||
|
}
|
||||||
export async function deleteOldFiles(directoryPath: string, daysThreshold: number) {
|
export async function deleteOldFiles(directoryPath: string, daysThreshold: number) {
|
||||||
try {
|
try {
|
||||||
const files = await fsPromise.readdir(directoryPath);
|
const files = await fsPromise.readdir(directoryPath);
|
||||||
|
@@ -1,31 +1,17 @@
|
|||||||
/**
|
//QQVersionType
|
||||||
* 运行时类型转换与检查类
|
type QQPackageInfoType = {
|
||||||
*/
|
version: string;
|
||||||
export class TypeCheck {
|
buildVersion: string;
|
||||||
static isEmpty(value: any): boolean {
|
platform: string;
|
||||||
return value === null || value === undefined || value === '' ||
|
eleArch: string;
|
||||||
(Array.isArray(value) && value.length === 0) || (typeof value === 'object' && Object.keys(value).length === 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
type QQVersionConfigType = {
|
||||||
export class TypeConvert {
|
baseVersion: string;
|
||||||
static toNumber(value: any): number {
|
curVersion: string;
|
||||||
const num = Number(value);
|
prevVersion: string;
|
||||||
if (isNaN(num)) {
|
onErrorVersions: Array<any>;
|
||||||
throw new Error(`无法将输入转换为数字: ${value}`);
|
buildId: string;
|
||||||
}
|
}
|
||||||
return num;
|
type QQAppidTableType = {
|
||||||
}
|
[key: string]: { appid: string, qua: string };
|
||||||
|
|
||||||
static toString(value: any): string {
|
|
||||||
return String(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static toBoolean(value: any): boolean {
|
|
||||||
return Boolean(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static toArray(value: any): any[] {
|
|
||||||
return Array.isArray(value) ? value : [value];
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -4,10 +4,10 @@ export async function checkVersion(): Promise<string> {
|
|||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
const MirrorList =
|
const MirrorList =
|
||||||
[
|
[
|
||||||
|
'https://jsd.cdn.zzko.cn/gh/NapNeko/NapCatQQ@main/package.json',
|
||||||
'https://fastly.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json',
|
'https://fastly.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json',
|
||||||
'https://gcore.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json',
|
'https://gcore.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json',
|
||||||
'https://cdn.jsdelivr.us/gh/NapNeko/NapCatQQ@main/package.json',
|
'https://cdn.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json'
|
||||||
'https://jsd.cdn.zzko.cn/gh/NapNeko/NapCatQQ@main/package.json'
|
|
||||||
];
|
];
|
||||||
let version = undefined;
|
let version = undefined;
|
||||||
for (const url of MirrorList) {
|
for (const url of MirrorList) {
|
||||||
|
@@ -18,6 +18,7 @@ import { sessionConfig } from '@/core/sessionConfig';
|
|||||||
import { rkeyManager } from '../utils/rkey';
|
import { rkeyManager } from '../utils/rkey';
|
||||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||||
import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService';
|
import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService';
|
||||||
|
import { selfInfo } from '../data';
|
||||||
|
|
||||||
|
|
||||||
export class NTQQFileApi {
|
export class NTQQFileApi {
|
||||||
@@ -67,7 +68,9 @@ export class NTQQFileApi {
|
|||||||
ext
|
ext
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
static async downloadMediaByUuid() {
|
||||||
|
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
|
||||||
|
}
|
||||||
static async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
static async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
||||||
//logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
|
//logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
|
||||||
// 用于下载收到的消息中的图片等
|
// 用于下载收到的消息中的图片等
|
||||||
|
@@ -1,11 +1,66 @@
|
|||||||
import { FriendRequest, User } from '@/core/entities';
|
import { FriendRequest, FriendV2, SimpleInfo, User } from '@/core/entities';
|
||||||
import { napCatCore, OnBuddyChangeParams } from '@/core';
|
import { BuddyListReqType, napCatCore, NodeIKernelBuddyListener, NodeIKernelProfileService, OnBuddyChangeParams } from '@/core';
|
||||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||||
|
import { LimitedHashTable } from '@/common/utils/MessageUnique';
|
||||||
|
import { CacheClassFuncAsyncExtend } from '@/common/utils/helper';
|
||||||
export class NTQQFriendApi {
|
export class NTQQFriendApi {
|
||||||
|
static async getBuddyV2(refresh = false): Promise<FriendV2[]> {
|
||||||
|
let uids: string[] = [];
|
||||||
|
const buddyService = napCatCore.session.getBuddyService();
|
||||||
|
const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
|
||||||
|
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids));
|
||||||
|
const data = await NTEventDispatch.CallNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
||||||
|
'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids
|
||||||
|
);
|
||||||
|
return Array.from(data.values());
|
||||||
|
}
|
||||||
|
@CacheClassFuncAsyncExtend(3600 * 1000, 'getBuddyIdMap', () => true)
|
||||||
|
static async getBuddyIdMapCache(refresh = false): Promise<LimitedHashTable<string, string>> {
|
||||||
|
return await NTQQFriendApi.getBuddyIdMap(refresh);
|
||||||
|
}
|
||||||
|
static async getBuddyIdMap(refresh = false): Promise<LimitedHashTable<string, string>> {
|
||||||
|
let uids: string[] = [];
|
||||||
|
let retMap: LimitedHashTable<string, string> = new LimitedHashTable<string, string>(5000);
|
||||||
|
const buddyService = napCatCore.session.getBuddyService();
|
||||||
|
const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
|
||||||
|
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids));
|
||||||
|
const data = await NTEventDispatch.CallNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
||||||
|
'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids
|
||||||
|
);
|
||||||
|
data.forEach((value, key) => {
|
||||||
|
retMap.set(value.uin!, value.uid!);
|
||||||
|
});
|
||||||
|
//console.log('getBuddyIdMap', retMap.getValue);
|
||||||
|
return retMap;
|
||||||
|
}
|
||||||
|
static async getBuddyV2ExWithCate(refresh = false) {
|
||||||
|
let uids: string[] = [];
|
||||||
|
let categoryMap: Map<string, any> = new Map();
|
||||||
|
const buddyService = napCatCore.session.getBuddyService();
|
||||||
|
const buddyListV2 = refresh ? (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data : (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data;
|
||||||
|
uids.push(
|
||||||
|
...buddyListV2.flatMap(item => {
|
||||||
|
item.buddyUids.forEach(uid => {
|
||||||
|
categoryMap.set(uid, { categoryId: item.categoryId, categroyName: item.categroyName });
|
||||||
|
});
|
||||||
|
return item.buddyUids
|
||||||
|
}));
|
||||||
|
const data = await NTEventDispatch.CallNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
||||||
|
'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids
|
||||||
|
);
|
||||||
|
return Array.from(data).map(([key, value]) => {
|
||||||
|
const category = categoryMap.get(key);
|
||||||
|
return category ? { ...value, categoryId: category.categoryId, categroyName: category.categroyName } : value;
|
||||||
|
});
|
||||||
|
}
|
||||||
static async isBuddy(uid: string) {
|
static async isBuddy(uid: string) {
|
||||||
return napCatCore.session.getBuddyService().isBuddy(uid);
|
return napCatCore.session.getBuddyService().isBuddy(uid);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* @param forced
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
static async getFriends(forced = false): Promise<User[]> {
|
static async getFriends(forced = false): Promise<User[]> {
|
||||||
let [_retData, _BuddyArg] = await NTEventDispatch.CallNormalEvent
|
let [_retData, _BuddyArg] = await NTEventDispatch.CallNormalEvent
|
||||||
<(force: boolean) => Promise<any>, (arg: OnBuddyChangeParams) => void>
|
<(force: boolean) => Promise<any>, (arg: OnBuddyChangeParams) => void>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { GroupMember, GroupRequestOperateTypes, GroupMemberRole, GroupNotify, Group, MemberExtSourceType, GroupNotifyTypes, ChatType, Peer } from '../entities';
|
import { GroupMember, GroupRequestOperateTypes, GroupMemberRole, GroupNotify, Group, MemberExtSourceType, GroupNotifyTypes, ChatType, Peer, GroupListUpdateType } from '../entities';
|
||||||
import { GeneralCallResult, NTQQUserApi, napCatCore } from '@/core';
|
import { GeneralCallResult, NTQQUserApi, NodeIKernelGroupListener, NodeIKernelGroupService, napCatCore } from '@/core';
|
||||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||||
import { log } from '@/common/utils/log';
|
import { log } from '@/common/utils/log';
|
||||||
import { groupMembers } from '../data';
|
import { groupMembers } from '../data';
|
||||||
@@ -9,20 +9,21 @@ export class NTQQGroupApi {
|
|||||||
return napCatCore.session.getGroupService().setHeader(gc, filePath);
|
return napCatCore.session.getGroupService().setHeader(gc, filePath);
|
||||||
}
|
}
|
||||||
static async getGroups(forced = false) {
|
static async getGroups(forced = false) {
|
||||||
|
type ListenerType = NodeIKernelGroupListener['onGroupListUpdate'];
|
||||||
let [_retData, _updateType, groupList] = await NTEventDispatch.CallNormalEvent
|
let [_retData, _updateType, groupList] = await NTEventDispatch.CallNormalEvent
|
||||||
<(force: boolean) => Promise<any>, (updateType: number, groupList: Group[]) => void>
|
<(force: boolean) => Promise<any>, ListenerType>
|
||||||
(
|
(
|
||||||
'NodeIKernelGroupService/getGroupList',
|
'NodeIKernelGroupService/getGroupList',
|
||||||
'NodeIKernelGroupListener/onGroupListUpdate',
|
'NodeIKernelGroupListener/onGroupListUpdate',
|
||||||
1,
|
1,
|
||||||
5000,
|
5000,
|
||||||
() => true,
|
(updateType) => true,
|
||||||
forced
|
forced
|
||||||
);
|
);
|
||||||
return groupList;
|
return groupList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CacheClassFuncAsyncExtend(600, "LastestSendTime", () => true)
|
@CacheClassFuncAsyncExtend(3600 * 1000, "LastestSendTime", () => true)
|
||||||
static async getGroupMemberLastestSendTimeCache(GroupCode: string) {
|
static async getGroupMemberLastestSendTimeCache(GroupCode: string) {
|
||||||
return NTQQGroupApi.getGroupMemberLastestSendTime(GroupCode);
|
return NTQQGroupApi.getGroupMemberLastestSendTime(GroupCode);
|
||||||
}
|
}
|
||||||
@@ -80,6 +81,9 @@ export class NTQQGroupApi {
|
|||||||
});
|
});
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
static async getGroupMemberAll(GroupCode: string, forced = false) {
|
||||||
|
return napCatCore.session.getGroupService().getAllMemberList(GroupCode, forced);
|
||||||
|
}
|
||||||
static async getLastestMsg(GroupCode: string, uins: string[]) {
|
static async getLastestMsg(GroupCode: string, uins: string[]) {
|
||||||
let uids: Array<string> = [];
|
let uids: Array<string> = [];
|
||||||
for (let uin of uins) {
|
for (let uin of uins) {
|
||||||
@@ -154,6 +158,25 @@ export class NTQQGroupApi {
|
|||||||
);
|
);
|
||||||
return notifies;
|
return notifies;
|
||||||
}
|
}
|
||||||
|
static async getGroupMemberV2(GroupCode: string, uid: string, forced = false) {
|
||||||
|
type ListenerType = NodeIKernelGroupListener['onMemberInfoChange'];
|
||||||
|
type EventType = NodeIKernelGroupService['getMemberInfo'];
|
||||||
|
// NTEventDispatch.CreatListenerFunction('NodeIKernelGroupListener/onGroupMemberInfoUpdate',
|
||||||
|
//return napCatCore.session.getGroupService().getMemberInfo(GroupCode, [uid], forced);
|
||||||
|
const [ret, _groupCode, _changeType, _members] = await NTEventDispatch.CallNormalEvent
|
||||||
|
<EventType, ListenerType>
|
||||||
|
(
|
||||||
|
'NodeIKernelGroupService/getMemberInfo',
|
||||||
|
'NodeIKernelGroupListener/onMemberInfoChange',
|
||||||
|
1,
|
||||||
|
5000,
|
||||||
|
(groupCode: string, changeType: number, members: Map<string, GroupMember>) => {
|
||||||
|
return groupCode == GroupCode && members.has(uid);
|
||||||
|
},
|
||||||
|
GroupCode, [uid], forced
|
||||||
|
);
|
||||||
|
return _members.get(uid);
|
||||||
|
}
|
||||||
static async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
static async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
||||||
const groupService = napCatCore.session.getGroupService();
|
const groupService = napCatCore.session.getGroupService();
|
||||||
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
||||||
@@ -161,6 +184,7 @@ export class NTQQGroupApi {
|
|||||||
if (result.errCode !== 0) {
|
if (result.errCode !== 0) {
|
||||||
throw ('获取群成员列表出错,' + result.errMsg);
|
throw ('获取群成员列表出错,' + result.errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//logDebug(`获取群(${groupQQ})成员列表结果:`, `finish: ${result.result.finish}`); //, Array.from(result.result.infos.values()));
|
//logDebug(`获取群(${groupQQ})成员列表结果:`, `finish: ${result.result.finish}`); //, Array.from(result.result.infos.values()));
|
||||||
return result.result.infos;
|
return result.result.infos;
|
||||||
/*
|
/*
|
||||||
@@ -196,7 +220,7 @@ export class NTQQGroupApi {
|
|||||||
const _Pskey = (await NTQQUserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
const _Pskey = (await NTQQUserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
||||||
return napCatCore.session.getGroupService().uploadGroupBulletinPic(GroupCode, _Pskey, imageurl);
|
return napCatCore.session.getGroupService().uploadGroupBulletinPic(GroupCode, _Pskey, imageurl);
|
||||||
}
|
}
|
||||||
static async handleGroupRequest(flag: string, operateType: GroupRequestOperateTypes, reason?: string) {
|
static async handleGroupRequest(flag: string , operateType: GroupRequestOperateTypes, reason?: string) {
|
||||||
let flagitem = flag.split('|');
|
let flagitem = flag.split('|');
|
||||||
let groupCode = flagitem[0];
|
let groupCode = flagitem[0];
|
||||||
let seq = flagitem[1];
|
let seq = flagitem[1];
|
||||||
|
@@ -1,14 +1,13 @@
|
|||||||
import { ElementType, GetFileListParam, MessageElement, Peer, RawMessage, SendMessageElement, SendMsgElementConstructor } from '@/core/entities';
|
import { ChatType, ChatType2, GetFileListParam, Peer, RawMessage, SendMessageElement, SendMsgElementConstructor } from '@/core/entities';
|
||||||
import { friends, groups, selfInfo } from '@/core/data';
|
import { friends, getGroupMember, groups, selfInfo } from '@/core/data';
|
||||||
import { log, logError, logWarn } from '@/common/utils/log';
|
import { log, logWarn } from '@/common/utils/log';
|
||||||
import { sleep } from '@/common/utils/helper';
|
import { sleep } from '@/common/utils/helper';
|
||||||
import { napCatCore, NodeIKernelMsgService, NTQQUserApi } from '@/core';
|
import { napCatCore, NTQQGroupApi, NTQQUserApi } from '@/core';
|
||||||
import { NodeIKernelMsgListener, onGroupFileInfoUpdateParamType } from '@/core/listeners';
|
import { onGroupFileInfoUpdateParamType } from '@/core/listeners';
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
import { MessageUnique } from '../../../common/utils/MessageUnique';
|
import { MessageUnique } from '../../../common/utils/MessageUnique';
|
||||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||||
import { logNotice } from '@/onebot11/log';
|
import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo';
|
||||||
let MsgSendMode = 2;
|
|
||||||
|
|
||||||
async function LoadMessageIdList(Peer: Peer, msgId: string) {
|
async function LoadMessageIdList(Peer: Peer, msgId: string) {
|
||||||
let msgList = await NTQQMsgApi.getMsgHistory(Peer, msgId, 50);
|
let msgList = await NTQQMsgApi.getMsgHistory(Peer, msgId, 50);
|
||||||
@@ -18,7 +17,7 @@ async function LoadMessageIdList(Peer: Peer, msgId: string) {
|
|||||||
}
|
}
|
||||||
async function loadMessageUnique() {
|
async function loadMessageUnique() {
|
||||||
if (groups.size > 100) {
|
if (groups.size > 100) {
|
||||||
logWarn('群数量大于100,可能会导致性能问题');
|
logWarn('[性能检测] 群数量大于100,可能会导致性能问题');
|
||||||
}
|
}
|
||||||
let predict = (groups.size + friends.size / 2) / 5;
|
let predict = (groups.size + friends.size / 2) / 5;
|
||||||
predict = predict < 20 ? 20 : predict;
|
predict = predict < 20 ? 20 : predict;
|
||||||
@@ -42,8 +41,11 @@ async function loadMessageUnique() {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
napCatCore.onLoginSuccess(async () => {
|
napCatCore.onLoginSuccess(async () => {
|
||||||
await sleep(100);
|
await sleep(100);
|
||||||
NTQQMsgApi.CheckSendMode().then().catch();
|
// NTQQMsgApi.CheckSendMode().then().catch();
|
||||||
loadMessageUnique().then().catch();
|
loadMessageUnique().then().catch();
|
||||||
|
//下面的代码还没摸清 不要使用
|
||||||
|
//let data = await napCatCore.session.getMsgService().sendSsoCmdReqByContend("LightAppSvc.mini_app_growguard.ReportExecute","1124343");
|
||||||
|
//console.log(data);
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
//歇菜LocalMsg压根不写Db
|
//歇菜LocalMsg压根不写Db
|
||||||
@@ -64,25 +66,38 @@ setTimeout(() => {
|
|||||||
// ));
|
// ));
|
||||||
// console.log(await NTQQMsgApi.multiForwardMsg(peer, peer, [MsgId]));
|
// console.log(await NTQQMsgApi.multiForwardMsg(peer, peer, [MsgId]));
|
||||||
// }, 25000)
|
// }, 25000)
|
||||||
|
|
||||||
export class NTQQMsgApi {
|
export class NTQQMsgApi {
|
||||||
static async CheckSendMode() {
|
static async FetchLongMsg(peer: Peer, msgId: string) {
|
||||||
try {
|
return napCatCore.session.getMsgService().fetchLongMsg(peer, msgId);
|
||||||
NTQQMsgApi.sendMsgV2({ chatType: 1, peerUid: selfInfo.uid }, [SendMsgElementConstructor.text('消息队列模式测试')], true, 10000).then().catch();
|
}
|
||||||
MsgSendMode = 2;
|
static async getTempChatInfo(chatType: ChatType2, peerUid: string) {
|
||||||
logNotice('[消息队列] 消息模式确认: MsgId异步队列');
|
return napCatCore.session.getMsgService().getTempChatInfo(chatType, peerUid);
|
||||||
return true;
|
}
|
||||||
} catch (error) {
|
static async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) {
|
||||||
logNotice('[消息队列] 消息模式失败: MsgId异步队列');
|
//By Jadx/Ida Mlikiowa
|
||||||
}
|
let TempGameSession = {
|
||||||
try {
|
nickname: "",
|
||||||
NTQQMsgApi.sendMsgV1({ chatType: 1, peerUid: selfInfo.uid }, [SendMsgElementConstructor.text('消息队列模式测试')], true, 10000).then().catch();
|
gameAppId: "",
|
||||||
MsgSendMode = 1;
|
selfTinyId: "",
|
||||||
logNotice('[消息队列] 消息模式确认: MsgSeq异步队列');
|
peerRoleId: "",
|
||||||
return true;
|
peerOpenId: "",
|
||||||
} catch (error) {
|
};
|
||||||
logNotice('[消息队列] 消息模式失败: MsgSeq异步队列');
|
return napCatCore.session.getMsgService().prepareTempChat({
|
||||||
}
|
chatType: ChatType2.KCHATTYPETEMPC2CFROMGROUP,
|
||||||
return false;
|
peerUid: toUserUid,
|
||||||
|
peerNickname: nickname,
|
||||||
|
fromGroupCode: GroupCode,
|
||||||
|
sig: "",
|
||||||
|
selfPhone: "",
|
||||||
|
selfUid: selfInfo.uid,
|
||||||
|
gameSession: TempGameSession
|
||||||
|
});
|
||||||
|
}
|
||||||
|
static async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) {
|
||||||
|
//console.log(peer, msgSeq, emojiId, emojiType, count);
|
||||||
|
//注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa
|
||||||
|
return napCatCore.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, "", false, 20)
|
||||||
}
|
}
|
||||||
// static napCatCore: NapCatCore | null = null;
|
// static napCatCore: NapCatCore | null = null;
|
||||||
// enum BaseEmojiType {
|
// enum BaseEmojiType {
|
||||||
@@ -104,20 +119,26 @@ export class NTQQMsgApi {
|
|||||||
} | undefined> {
|
} | undefined> {
|
||||||
return napCatCore.session.getMsgService().getMultiMsg(peer, rootMsgId, parentMsgId);
|
return napCatCore.session.getMsgService().getMultiMsg(peer, rootMsgId, parentMsgId);
|
||||||
}
|
}
|
||||||
static async getLastestMsgByUids(peer: Peer) {
|
static async ForwardMsg(peer: Peer, msgIds: string[]) {
|
||||||
|
return napCatCore.session.getMsgService().forwardMsg(msgIds, peer, [peer], []);
|
||||||
|
}
|
||||||
|
static async getLastestMsgByUids(peer: Peer, count: number = 20, isReverseOrder: boolean = false) {
|
||||||
let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
|
let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
|
||||||
chatInfo: peer,
|
chatInfo: peer,
|
||||||
filterMsgType: [],
|
filterMsgType: [],
|
||||||
filterSendersUid: [],
|
filterSendersUid: [],
|
||||||
filterMsgToTime: '0',
|
filterMsgToTime: '0',
|
||||||
filterMsgFromTime: '0',
|
filterMsgFromTime: '0',
|
||||||
isReverseOrder: false,
|
isReverseOrder: isReverseOrder,//此参数有点离谱 注意不是本次查询的排序 而是全部消历史信息的排序 默认false 从新消息拉取到旧消息
|
||||||
isIncludeCurrent: true,
|
isIncludeCurrent: true,
|
||||||
pageLimit: 1,
|
pageLimit: count,
|
||||||
});
|
});
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static async getMsgsByMsgId(peer: Peer, msgIds: string[]) {
|
static async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) {
|
||||||
|
if (!peer) throw new Error('peer is not allowed');
|
||||||
|
if (!msgIds) throw new Error('msgIds is not allowed');
|
||||||
|
//Mlikiowa: 参数不合规会导致NC异常崩溃 原因是TX未对进入参数判断 对应Android标记@NotNull AndroidJADX分析可得
|
||||||
return await napCatCore.session.getMsgService().getMsgsByMsgId(peer, msgIds);
|
return await napCatCore.session.getMsgService().getMsgsByMsgId(peer, msgIds);
|
||||||
}
|
}
|
||||||
static async getSingleMsg(peer: Peer, seq: string) {
|
static async getSingleMsg(peer: Peer, seq: string) {
|
||||||
@@ -128,7 +149,7 @@ export class NTQQMsgApi {
|
|||||||
}
|
}
|
||||||
static async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) {
|
static async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) {
|
||||||
let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
let ret = await napCatCore.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||||||
chatInfo: peer,
|
chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa
|
||||||
filterMsgType: [],
|
filterMsgType: [],
|
||||||
filterSendersUid: [],
|
filterSendersUid: [],
|
||||||
filterMsgToTime: '0',
|
filterMsgToTime: '0',
|
||||||
@@ -139,11 +160,18 @@ export class NTQQMsgApi {
|
|||||||
});
|
});
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @deprecated 从9.9.15-26702版本开始,该接口已经废弃,请使用getMsgsEx
|
||||||
|
* @param peer
|
||||||
|
* @param seq
|
||||||
|
* @param count
|
||||||
|
* @param desc
|
||||||
|
* @param z
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
static async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
|
static async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
|
||||||
return await napCatCore.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
|
return await napCatCore.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
|
||||||
}
|
|
||||||
static async testMode() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
static async setMsgRead(peer: Peer) {
|
static async setMsgRead(peer: Peer) {
|
||||||
return napCatCore.session.getMsgService().setMsgRead(peer);
|
return napCatCore.session.getMsgService().setMsgRead(peer);
|
||||||
@@ -153,11 +181,12 @@ export class NTQQMsgApi {
|
|||||||
(GroupCode: string, params: GetFileListParam) => Promise<unknown>,
|
(GroupCode: string, params: GetFileListParam) => Promise<unknown>,
|
||||||
(groupFileListResult: onGroupFileInfoUpdateParamType) => void
|
(groupFileListResult: onGroupFileInfoUpdateParamType) => void
|
||||||
>(
|
>(
|
||||||
'NodeIKernelRichMediaService/sendMsg',
|
'NodeIKernelRichMediaService/getGroupFileList',
|
||||||
'NodeIKernelMsgListener/onGroupFileInfoUpdate',
|
'NodeIKernelMsgListener/onGroupFileInfoUpdate',
|
||||||
1,
|
1,
|
||||||
5000,
|
5000,
|
||||||
(groupFileListResult: onGroupFileInfoUpdateParamType) => {
|
(groupFileListResult: onGroupFileInfoUpdateParamType) => {
|
||||||
|
//Developer Mlikiowa Todo: 此处有问题 无法判断是否成功
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
GroupCode,
|
GroupCode,
|
||||||
@@ -165,9 +194,9 @@ export class NTQQMsgApi {
|
|||||||
);
|
);
|
||||||
return data[1].item;
|
return data[1].item;
|
||||||
}
|
}
|
||||||
static async getMsgHistory(peer: Peer, msgId: string, count: number) {
|
static async getMsgHistory(peer: Peer, msgId: string, count: number, isReverseOrder: boolean = false) {
|
||||||
// 消息时间从旧到新
|
// 消息时间从旧到新
|
||||||
return napCatCore.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, true);
|
return napCatCore.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, isReverseOrder);
|
||||||
}
|
}
|
||||||
static async recallMsg(peer: Peer, msgIds: string[]) {
|
static async recallMsg(peer: Peer, msgIds: string[]) {
|
||||||
await napCatCore.session.getMsgService().recallMsg({
|
await napCatCore.session.getMsgService().recallMsg({
|
||||||
@@ -176,16 +205,29 @@ export class NTQQMsgApi {
|
|||||||
}, msgIds);
|
}, msgIds);
|
||||||
}
|
}
|
||||||
static async sendMsgV2(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
static async sendMsgV2(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
||||||
// function generateMsgId() {
|
if (peer.chatType === ChatType.temp) {
|
||||||
// const timestamp = Math.floor(Date.now() / 1000);
|
//await NTQQMsgApi.PrepareTempChat().then().catch();
|
||||||
// const random = Math.floor(Math.random() * Math.pow(2, 32));
|
}
|
||||||
// const buffer = Buffer.alloc(8);
|
function generateMsgId() {
|
||||||
// buffer.writeUInt32BE(timestamp, 0);
|
const timestamp = Math.floor(Date.now() / 1000);
|
||||||
// buffer.writeUInt32BE(random, 4);
|
const random = Math.floor(Math.random() * Math.pow(2, 32));
|
||||||
// const msgId = BigInt("0x" + buffer.toString('hex')).toString();
|
const buffer = Buffer.alloc(8);
|
||||||
// return msgId;
|
buffer.writeUInt32BE(timestamp, 0);
|
||||||
// }
|
buffer.writeUInt32BE(random, 4);
|
||||||
let msgId = await NTQQMsgApi.getMsgUnique(await NTQQMsgApi.getServerTime());
|
const msgId = BigInt("0x" + buffer.toString('hex')).toString();
|
||||||
|
return msgId;
|
||||||
|
}
|
||||||
|
// 此处有采用Hack方法 利用数据返回正确得到对应消息
|
||||||
|
// 与之前 Peer队列 MsgSeq队列 真正的MsgId并发不同
|
||||||
|
// 谨慎采用 目前测试暂无问题 Developer.Mlikiowa
|
||||||
|
let msgId: string;
|
||||||
|
try {
|
||||||
|
msgId = await NTQQMsgApi.getMsgUnique(peer.chatType, await NTQQMsgApi.getServerTime());
|
||||||
|
} catch (error) {
|
||||||
|
//if (!napCatCore.session.getMsgService()['generateMsgUniqueId'])
|
||||||
|
//兜底识别策略V2
|
||||||
|
msgId = generateMsgId().toString();
|
||||||
|
}
|
||||||
let data = await NTEventDispatch.CallNormalEvent<
|
let data = await NTEventDispatch.CallNormalEvent<
|
||||||
(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map<any, any>) => Promise<unknown>,
|
(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map<any, any>) => Promise<unknown>,
|
||||||
(msgList: RawMessage[]) => void
|
(msgList: RawMessage[]) => void
|
||||||
@@ -214,58 +256,72 @@ export class NTQQMsgApi {
|
|||||||
});
|
});
|
||||||
return retMsg;
|
return retMsg;
|
||||||
}
|
}
|
||||||
static sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
static sendMsgEx(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
||||||
if (MsgSendMode == 1) {
|
//return NTQQMsgApi.sendMsgV1(peer, msgElements, waitComplete, timeout);
|
||||||
return NTQQMsgApi.sendMsgV1(peer, msgElements, waitComplete, timeout);
|
|
||||||
} else if (MsgSendMode == 2) {
|
|
||||||
return NTQQMsgApi.sendMsgV2(peer, msgElements, waitComplete, timeout);
|
|
||||||
}
|
|
||||||
throw new Error('未知的发送消息模式');
|
|
||||||
}
|
}
|
||||||
static async sendMsgV1(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
static async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
||||||
let msgList = await NTQQMsgApi.getLastestMsgByUids(peer);
|
//唉? !我有个想法
|
||||||
let msgCurrentSeq = 0n;
|
function generateMsgId() {
|
||||||
if (msgList.msgList.length > 0) {
|
const timestamp = Math.floor(Date.now() / 1000);
|
||||||
msgCurrentSeq = BigInt(msgList.msgList[0].msgSeq);
|
const random = Math.floor(Math.random() * Math.pow(2, 32));
|
||||||
|
const buffer = Buffer.alloc(8);
|
||||||
|
buffer.writeUInt32BE(timestamp, 0);
|
||||||
|
buffer.writeUInt32BE(random, 4);
|
||||||
|
const msgId = BigInt("0x" + buffer.toString('hex')).toString();
|
||||||
|
return msgId;
|
||||||
}
|
}
|
||||||
let rawMsg: RawMessage | undefined;
|
// 此处有采用Hack方法 利用数据返回正确得到对应消息
|
||||||
let EventListener = NTEventDispatch.RegisterListen<NodeIKernelMsgListener['onAddSendMsg']>('NodeIKernelMsgListener/onAddSendMsg', 1, timeout, (msg: RawMessage) => {
|
// 与之前 Peer队列 MsgSeq队列 真正的MsgId并发不同
|
||||||
//console.log("msgSeq:", msgCurrentSeq.toString(), JSON.stringify(msgList.msgList[0], null, 4));
|
// 谨慎采用 目前测试暂无问题 Developer.Mlikiowa
|
||||||
if (msg.peerUid == peer.peerUid && (msgCurrentSeq == 0n || msgList.msgList[0].msgSeq == msgCurrentSeq.toString())) {
|
let msgId: string;
|
||||||
rawMsg = msg;
|
try {
|
||||||
return true;
|
msgId = await NTQQMsgApi.getMsgUnique(peer.chatType, await NTQQMsgApi.getServerTime());
|
||||||
|
} catch (error) {
|
||||||
|
//if (!napCatCore.session.getMsgService()['generateMsgUniqueId'])
|
||||||
|
//兜底识别策略V2
|
||||||
|
msgId = generateMsgId();
|
||||||
|
}
|
||||||
|
if (peer.chatType === ChatType.temp && peer.guildId && peer.guildId !== '') {
|
||||||
|
let member = await getGroupMember(peer.guildId, peer.peerUid!);
|
||||||
|
if(member){
|
||||||
|
await NTQQMsgApi.PrepareTempChat(peer.peerUid,peer.guildId,member.nick);
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
}).catch(logError);
|
peer.guildId = msgId;
|
||||||
let EventListener2 = NTEventDispatch.RegisterListen<NodeIKernelMsgListener['onMsgInfoListUpdate']>('NodeIKernelMsgListener/onMsgInfoListUpdate', 1, timeout,
|
let data = await NTEventDispatch.CallNormalEvent<
|
||||||
(msgList: RawMessage[]) => {
|
(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map<any, any>) => Promise<unknown>,
|
||||||
for (let msg of msgList) {
|
(msgList: RawMessage[]) => void
|
||||||
if (msg.peerUid == peer.peerUid && rawMsg && rawMsg.msgId == msg.msgId && msg.sendStatus == 2) {
|
>(
|
||||||
rawMsg = msg;
|
'NodeIKernelMsgService/sendMsg',
|
||||||
|
'NodeIKernelMsgListener/onMsgInfoListUpdate',
|
||||||
|
1,
|
||||||
|
timeout,
|
||||||
|
(msgRecords: RawMessage[]) => {
|
||||||
|
for (let msgRecord of msgRecords) {
|
||||||
|
if (msgRecord.guildId === msgId && msgRecord.sendStatus === 2) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).catch(logError);
|
},
|
||||||
await NTEventDispatch.CallNoListenerEvent<NodeIKernelMsgService['sendMsg']>('NodeIKernelMsgService/sendMsg', timeout, "0", peer, msgElements, new Map());
|
"0",
|
||||||
await EventListener;
|
peer,
|
||||||
await EventListener2;
|
msgElements,
|
||||||
// console.log("rawMsg", JSON.stringify(rawMsg, null, 4));
|
new Map()
|
||||||
if (rawMsg) {
|
);
|
||||||
return rawMsg;
|
let retMsg = data[1].find(msgRecord => {
|
||||||
|
if (msgRecord.guildId === msgId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return retMsg;
|
||||||
|
}
|
||||||
|
static async getMsgUnique(chatType: number, time: string) {
|
||||||
|
if (requireMinNTQQBuild('26702')) {
|
||||||
|
return napCatCore.session.getMsgService().generateMsgUniqueId(chatType, time);
|
||||||
}
|
}
|
||||||
throw new Error('发送消息超时');
|
|
||||||
}
|
|
||||||
static async getMsgUniqueEx() {
|
|
||||||
let msgId = await NTQQMsgApi.getMsgUnique(await NTQQMsgApi.getServerTime());
|
|
||||||
return msgId;
|
|
||||||
}
|
|
||||||
static async getMsgUnique(time: string) {
|
|
||||||
return napCatCore.session.getMsgService().getMsgUniqueId(time);
|
return napCatCore.session.getMsgService().getMsgUniqueId(time);
|
||||||
}
|
}
|
||||||
static async getMsgUniqueByTimeV2() {
|
|
||||||
return NTEventDispatch.CallNoListenerEvent<NodeIKernelMsgService['getMsgUniqueId']>('NodeIKernelMsgService/getMsgUniqueId', 5000, await NTQQMsgApi.getServerTimeV2())
|
|
||||||
}
|
|
||||||
static async getServerTime() {
|
static async getServerTime() {
|
||||||
return napCatCore.session.getMSFService().getServerTime();
|
return napCatCore.session.getMSFService().getServerTime();
|
||||||
}
|
}
|
||||||
@@ -273,7 +329,7 @@ export class NTQQMsgApi {
|
|||||||
return NTEventDispatch.CallNoListenerEvent<() => string>('NodeIKernelMsgService/getServerTime', 5000);
|
return NTEventDispatch.CallNoListenerEvent<() => string>('NodeIKernelMsgService/getServerTime', 5000);
|
||||||
}
|
}
|
||||||
static async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
static async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
||||||
return napCatCore.session.getMsgService().forwardMsg(msgIds, srcPeer, [destPeer], new Map());
|
return napCatCore.session.getMsgService().forwardMsg(msgIds, srcPeer, [destPeer], []);
|
||||||
}
|
}
|
||||||
static async multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]): Promise<RawMessage> {
|
static async multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]): Promise<RawMessage> {
|
||||||
const msgInfos = msgIds.map(id => {
|
const msgInfos = msgIds.map(id => {
|
||||||
|
@@ -19,6 +19,43 @@ export interface CustomMusicSignPostData {
|
|||||||
image?: string,
|
image?: string,
|
||||||
singer?: string
|
singer?: string
|
||||||
}
|
}
|
||||||
|
// let t = await napCatCore.session.getGroupService().shareDigest({
|
||||||
|
// appId: "100497308",
|
||||||
|
// appType: 1,
|
||||||
|
// msgStyle: 0,
|
||||||
|
// recvUin: "726067488",
|
||||||
|
// sendType: 1,
|
||||||
|
// clientInfo: {
|
||||||
|
// platform: 1
|
||||||
|
// },
|
||||||
|
// richMsg: {
|
||||||
|
// usingArk: true,
|
||||||
|
// title: "Bot测试title",
|
||||||
|
// summary: "Bot测试summary",
|
||||||
|
// url: "https://www.bilibili.com",
|
||||||
|
// pictureUrl: "https://y.qq.com/music/photo_new/T002R300x300M0000035DC6W4ZpSqf_1.jpg?max_age=2592000",
|
||||||
|
// brief: "Bot测试brief",
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// {
|
||||||
|
// errCode: 0,
|
||||||
|
// errMsg: '',
|
||||||
|
// rsp: {
|
||||||
|
// sendType: 1,
|
||||||
|
// recvUin: '726067488',
|
||||||
|
// recvOpenId: '',
|
||||||
|
// errCode: 901501,
|
||||||
|
// errMsg: 'imagent service_error:150_OIDB_NO_PRIV',
|
||||||
|
// extInfo: {
|
||||||
|
// wording: '消息下发失败(错误码:901501)',
|
||||||
|
// jumpResult: 0,
|
||||||
|
// jumpUrl: '',
|
||||||
|
// level: 0,
|
||||||
|
// subLevel: 0,
|
||||||
|
// developMsg: 'imagent error'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// export class MusicSign {
|
// export class MusicSign {
|
||||||
// private readonly url: string;
|
// private readonly url: string;
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
import { ModifyProfileParams, SelfInfo, User, UserDetailInfoByUin } from '@/core/entities';
|
import { ModifyProfileParams, SelfInfo, User, UserDetailInfoByUin, UserDetailInfoByUinV2 } from '@/core/entities';
|
||||||
import { friends, groupMembers, selfInfo } from '@/core/data';
|
import { friends, groupMembers, selfInfo } from '@/core/data';
|
||||||
import { CacheClassFuncAsync, CacheClassFuncAsyncExtend } from '@/common/utils/helper';
|
import { CacheClassFuncAsync, CacheClassFuncAsyncExtend } from '@/common/utils/helper';
|
||||||
import { napCatCore } from '@/core';
|
import { napCatCore, NTQQFriendApi } from '@/core';
|
||||||
import { NodeIKernelProfileListener, ProfileListener } from '@/core/listeners';
|
import { NodeIKernelProfileListener, ProfileListener } from '@/core/listeners';
|
||||||
import { RequestUtil } from '@/common/utils/request';
|
import { RequestUtil } from '@/common/utils/request';
|
||||||
import { logWarn } from '@/common/utils/log';
|
import { logWarn } from '@/common/utils/log';
|
||||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||||
import { NodeIKernelProfileService } from '@/core/services';
|
import { NodeIKernelProfileService, ProfileBizType, UserDetailSource } from '@/core/services';
|
||||||
|
import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo';
|
||||||
|
|
||||||
export class NTQQUserApi {
|
export class NTQQUserApi {
|
||||||
static async getProfileLike(uid: string) {
|
static async getProfileLike(uid: string) {
|
||||||
@@ -50,21 +51,87 @@ export class NTQQUserApi {
|
|||||||
return napCatCore.session.getGroupService().setHeader(gc, filePath);
|
return napCatCore.session.getGroupService().setHeader(gc, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getSelfInfo() {
|
static async fetchUserDetailInfos(uids: string[]) {
|
||||||
|
//26702 以上使用新接口 .Dev Mlikiowa
|
||||||
|
type EventService = NodeIKernelProfileService['fetchUserDetailInfo'];
|
||||||
|
type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged'];
|
||||||
|
let retData: User[] = [];
|
||||||
|
let [_retData, _retListener] = await NTEventDispatch.CallNormalEvent
|
||||||
|
<EventService, EventListener>
|
||||||
|
(
|
||||||
|
'NodeIKernelProfileService/fetchUserDetailInfo',
|
||||||
|
'NodeIKernelProfileListener/onUserDetailInfoChanged',
|
||||||
|
uids.length,
|
||||||
|
5000,
|
||||||
|
(profile) => {
|
||||||
|
if (uids.includes(profile.uid)) {
|
||||||
|
let RetUser: User = {
|
||||||
|
...profile.simpleInfo.coreInfo,
|
||||||
|
...profile.simpleInfo.status,
|
||||||
|
...profile.simpleInfo.vasInfo,
|
||||||
|
...profile.commonExt,
|
||||||
|
...profile.simpleInfo.baseInfo,
|
||||||
|
qqLevel: profile.commonExt.qqLevel,
|
||||||
|
pendantId: ""
|
||||||
|
};
|
||||||
|
retData.push(RetUser);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
"BuddyProfileStore",
|
||||||
|
uids,
|
||||||
|
UserDetailSource.KSERVER,
|
||||||
|
[
|
||||||
|
ProfileBizType.KALL
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return retData;
|
||||||
}
|
}
|
||||||
|
static async fetchUserDetailInfo(uid: string) {
|
||||||
static async getUserInfo(uid: string) {
|
type EventService = NodeIKernelProfileService['fetchUserDetailInfo'];
|
||||||
|
type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged'];
|
||||||
|
let [_retData, profile] = await NTEventDispatch.CallNormalEvent
|
||||||
|
<EventService, EventListener>
|
||||||
|
(
|
||||||
|
'NodeIKernelProfileService/fetchUserDetailInfo',
|
||||||
|
'NodeIKernelProfileListener/onUserDetailInfoChanged',
|
||||||
|
1,
|
||||||
|
5000,
|
||||||
|
(profile) => {
|
||||||
|
if (profile.uid === uid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
"BuddyProfileStore",
|
||||||
|
[
|
||||||
|
uid
|
||||||
|
],
|
||||||
|
UserDetailSource.KSERVER,
|
||||||
|
[
|
||||||
|
ProfileBizType.KALL
|
||||||
|
]
|
||||||
|
);
|
||||||
|
let RetUser: User = {
|
||||||
|
...profile.simpleInfo.coreInfo,
|
||||||
|
...profile.simpleInfo.status,
|
||||||
|
...profile.simpleInfo.vasInfo,
|
||||||
|
...profile.commonExt,
|
||||||
|
...profile.simpleInfo.baseInfo,
|
||||||
|
qqLevel: profile.commonExt.qqLevel,
|
||||||
|
pendantId: ""
|
||||||
|
};
|
||||||
|
return RetUser;
|
||||||
}
|
}
|
||||||
// enum ProfileBizType {
|
|
||||||
// KALL,
|
|
||||||
// KBASEEXTEND,
|
|
||||||
// KVAS,
|
|
||||||
// KQZONE,
|
|
||||||
// KOTHER
|
|
||||||
// }
|
|
||||||
static async getUserDetailInfo(uid: string) {
|
static async getUserDetailInfo(uid: string) {
|
||||||
|
if (requireMinNTQQBuild('26702')) {
|
||||||
|
return this.fetchUserDetailInfo(uid);
|
||||||
|
}
|
||||||
|
return this.getUserDetailInfoOld(uid);
|
||||||
|
}
|
||||||
|
static async getUserDetailInfoOld(uid: string) {
|
||||||
type EventService = NodeIKernelProfileService['getUserDetailInfoWithBizInfo'];
|
type EventService = NodeIKernelProfileService['getUserDetailInfoWithBizInfo'];
|
||||||
type EventListener = NodeIKernelProfileListener['onProfileDetailInfoChanged'];
|
type EventListener = NodeIKernelProfileListener['onProfileDetailInfoChanged'];
|
||||||
let [_retData, profile] = await NTEventDispatch.CallNormalEvent
|
let [_retData, profile] = await NTEventDispatch.CallNormalEvent
|
||||||
@@ -135,22 +202,72 @@ export class NTQQUserApi {
|
|||||||
}
|
}
|
||||||
return skey;
|
return skey;
|
||||||
}
|
}
|
||||||
@CacheClassFuncAsyncExtend(3600, 'Uin2Uid', (Uin: string, Uid: string | undefined) => {
|
@CacheClassFuncAsyncExtend(3600 * 1000, 'Uin2Uid', (Uin: string, Uid: string | undefined) => {
|
||||||
if (Uid && Uid.indexOf('u_') != -1) {
|
if (Uid && Uid.indexOf('u_') != -1) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
logWarn("uin转换到uid时异常", Uin);
|
logWarn("uin转换到uid时异常", Uin, Uid);
|
||||||
return false;
|
return false;
|
||||||
})
|
})
|
||||||
static async getUidByUin(Uin: string) {
|
static async getUidByUin(Uin: string) {
|
||||||
//Uid 接口转
|
//此代码仅临时使用,后期会被废弃
|
||||||
let ret = await NTEventDispatch.CallNoListenerEvent
|
if (requireMinNTQQBuild('26702')) {
|
||||||
<(Uin: string[]) => Promise<{ uidInfo: Map<string, string> }>>(
|
return await NTQQUserApi.getUidByUinV2(Uin);
|
||||||
'NodeIKernelUixConvertService/getUid',
|
}
|
||||||
5000,
|
return await NTQQUserApi.getUidByUinV1(Uin);
|
||||||
[Uin]
|
}
|
||||||
);
|
@CacheClassFuncAsyncExtend(3600 * 1000, 'Uid2Uin', (Uid: string | undefined, Uin: number | undefined) => {
|
||||||
let uid = ret.uidInfo.get(Uin);
|
if (Uin && Uin != 0 && !isNaN(Uin)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
logWarn("uid转换到uin时异常", Uid, Uin);
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
static async getUinByUid(Uid: string) {
|
||||||
|
//此代码仅临时使用,后期会被废弃
|
||||||
|
if (requireMinNTQQBuild('26702')) {
|
||||||
|
return await NTQQUserApi.getUinByUidV2(Uid);
|
||||||
|
}
|
||||||
|
return await NTQQUserApi.getUinByUidV1(Uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
//后期改成流水线处理
|
||||||
|
static async getUidByUinV2(Uin: string) {
|
||||||
|
let uid = (await napCatCore.session.getProfileService().getUidByUin('FriendsServiceImpl', [Uin])).get(Uin);
|
||||||
|
if (uid) return uid;
|
||||||
|
uid = (await napCatCore.session.getGroupService().getUidByUins([Uin])).uids.get(Uin);
|
||||||
|
if (uid) return uid;
|
||||||
|
uid = (await napCatCore.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin);
|
||||||
|
if (uid) return uid;
|
||||||
|
console.log((await NTQQFriendApi.getBuddyIdMapCache(true)));
|
||||||
|
uid = (await NTQQFriendApi.getBuddyIdMapCache(true)).getValue(Uin);//从Buddy缓存获取Uid
|
||||||
|
if (uid) return uid;
|
||||||
|
uid = (await NTQQFriendApi.getBuddyIdMap(true)).getValue(Uin);
|
||||||
|
if (uid) return uid;
|
||||||
|
let unveifyUid = (await NTQQUserApi.getUserDetailInfoByUinV2(Uin)).detail.uid;//从QQ Native 特殊转换
|
||||||
|
if (unveifyUid.indexOf("*") == -1) uid = unveifyUid;
|
||||||
|
//if (uid) return uid;
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
//后期改成流水线处理
|
||||||
|
static async getUinByUidV2(Uid: string) {
|
||||||
|
let uin = (await napCatCore.session.getProfileService().getUinByUid('FriendsServiceImpl', [Uid])).get(Uid);
|
||||||
|
if (uin) return uin;
|
||||||
|
uin = (await napCatCore.session.getGroupService().getUinByUids([Uid])).uins.get(Uid);
|
||||||
|
if (uin) return uin;
|
||||||
|
uin = (await napCatCore.session.getUixConvertService().getUin([Uid])).uinInfo.get(Uid);
|
||||||
|
if (uin) return uin;
|
||||||
|
uin = (await NTQQFriendApi.getBuddyIdMapCache(true)).getKey(Uid);//从Buddy缓存获取Uin
|
||||||
|
if (uin) return uin;
|
||||||
|
uin = (await NTQQFriendApi.getBuddyIdMap(true)).getKey(Uid);
|
||||||
|
if (uin) return uin;
|
||||||
|
uin = (await NTQQUserApi.getUserDetailInfo(Uid)).uin; //从QQ Native 转换
|
||||||
|
return uin;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getUidByUinV1(Uin: string) {
|
||||||
|
// 通用转换开始尝试
|
||||||
|
let uid = (await napCatCore.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin);
|
||||||
// Uid 好友转
|
// Uid 好友转
|
||||||
if (!uid) {
|
if (!uid) {
|
||||||
Array.from(friends.values()).forEach((t) => {
|
Array.from(friends.values()).forEach((t) => {
|
||||||
@@ -177,17 +294,7 @@ export class NTQQUserApi {
|
|||||||
}
|
}
|
||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
@CacheClassFuncAsyncExtend(3600, 'Uid2Uin', (Uid: string | undefined, Uin: number | undefined) => {
|
static async getUinByUidV1(Uid: string) {
|
||||||
if (Uin && Uin != 0 && !isNaN(Uin)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
logWarn("uid转换到uin时异常", Uid);
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
static async getUinByUid(Uid: string | undefined) {
|
|
||||||
if (!Uid) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
let ret = await NTEventDispatch.CallNoListenerEvent
|
let ret = await NTEventDispatch.CallNoListenerEvent
|
||||||
<(Uin: string[]) => Promise<{ uinInfo: Map<string, string> }>>(
|
<(Uin: string[]) => Promise<{ uinInfo: Map<string, string> }>>(
|
||||||
'NodeIKernelUixConvertService/getUin',
|
'NodeIKernelUixConvertService/getUin',
|
||||||
@@ -227,6 +334,14 @@ export class NTQQUserApi {
|
|||||||
static async getRecentContactList() {
|
static async getRecentContactList() {
|
||||||
return await napCatCore.session.getRecentContactService().getRecentContactList();
|
return await napCatCore.session.getRecentContactService().getRecentContactList();
|
||||||
}
|
}
|
||||||
|
static async getUserDetailInfoByUinV2(Uin: string) {
|
||||||
|
return await NTEventDispatch.CallNoListenerEvent
|
||||||
|
<(Uin: string) => Promise<UserDetailInfoByUinV2>>(
|
||||||
|
'NodeIKernelProfileService/getUserDetailInfoByUin',
|
||||||
|
5000,
|
||||||
|
Uin
|
||||||
|
);
|
||||||
|
}
|
||||||
static async getUserDetailInfoByUin(Uin: string) {
|
static async getUserDetailInfoByUin(Uin: string) {
|
||||||
return NTEventDispatch.CallNoListenerEvent
|
return NTEventDispatch.CallNoListenerEvent
|
||||||
<(Uin: string) => Promise<UserDetailInfoByUin>>(
|
<(Uin: string) => Promise<UserDetailInfoByUin>>(
|
||||||
|
@@ -114,6 +114,22 @@ export interface GroupEssenceMsgRet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class WebApi {
|
export class WebApi {
|
||||||
|
static async shareDigest(groupCode: string, msgSeq: string, msgRandom: string, targetGroupCode: string) {
|
||||||
|
const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com');
|
||||||
|
const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||||
|
const Bkn = WebApi.genBkn(CookiesObject.skey);
|
||||||
|
let ret: any = undefined;
|
||||||
|
const data = 'group_code=' + groupCode + '&msg_seq=' + msgSeq + '&msg_random=' + msgRandom + '&target_group_code=' + targetGroupCode;
|
||||||
|
const url = 'https://qun.qq.com/cgi-bin/group_digest/share_digest?bkn=' + Bkn + "&" + data;
|
||||||
|
//console.log(url);
|
||||||
|
try {
|
||||||
|
ret = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': CookieValue });
|
||||||
|
return ret;
|
||||||
|
} catch (e) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
@CacheClassFuncAsync(3600 * 1000, 'webapi_get_group_members')
|
@CacheClassFuncAsync(3600 * 1000, 'webapi_get_group_members')
|
||||||
static async getGroupEssenceMsg(GroupCode: string, page_start: string) {
|
static async getGroupEssenceMsg(GroupCode: string, page_start: string) {
|
||||||
const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com');
|
const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com');
|
||||||
|
@@ -15,12 +15,12 @@ import { DependsAdapter, DispatcherAdapter, GlobalAdapter, NodeIGlobalAdapter }
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import { appid, qqVersionConfigInfo } from '@/common/utils/QQBasicInfo';
|
import { getFullQQVesion, QQVersionAppid, QQVersionQua, requireMinNTQQBuild } from '@/common/utils/QQBasicInfo';
|
||||||
import { hostname, systemVersion } from '@/common/utils/system';
|
import { hostname, systemVersion } from '@/common/utils/system';
|
||||||
import { genSessionConfig } from '@/core/sessionConfig';
|
import { genSessionConfig } from '@/core/sessionConfig';
|
||||||
import { sleep } from '@/common/utils/helper';
|
import { sleep } from '@/common/utils/helper';
|
||||||
import crypto from 'node:crypto';
|
import crypto from 'node:crypto';
|
||||||
import { rawFriends, friends, groupMembers, groups, selfInfo, stat } from '@/core/data';
|
import { groupMembers, groups, selfInfo, stat } from '@/core/data';
|
||||||
import { GroupMember, RawMessage } from '@/core/entities';
|
import { GroupMember, RawMessage } from '@/core/entities';
|
||||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||||
import {
|
import {
|
||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
setLogSelfInfo
|
setLogSelfInfo
|
||||||
} from '@/common/utils/log';
|
} from '@/common/utils/log';
|
||||||
import { napCatConfig } from '@/core/utils/config';
|
import { napCatConfig } from '@/core/utils/config';
|
||||||
|
import { NTQQFriendApi } from './apis';
|
||||||
|
|
||||||
export interface OnLoginSuccess {
|
export interface OnLoginSuccess {
|
||||||
(uin: string, uid: string): void | Promise<void>;
|
(uin: string, uid: string): void | Promise<void>;
|
||||||
@@ -84,7 +85,6 @@ export class NapCatCore {
|
|||||||
const dataPath = path.resolve(this.dataPath, './NapCat/data');
|
const dataPath = path.resolve(this.dataPath, './NapCat/data');
|
||||||
fs.mkdirSync(dataPath, { recursive: true });
|
fs.mkdirSync(dataPath, { recursive: true });
|
||||||
logDebug('本账号数据/缓存目录:', dataPath);
|
logDebug('本账号数据/缓存目录:', dataPath);
|
||||||
// dbUtil.init(path.resolve(dataPath, `./${arg.uin}-v2.db`)).then(() => {
|
|
||||||
this.initDataListener();
|
this.initDataListener();
|
||||||
this.onLoginSuccessFuncList.map(cb => {
|
this.onLoginSuccessFuncList.map(cb => {
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
@@ -94,11 +94,6 @@ export class NapCatCore {
|
|||||||
}
|
}
|
||||||
}).then();
|
}).then();
|
||||||
});
|
});
|
||||||
// }).catch((e) => {
|
|
||||||
// logError('数据库初始化失败', e);
|
|
||||||
// });
|
|
||||||
// this.initDataListener();
|
|
||||||
|
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
logError('initSession failed', e);
|
logError('initSession failed', e);
|
||||||
throw new Error(`启动失败: ${JSON.stringify(e)}`);
|
throw new Error(`启动失败: ${JSON.stringify(e)}`);
|
||||||
@@ -139,10 +134,10 @@ export class NapCatCore {
|
|||||||
base_path_prefix: '',
|
base_path_prefix: '',
|
||||||
platform_type: 3,
|
platform_type: 3,
|
||||||
app_type: 4,
|
app_type: 4,
|
||||||
app_version: qqVersionConfigInfo.curVersion,
|
app_version: getFullQQVesion(),
|
||||||
os_version: 'Windows 10 Pro',
|
os_version: 'Windows 10 Pro',
|
||||||
use_xlog: true,
|
use_xlog: true,
|
||||||
qua: `V1_WIN_NQ_${qqVersionConfigInfo.curVersion.replace('-', '_')}_GW_B`,
|
qua: QQVersionQua,
|
||||||
global_path_config: {
|
global_path_config: {
|
||||||
desktopGlobalPath: this.dataPathGlobal,
|
desktopGlobalPath: this.dataPathGlobal,
|
||||||
},
|
},
|
||||||
@@ -150,10 +145,10 @@ export class NapCatCore {
|
|||||||
}, new QQWrapper.NodeIGlobalAdapter(new GlobalAdapter()));
|
}, new QQWrapper.NodeIGlobalAdapter(new GlobalAdapter()));
|
||||||
this.loginService.initConfig({
|
this.loginService.initConfig({
|
||||||
machineId: '',
|
machineId: '',
|
||||||
appid,
|
appid: QQVersionAppid,
|
||||||
platVer: systemVersion,
|
platVer: systemVersion,
|
||||||
commonPath: this.dataPathGlobal,
|
commonPath: this.dataPathGlobal,
|
||||||
clientVer: qqVersionConfigInfo.curVersion,
|
clientVer: getFullQQVesion(),
|
||||||
hostName: hostname
|
hostName: hostname
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -258,31 +253,23 @@ export class NapCatCore {
|
|||||||
stat.packet_received += 1;
|
stat.packet_received += 1;
|
||||||
};
|
};
|
||||||
this.addListener(msgListener);
|
this.addListener(msgListener);
|
||||||
// 好友相关
|
// 好友相关
|
||||||
const buddyListener = new BuddyListener();
|
const buddyListener = new BuddyListener();
|
||||||
buddyListener.onBuddyListChange = arg => {
|
|
||||||
rawFriends.length = 0;
|
|
||||||
rawFriends.push(...arg);
|
|
||||||
// console.log('onBuddyListChange', arg);
|
|
||||||
for (const categoryItem of arg) {
|
|
||||||
for (const friend of categoryItem.buddyList) {
|
|
||||||
// console.log("onBuddyListChange", friend)
|
|
||||||
const existFriend = friends.get(friend.uid);
|
|
||||||
if (existFriend) {
|
|
||||||
Object.assign(existFriend, friend);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
friends.set(friend.uid, friend);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// console.log("onBuddyListChange", friend)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.addListener(buddyListener);
|
this.addListener(buddyListener);
|
||||||
// 刷新一次好友列表
|
// 刷新一次好友列表 26702版本以下需要手动刷新一次获取 高版本NTQQ自带缓存
|
||||||
this.session.getBuddyService().getBuddyList(true).then(arg => {
|
if (!requireMinNTQQBuild('26702')) {
|
||||||
// console.log('getBuddyList', arg);
|
this.session.getBuddyService().getBuddyList(true).then(arg => {
|
||||||
});
|
// console.log('getBuddyList', arg);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// NTQQFriendApi.getBuddyV2(true).then((res) => {
|
||||||
|
// res.forEach((item) => {
|
||||||
|
// CachedIdMap.set(item.uid!, item.uin!);
|
||||||
|
// });
|
||||||
|
// }).catch();
|
||||||
|
}
|
||||||
interface SelfStatusInfo {
|
interface SelfStatusInfo {
|
||||||
uid: string
|
uid: string
|
||||||
status: number
|
status: number
|
||||||
@@ -335,6 +322,7 @@ export class NapCatCore {
|
|||||||
if (groupMembers.has(groupCode)) {
|
if (groupMembers.has(groupCode)) {
|
||||||
const existMembers = groupMembers.get(groupCode)!;
|
const existMembers = groupMembers.get(groupCode)!;
|
||||||
arg.infos.forEach((member, uid) => {
|
arg.infos.forEach((member, uid) => {
|
||||||
|
//console.log('onMemberListChange', member);
|
||||||
const existMember = existMembers.get(uid);
|
const existMember = existMembers.get(uid);
|
||||||
if (existMember) {
|
if (existMember) {
|
||||||
Object.assign(existMember, member);
|
Object.assign(existMember, member);
|
||||||
|
@@ -3,9 +3,11 @@ import {
|
|||||||
type Group,
|
type Group,
|
||||||
type GroupMember,
|
type GroupMember,
|
||||||
type SelfInfo,
|
type SelfInfo,
|
||||||
type BuddyCategoryType
|
type BuddyCategoryType,
|
||||||
|
FriendV2
|
||||||
} from './entities';
|
} from './entities';
|
||||||
import { isNumeric } from '@/common/utils/helper';
|
import { isNumeric } from '@/common/utils/helper';
|
||||||
|
import { LimitedHashTable } from '@/common/utils/MessageUnique';
|
||||||
import { NTQQGroupApi } from '@/core/apis';
|
import { NTQQGroupApi } from '@/core/apis';
|
||||||
|
|
||||||
export const selfInfo: SelfInfo = {
|
export const selfInfo: SelfInfo = {
|
||||||
@@ -14,8 +16,6 @@ export const selfInfo: SelfInfo = {
|
|||||||
nick: '',
|
nick: '',
|
||||||
online: true
|
online: true
|
||||||
};
|
};
|
||||||
// 未来只在此处保留 selfInfo stat
|
|
||||||
// groupCode -> Group
|
|
||||||
export const groups: Map<string, Group> = new Map<string, Group>();
|
export const groups: Map<string, Group> = new Map<string, Group>();
|
||||||
|
|
||||||
export function deleteGroup(groupQQ: string) {
|
export function deleteGroup(groupQQ: string) {
|
||||||
@@ -26,9 +26,10 @@ export function deleteGroup(groupQQ: string) {
|
|||||||
// 群号 -> 群成员map(uid=>GroupMember)
|
// 群号 -> 群成员map(uid=>GroupMember)
|
||||||
export const groupMembers: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
|
export const groupMembers: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
|
||||||
|
|
||||||
// uid -> Friend 下面这俩个准备移除 QQ里面自带缓存
|
|
||||||
export const friends: Map<string, Friend> = new Map<string, Friend>();
|
export const friends: Map<string, Friend> = new Map<string, Friend>();
|
||||||
export const rawFriends: Array<BuddyCategoryType> = []; // 带分组的好友列表
|
|
||||||
|
//转换列表
|
||||||
|
//export const CachedIdMap = new LimitedHashTable<string, string>(1000);
|
||||||
|
|
||||||
export async function getGroup(qq: string | number): Promise<Group | undefined> {
|
export async function getGroup(qq: string | number): Promise<Group | undefined> {
|
||||||
let group = groups.get(qq.toString());
|
let group = groups.get(qq.toString());
|
||||||
@@ -79,9 +80,6 @@ export async function getGroupMember(groupQQ: string | number, memberUinOrUid: s
|
|||||||
}
|
}
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
// 考虑优化 移入QQ缓存或使用Api直接获取
|
|
||||||
export const tempGroupCodeMap: Record<string, string> = {}; // peerUid => 群号
|
|
||||||
|
|
||||||
// 保留 需要频繁读写
|
// 保留 需要频繁读写
|
||||||
export const stat = {
|
export const stat = {
|
||||||
packet_received: 0,
|
packet_received: 0,
|
||||||
|
@@ -1,12 +1,18 @@
|
|||||||
import { QQLevel, Sex } from './user';
|
import { QQLevel, Sex } from './user';
|
||||||
|
export enum GroupListUpdateType {
|
||||||
|
REFRESHALL,
|
||||||
|
GETALL,
|
||||||
|
MODIFIED,
|
||||||
|
REMOVE
|
||||||
|
}
|
||||||
export interface Group {
|
export interface Group {
|
||||||
groupCode: string,
|
groupCode: string,
|
||||||
|
createTime?: string,//高版本才有
|
||||||
maxMember: number,
|
maxMember: number,
|
||||||
memberCount: number,
|
memberCount: number,
|
||||||
groupName: string,
|
groupName: string,
|
||||||
groupStatus: 0,
|
groupStatus: number,
|
||||||
memberRole: 2,
|
memberRole: number,
|
||||||
isTop: boolean,
|
isTop: boolean,
|
||||||
toppedTimestamp: string,
|
toppedTimestamp: string,
|
||||||
privilegeFlag: number, //65760
|
privilegeFlag: number, //65760
|
||||||
@@ -53,4 +59,6 @@ export interface GroupMember {
|
|||||||
sex?: Sex
|
sex?: Sex
|
||||||
qqLevel?: QQLevel
|
qqLevel?: QQLevel
|
||||||
isChangeRole: boolean;
|
isChangeRole: boolean;
|
||||||
|
joinTime: string;
|
||||||
|
lastSpeakTime: string;
|
||||||
}
|
}
|
@@ -731,9 +731,12 @@ export interface MultiForwardMsgElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface RawMessage {
|
export interface RawMessage {
|
||||||
|
parentMsgPeer: Peer;
|
||||||
|
parentMsgIdList:string[];
|
||||||
|
id?: number;//扩展字段 用于处理OB11 ID
|
||||||
|
guildId: string;
|
||||||
msgRandom: string;
|
msgRandom: string;
|
||||||
// int32, 自己维护的消息id
|
|
||||||
id?: number;
|
|
||||||
|
|
||||||
msgId: string;
|
msgId: string;
|
||||||
|
|
||||||
|
@@ -62,6 +62,7 @@ export enum BuddyReqType {
|
|||||||
KMEINITIATORWAITPEERCONFIRM
|
KMEINITIATORWAITPEERCONFIRM
|
||||||
}
|
}
|
||||||
export interface FriendRequest {
|
export interface FriendRequest {
|
||||||
|
isInitiator?: boolean;
|
||||||
isDecide: boolean;
|
isDecide: boolean;
|
||||||
friendUid: string;
|
friendUid: string;
|
||||||
reqType: BuddyReqType,
|
reqType: BuddyReqType,
|
||||||
|
@@ -9,7 +9,181 @@ export interface BuddyCategoryType {
|
|||||||
categroyMbCount: number;
|
categroyMbCount: number;
|
||||||
buddyList: User[];
|
buddyList: User[];
|
||||||
}
|
}
|
||||||
|
export interface CoreInfo {
|
||||||
|
uid: string;
|
||||||
|
uin: string;
|
||||||
|
nick: string;
|
||||||
|
remark: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BaseInfo {
|
||||||
|
qid: string;
|
||||||
|
longNick: string;
|
||||||
|
birthday_year: number;
|
||||||
|
birthday_month: number;
|
||||||
|
birthday_day: number;
|
||||||
|
age: number;
|
||||||
|
sex: number;
|
||||||
|
eMail: string;
|
||||||
|
phoneNum: string;
|
||||||
|
categoryId: number;
|
||||||
|
richTime: number;
|
||||||
|
richBuffer: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MusicInfo {
|
||||||
|
buf: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VideoBizInfo {
|
||||||
|
cid: string;
|
||||||
|
tvUrl: string;
|
||||||
|
synchType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VideoInfo {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ExtOnlineBusinessInfo {
|
||||||
|
buf: string;
|
||||||
|
customStatus: any;
|
||||||
|
videoBizInfo: VideoBizInfo;
|
||||||
|
videoInfo: VideoInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ExtBuffer {
|
||||||
|
buf: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UserStatus {
|
||||||
|
uid: string;
|
||||||
|
uin: string;
|
||||||
|
status: number;
|
||||||
|
extStatus: number;
|
||||||
|
batteryStatus: number;
|
||||||
|
termType: number;
|
||||||
|
netType: number;
|
||||||
|
iconType: number;
|
||||||
|
customStatus: any;
|
||||||
|
setTime: string;
|
||||||
|
specialFlag: number;
|
||||||
|
abiFlag: number;
|
||||||
|
eNetworkType: number;
|
||||||
|
showName: string;
|
||||||
|
termDesc: string;
|
||||||
|
musicInfo: MusicInfo;
|
||||||
|
extOnlineBusinessInfo: ExtOnlineBusinessInfo;
|
||||||
|
extBuffer: ExtBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PrivilegeIcon {
|
||||||
|
jumpUrl: string;
|
||||||
|
openIconList: any[];
|
||||||
|
closeIconList: any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VasInfo {
|
||||||
|
vipFlag: boolean;
|
||||||
|
yearVipFlag: boolean;
|
||||||
|
svipFlag: boolean;
|
||||||
|
vipLevel: number;
|
||||||
|
bigClub: boolean;
|
||||||
|
bigClubLevel: number;
|
||||||
|
nameplateVipType: number;
|
||||||
|
grayNameplateFlag: number;
|
||||||
|
superVipTemplateId: number;
|
||||||
|
diyFontId: number;
|
||||||
|
pendantId: number;
|
||||||
|
pendantDiyId: number;
|
||||||
|
faceId: number;
|
||||||
|
vipFont: number;
|
||||||
|
vipFontType: number;
|
||||||
|
magicFont: number;
|
||||||
|
fontEffect: number;
|
||||||
|
newLoverDiamondFlag: number;
|
||||||
|
extendNameplateId: number;
|
||||||
|
diyNameplateIDs: any[];
|
||||||
|
vipStartFlag: number;
|
||||||
|
vipDataFlag: number;
|
||||||
|
gameNameplateId: string;
|
||||||
|
gameLastLoginTime: string;
|
||||||
|
gameRank: number;
|
||||||
|
gameIconShowFlag: boolean;
|
||||||
|
gameCardId: string;
|
||||||
|
vipNameColorId: string;
|
||||||
|
privilegeIcon: PrivilegeIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RelationFlags {
|
||||||
|
topTime: string;
|
||||||
|
isBlock: boolean;
|
||||||
|
isMsgDisturb: boolean;
|
||||||
|
isSpecialCareOpen: boolean;
|
||||||
|
isSpecialCareZone: boolean;
|
||||||
|
ringId: string;
|
||||||
|
isBlocked: boolean;
|
||||||
|
recommendImgFlag: number;
|
||||||
|
disableEmojiShortCuts: number;
|
||||||
|
qidianMasterFlag: number;
|
||||||
|
qidianCrewFlag: number;
|
||||||
|
qidianCrewFlag2: number;
|
||||||
|
isHideQQLevel: number;
|
||||||
|
isHidePrivilegeIcon: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface CommonExt {
|
||||||
|
constellation: number;
|
||||||
|
shengXiao: number;
|
||||||
|
kBloodType: number;
|
||||||
|
homeTown: string;
|
||||||
|
makeFriendCareer: number;
|
||||||
|
pos: string;
|
||||||
|
college: string;
|
||||||
|
country: string;
|
||||||
|
province: string;
|
||||||
|
city: string;
|
||||||
|
postCode: string;
|
||||||
|
address: string;
|
||||||
|
regTime: number;
|
||||||
|
interest: string;
|
||||||
|
labels: any[];
|
||||||
|
qqLevel: QQLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Pic {
|
||||||
|
picId: string;
|
||||||
|
picTime: number;
|
||||||
|
picUrlMap: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PhotoWall {
|
||||||
|
picList: Pic[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SimpleInfo {
|
||||||
|
uid?: string;
|
||||||
|
uin?: string;
|
||||||
|
coreInfo: CoreInfo;
|
||||||
|
baseInfo: BaseInfo;
|
||||||
|
status: UserStatus | null;
|
||||||
|
vasInfo: VasInfo | null;
|
||||||
|
relationFlags: RelationFlags | null;
|
||||||
|
otherFlags: any | null;
|
||||||
|
intimate: any | null;
|
||||||
|
}
|
||||||
|
export interface FriendV2 extends SimpleInfo {
|
||||||
|
categoryId?: number;
|
||||||
|
categroyName?: string;
|
||||||
|
}
|
||||||
|
export interface UserDetailInfoListenerArg {
|
||||||
|
uid: string;
|
||||||
|
uin: string;
|
||||||
|
simpleInfo: SimpleInfo;
|
||||||
|
commonExt: CommonExt;
|
||||||
|
photoWall: PhotoWall;
|
||||||
|
}
|
||||||
export interface ModifyProfileParams {
|
export interface ModifyProfileParams {
|
||||||
nick: string,
|
nick: string,
|
||||||
longNick: string,
|
longNick: string,
|
||||||
@@ -101,7 +275,18 @@ export interface Friend extends User { }
|
|||||||
export enum BizKey {
|
export enum BizKey {
|
||||||
KPRIVILEGEICON,
|
KPRIVILEGEICON,
|
||||||
KPHOTOWALL
|
KPHOTOWALL
|
||||||
}
|
}
|
||||||
|
export interface UserDetailInfoByUinV2 {
|
||||||
|
result: number,
|
||||||
|
errMsg: string,
|
||||||
|
detail: {
|
||||||
|
uid: string,
|
||||||
|
uin: string,
|
||||||
|
simpleInfo: SimpleInfo,
|
||||||
|
commonExt: CommonExt,
|
||||||
|
photoWall: null
|
||||||
|
}
|
||||||
|
}
|
||||||
export interface UserDetailInfoByUin {
|
export interface UserDetailInfoByUin {
|
||||||
result: number,
|
result: number,
|
||||||
errMsg: string,
|
errMsg: string,
|
||||||
|
50
src/core/src/external/appid.json
vendored
Normal file
50
src/core/src/external/appid.json
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"3.1.2-13107": {
|
||||||
|
"appid": 537146866,
|
||||||
|
"qua": "V1_LNX_NQ_3.1.2-13107_RDM_B"
|
||||||
|
},
|
||||||
|
"3.2.10-25765": {
|
||||||
|
"appid": 537234773,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.10_25765_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.12-26702": {
|
||||||
|
"appid": 537237950,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.12_26702_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.12-26740": {
|
||||||
|
"appid": 537237950,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.15_26740_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.11-24815": {
|
||||||
|
"appid": 537226656,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.11_24815_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.12-25493": {
|
||||||
|
"appid": 537231759,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.12_25493_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.12-25765": {
|
||||||
|
"appid": 537234702,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.12_25765_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.12-26299": {
|
||||||
|
"appid": 537234826,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.12_26299_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.12-26339": {
|
||||||
|
"appid": 537234826,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.12_26339_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.12-26466": {
|
||||||
|
"appid": 537234826,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.12_26466_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.15-26702": {
|
||||||
|
"appid": 537237765,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.15_26702_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.15-26740": {
|
||||||
|
"appid": 537237765,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.15_26702_GW_B"
|
||||||
|
}
|
||||||
|
}
|
@@ -3,6 +3,8 @@ import { BuddyCategoryType, FriendRequestNotify } from '@/core/entities';
|
|||||||
export type OnBuddyChangeParams = BuddyCategoryType[]
|
export type OnBuddyChangeParams = BuddyCategoryType[]
|
||||||
|
|
||||||
interface IBuddyListener {
|
interface IBuddyListener {
|
||||||
|
onBuddyListChangedV2(arg: unknown): void,//V2版本 还没兼容
|
||||||
|
|
||||||
onBuddyListChange(arg: OnBuddyChangeParams): void,
|
onBuddyListChange(arg: OnBuddyChangeParams): void,
|
||||||
|
|
||||||
onBuddyInfoChange(arg: unknown): void,
|
onBuddyInfoChange(arg: unknown): void,
|
||||||
@@ -44,6 +46,9 @@ export interface NodeIKernelBuddyListener extends IBuddyListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class BuddyListener implements IBuddyListener {
|
export class BuddyListener implements IBuddyListener {
|
||||||
|
onBuddyListChangedV2(arg: unknown): void {
|
||||||
|
//throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
onAddBuddyNeedVerify(arg: unknown) {
|
onAddBuddyNeedVerify(arg: unknown) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { Group, GroupMember, GroupNotify } from '@/core/entities';
|
import { Group, GroupListUpdateType, GroupMember, GroupNotify } from '@/core/entities';
|
||||||
|
|
||||||
interface IGroupListener {
|
interface IGroupListener {
|
||||||
onGroupListUpdate(updateType: number, groupList: Group[]): void;
|
onGroupListUpdate(updateType: GroupListUpdateType, groupList: Group[]): void;
|
||||||
|
|
||||||
onGroupExtListUpdate(...args: unknown[]): void;
|
onGroupExtListUpdate(...args: unknown[]): void;
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ export class GroupListener implements IGroupListener {
|
|||||||
onGroupFirstBulletinNotify(...args: unknown[]) {
|
onGroupFirstBulletinNotify(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupListUpdate(updateType: number, groupList: Group[]) {
|
onGroupListUpdate(updateType: GroupListUpdateType, groupList: Group[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]) {
|
onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]) {
|
||||||
@@ -202,7 +202,7 @@ export class DebugGroupListener implements IGroupListener {
|
|||||||
console.log('onGroupNotifiesUnreadCountUpdated:', ...args);
|
console.log('onGroupNotifiesUnreadCountUpdated:', ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]){
|
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]) {
|
||||||
console.log('onGroupSingleScreenNotifies:');
|
console.log('onGroupSingleScreenNotifies:');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import { User } from '@/core/entities';
|
import { User, UserDetailInfoListenerArg } from '@/core/entities';
|
||||||
|
|
||||||
interface IProfileListener {
|
interface IProfileListener {
|
||||||
onProfileSimpleChanged(...args: unknown[]): void;
|
onProfileSimpleChanged(...args: unknown[]): void;
|
||||||
|
onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void;
|
||||||
onProfileDetailInfoChanged(profile: User): void;
|
onProfileDetailInfoChanged(profile: User): void;
|
||||||
|
|
||||||
onStatusUpdate(...args: unknown[]): void;
|
onStatusUpdate(...args: unknown[]): void;
|
||||||
@@ -18,6 +18,9 @@ export interface NodeIKernelProfileListener extends IProfileListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ProfileListener implements IProfileListener {
|
export class ProfileListener implements IProfileListener {
|
||||||
|
onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void {
|
||||||
|
|
||||||
|
}
|
||||||
onProfileSimpleChanged(...args: unknown[]) {
|
onProfileSimpleChanged(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,19 +1,44 @@
|
|||||||
import { Friend } from '@/core/entities';
|
import { Friend } from '@/core/entities';
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
import { NodeIKernelBuddyListener } from '@/core/listeners';
|
import { NodeIKernelBuddyListener } from '@/core/listeners';
|
||||||
|
export enum BuddyListReqType {
|
||||||
|
KNOMAL,
|
||||||
|
KLETTER
|
||||||
|
}
|
||||||
export interface NodeIKernelBuddyService {
|
export interface NodeIKernelBuddyService {
|
||||||
// 以下为自行添加的,wrapper.node中并没有这些方法,目的是简化调用
|
// 26702 以上
|
||||||
friends: Friend[];
|
getBuddyListV2(callFrom: string, reqType: BuddyListReqType): Promise<GeneralCallResult & {
|
||||||
|
data: Array<{
|
||||||
getFriend(uidOrUin: string): Promise<Friend>;
|
categoryId: number,
|
||||||
|
categorySortId: number,
|
||||||
|
categroyName: string,
|
||||||
|
categroyMbCount: number,
|
||||||
|
onlineCount: number,
|
||||||
|
buddyUids: Array<string>
|
||||||
|
}>
|
||||||
|
}>;
|
||||||
|
//26702 以上
|
||||||
|
getBuddyListFromCache(callFrom: string): Promise<Array<
|
||||||
|
{
|
||||||
|
categoryId: number,//9999应该跳过 那是兜底数据吧
|
||||||
|
categorySortId: number,//排序方式
|
||||||
|
categroyName: string,//分类名
|
||||||
|
categroyMbCount: number,//不懂
|
||||||
|
onlineCount: number,//在线数目
|
||||||
|
buddyUids: Array<string>//Uids
|
||||||
|
}>>;
|
||||||
// 以下为原生方法
|
// 以下为原生方法
|
||||||
addKernelBuddyListener(listener: NodeIKernelBuddyListener): number;
|
addKernelBuddyListener(listener: NodeIKernelBuddyListener): number;
|
||||||
|
|
||||||
|
getAllBuddyCount(): number;
|
||||||
|
|
||||||
removeKernelBuddyListener(listener: unknown): void;
|
removeKernelBuddyListener(listener: unknown): void;
|
||||||
|
|
||||||
getBuddyList(bool: boolean): Promise<GeneralCallResult>;
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* @param nocache 使用缓存
|
||||||
|
*/
|
||||||
|
getBuddyList(nocache: boolean): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
getBuddyNick(uid: number): string;
|
getBuddyNick(uid: number): string;
|
||||||
|
|
||||||
|
3
src/core/src/services/NodeIKernelECDHService.ts
Normal file
3
src/core/src/services/NodeIKernelECDHService.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export interface NodeIKernelECDHService{
|
||||||
|
|
||||||
|
}
|
@@ -8,8 +8,90 @@ 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 {
|
||||||
setHeader(uid:string,path:string): unknown;
|
getMemberCommonInfo(Req: {
|
||||||
|
groupCode: string,
|
||||||
|
startUin: string,
|
||||||
|
identifyFlag: string,
|
||||||
|
uinList: string[],
|
||||||
|
memberCommonFilter: {
|
||||||
|
memberUin: number,
|
||||||
|
uinFlag: number,
|
||||||
|
uinFlagExt: number,
|
||||||
|
uinMobileFlag: number,
|
||||||
|
shutUpTime: number,
|
||||||
|
privilege: number,
|
||||||
|
},
|
||||||
|
memberNum: number,
|
||||||
|
filterMethod: string,
|
||||||
|
onlineFlag: string,
|
||||||
|
realSpecialTitleFlag: number
|
||||||
|
}): Promise<unknown>;
|
||||||
|
//26702
|
||||||
|
getGroupMemberLevelInfo(groupCode: string): Promise<unknown>;
|
||||||
|
//26702
|
||||||
|
getGroupHonorList(groupCodes: Array<string>): unknown;
|
||||||
|
|
||||||
|
getUinByUids(uins: string[]): Promise<{
|
||||||
|
errCode: number,
|
||||||
|
errMsg: string,
|
||||||
|
uins: Map<string, string>
|
||||||
|
}>;
|
||||||
|
|
||||||
|
getUidByUins(uins: string[]): Promise<{
|
||||||
|
errCode: number,
|
||||||
|
errMsg: string,
|
||||||
|
uids: Map<string, string>
|
||||||
|
}>;
|
||||||
|
//26702(其实更早 但是我不知道)
|
||||||
|
checkGroupMemberCache(arrayList: Array<string>): Promise<unknown>;
|
||||||
|
|
||||||
|
//26702(其实更早 但是我不知道)
|
||||||
|
getGroupLatestEssenceList(groupCode: string): Promise<unknown>;
|
||||||
|
|
||||||
|
//26702(其实更早 但是我不知道)
|
||||||
|
shareDigest(Req: {
|
||||||
|
appId: string,
|
||||||
|
appType: number,
|
||||||
|
msgStyle: number,
|
||||||
|
recvUin: string,
|
||||||
|
sendType: number,
|
||||||
|
clientInfo: {
|
||||||
|
platform: number
|
||||||
|
},
|
||||||
|
richMsg: {
|
||||||
|
usingArk: boolean,
|
||||||
|
title: string,
|
||||||
|
summary: string,
|
||||||
|
url: string,
|
||||||
|
pictureUrl: string,
|
||||||
|
brief: string
|
||||||
|
}
|
||||||
|
}): Promise<unknown>;
|
||||||
|
//26702(其实更早 但是我不知道)
|
||||||
|
isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
||||||
|
//26702(其实更早 但是我不知道)
|
||||||
|
queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
||||||
|
//26702(其实更早 但是我不知道)
|
||||||
|
fetchGroupEssenceList(Req: { groupCode: string, pageStart: number, pageLimit: number }, Arg: unknown): Promise<unknown>;
|
||||||
|
//26702
|
||||||
|
getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{
|
||||||
|
errCode: number,
|
||||||
|
errMsg: string,
|
||||||
|
result: {
|
||||||
|
ids: Array<{
|
||||||
|
uid: string,
|
||||||
|
index: number//0
|
||||||
|
}>,
|
||||||
|
infos: {},
|
||||||
|
finish: true,
|
||||||
|
hasRobot: false
|
||||||
|
}
|
||||||
|
}>;
|
||||||
|
|
||||||
|
setHeader(uid: string, path: string): unknown;
|
||||||
|
|
||||||
addKernelGroupListener(listener: NodeIKernelGroupListener): number;
|
addKernelGroupListener(listener: NodeIKernelGroupListener): number;
|
||||||
|
|
||||||
@@ -17,7 +99,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
createMemberListScene(groupCode: string, scene: string): string;
|
createMemberListScene(groupCode: string, scene: string): string;
|
||||||
|
|
||||||
destroyMemberListScene(): void;
|
destroyMemberListScene(SceneId:string): void;
|
||||||
//About Arg (a) name: lastId 根据手Q来看为object {index:?(number),uid:string}
|
//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,
|
||||||
@@ -28,9 +110,9 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
monitorMemberList(): unknown;
|
monitorMemberList(): unknown;
|
||||||
|
|
||||||
searchMember(uid: string): unknown;
|
searchMember(sceneId: string, keywords: string[]): unknown;
|
||||||
|
|
||||||
getMemberInfo(uid: string): unknown;
|
getMemberInfo(group_id: string, uids: string[], forceFetch: boolean): Promise<GeneralCallResult>;
|
||||||
//getMemberInfo [ '56729xxxx', [ 'u_4Nj08cwW5Hxxxxx' ], true ]
|
//getMemberInfo [ '56729xxxx', [ 'u_4Nj08cwW5Hxxxxx' ], true ]
|
||||||
|
|
||||||
kickMember(groupCode: string, memberUids: string[], refuseForever: boolean, kickReason: string): Promise<void>;
|
kickMember(groupCode: string, memberUids: string[], refuseForever: boolean, kickReason: string): Promise<void>;
|
||||||
@@ -39,7 +121,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
modifyMemberCardName(groupCode: string, uid: string, cardName: string): void;
|
modifyMemberCardName(groupCode: string, uid: string, cardName: string): void;
|
||||||
|
|
||||||
getTransferableMemberInfo(uid: string): unknown;
|
getTransferableMemberInfo(groupCode: string): unknown;//获取整个群的
|
||||||
|
|
||||||
transferGroup(uid: string): void;
|
transferGroup(uid: string): void;
|
||||||
|
|
||||||
|
@@ -2,10 +2,38 @@ import { ElementType, MessageElement, Peer, RawMessage, SendMessageElement } fro
|
|||||||
import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener';
|
import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener';
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
|
|
||||||
|
export interface QueryMsgsParams {
|
||||||
|
chatInfo: Peer,
|
||||||
|
filterMsgType: [],
|
||||||
|
filterSendersUid: string[],
|
||||||
|
filterMsgFromTime: string,
|
||||||
|
filterMsgToTime: string,
|
||||||
|
pageLimit: number,
|
||||||
|
isReverseOrder: boolean,
|
||||||
|
isIncludeCurrent: boolean
|
||||||
|
}
|
||||||
|
export interface 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 {
|
||||||
|
|
||||||
|
generateMsgUniqueId(chatType: number, time: string): string;
|
||||||
|
|
||||||
addKernelMsgListener(nodeIKernelMsgListener: NodeIKernelMsgListener): number;
|
addKernelMsgListener(nodeIKernelMsgListener: NodeIKernelMsgListener): number;
|
||||||
|
|
||||||
sendMsg(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map<any, any>): Promise<unknown>;
|
sendMsg(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map<any, any>): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
recallMsg(peer: Peer, msgIds: string[]): Promise<GeneralCallResult>;
|
recallMsg(peer: Peer, msgIds: string[]): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
@@ -84,8 +112,8 @@ export interface NodeIKernelMsgService {
|
|||||||
recallMsg(...args: unknown[]): unknown;
|
recallMsg(...args: unknown[]): unknown;
|
||||||
|
|
||||||
reeditRecallMsg(...args: unknown[]): unknown;
|
reeditRecallMsg(...args: unknown[]): unknown;
|
||||||
|
//调用请检查除开commentElements其余参数不能为null
|
||||||
forwardMsg(...args: unknown[]): Promise<GeneralCallResult>;
|
forwardMsg(msgIds: string[], srcContact: Peer, dstContacts: Peer[], commentElements: MessageElement[]): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
forwardMsgWithComment(...args: unknown[]): unknown;
|
forwardMsgWithComment(...args: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -117,7 +145,7 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
addLocalRecordMsg(Peer: Peer, msgId: string, ele: MessageElement, attr: Array<any> | number, front: boolean): Promise<unknown>;
|
addLocalRecordMsg(Peer: Peer, msgId: string, ele: MessageElement, attr: Array<any> | number, front: boolean): Promise<unknown>;
|
||||||
|
|
||||||
deleteMsg(...args: unknown[]): unknown;
|
deleteMsg(Peer: Peer, msgIds: Array<string>): Promise<any>;
|
||||||
|
|
||||||
updateElementExtBufForUI(...args: unknown[]): unknown;
|
updateElementExtBufForUI(...args: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -143,6 +171,7 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
getAioFirstViewLatestMsgs(peer: Peer, num: number): unknown;
|
getAioFirstViewLatestMsgs(peer: Peer, num: number): unknown;
|
||||||
|
|
||||||
|
//deprecated 从9.9.15-26702版本开始,该接口已经废弃,请使用getMsgsEx
|
||||||
getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise<unknown>;
|
getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise<unknown>;
|
||||||
|
|
||||||
getMsgsIncludeSelf(peer: Peer, msgId: string, count: number, queryOrder: boolean): Promise<GeneralCallResult & {
|
getMsgsIncludeSelf(peer: Peer, msgId: string, count: number, queryOrder: boolean): Promise<GeneralCallResult & {
|
||||||
@@ -178,14 +207,14 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
getSingleMsg(Peer: Peer, msgSeq: string): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
getSingleMsg(Peer: Peer, msgSeq: string): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||||
|
|
||||||
getSourceOfReplyMsg(...args: unknown[]): unknown;
|
getSourceOfReplyMsg(peer: Peer, MsgId: string, SourceSeq: string): unknown;
|
||||||
|
|
||||||
getSourceOfReplyMsgV2(...args: unknown[]): unknown;
|
getSourceOfReplyMsgV2(peer: Peer, RootMsgId: string, ReplyMsgId: string): unknown;
|
||||||
|
|
||||||
getMsgByClientSeqAndTime(...args: unknown[]): unknown;
|
getMsgByClientSeqAndTime(peer: Peer, clientSeq: string, time: string): unknown;
|
||||||
|
|
||||||
getSourceOfReplyMsgByClientSeqAndTime(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
|
getSourceOfReplyMsgByClientSeqAndTime(peer: Peer, clientSeq: string, time: string): unknown;
|
||||||
|
//cnt clientSeq?并不是吧
|
||||||
getMsgsByTypeFilter(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilter: { type: number, subtype: Array<number> }): unknown;
|
getMsgsByTypeFilter(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilter: { type: number, subtype: Array<number> }): unknown;
|
||||||
|
|
||||||
getMsgsByTypeFilters(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilters: Array<{ type: number, subtype: Array<number> }>): unknown;
|
getMsgsByTypeFilters(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilters: Array<{ type: number, subtype: Array<number> }>): unknown;
|
||||||
@@ -214,19 +243,7 @@ export interface NodeIKernelMsgService {
|
|||||||
* @param param.isIncludeCurrent 是否包含当前页码。
|
* @param param.isIncludeCurrent 是否包含当前页码。
|
||||||
* @returns 返回一个Promise,解析为查询结果的未知类型对象。
|
* @returns 返回一个Promise,解析为查询结果的未知类型对象。
|
||||||
*/
|
*/
|
||||||
queryMsgsWithFilterVer2(MsgId: string, MsgTime: string, param: {
|
queryMsgsWithFilterVer2(MsgId: string, MsgTime: string, param: QueryMsgsParams): Promise<unknown>;
|
||||||
chatInfo: {
|
|
||||||
chatType: number,
|
|
||||||
peerUid: string
|
|
||||||
},
|
|
||||||
filterMsgType: [],
|
|
||||||
filterSendersUid: Array<string>,
|
|
||||||
filterMsgFromTime: string,
|
|
||||||
filterMsgToTime: string,
|
|
||||||
pageLimit: number,
|
|
||||||
isReverseOrder: boolean,
|
|
||||||
isIncludeCurrent: boolean
|
|
||||||
}): Promise<unknown>;
|
|
||||||
|
|
||||||
// this.chatType = i2;
|
// this.chatType = i2;
|
||||||
// this.peerUid = str;
|
// this.peerUid = str;
|
||||||
@@ -243,19 +260,7 @@ export interface NodeIKernelMsgService {
|
|||||||
// this.isReverseOrder = z;
|
// this.isReverseOrder = z;
|
||||||
// this.isIncludeCurrent = z2;
|
// this.isIncludeCurrent = z2;
|
||||||
//queryMsgsWithFilterEx(0L, 0L, 0L, new QueryMsgsParams(new ChatInfo(2, str), new ArrayList(), new ArrayList(), 0L, 0L, 250, false, true))
|
//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: {
|
queryMsgsWithFilterEx(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): Promise<GeneralCallResult & {
|
||||||
chatInfo: {
|
|
||||||
chatType: number,
|
|
||||||
peerUid: string
|
|
||||||
},
|
|
||||||
filterMsgType: [],
|
|
||||||
filterSendersUid: string[],
|
|
||||||
filterMsgFromTime: string,
|
|
||||||
filterMsgToTime: string,
|
|
||||||
pageLimit: number,
|
|
||||||
isReverseOrder: boolean,
|
|
||||||
isIncludeCurrent: boolean
|
|
||||||
}): Promise<GeneralCallResult & {
|
|
||||||
msgList: RawMessage[]
|
msgList: RawMessage[]
|
||||||
}>;
|
}>;
|
||||||
//queryMsgsWithFilterEx(this.$msgId, this.$msgTime, this.$msgSeq, this.$param)
|
//queryMsgsWithFilterEx(this.$msgId, this.$msgTime, this.$msgSeq, this.$param)
|
||||||
@@ -263,39 +268,15 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
setMsgRichInfoFlag(...args: unknown[]): unknown;
|
setMsgRichInfoFlag(...args: unknown[]): unknown;
|
||||||
|
|
||||||
queryPicOrVideoMsgs(msgId: string, msgTime: string, megSeq: string, param: {
|
queryPicOrVideoMsgs(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): Promise<unknown>;
|
||||||
chatInfo: {
|
|
||||||
chatType: number,
|
|
||||||
peerUid: string
|
|
||||||
},
|
|
||||||
filterMsgType: [],
|
|
||||||
filterSendersUid: [],
|
|
||||||
filterMsgFromTime: string,
|
|
||||||
filterMsgToTime: string,
|
|
||||||
pageLimit: number,
|
|
||||||
isReverseOrder: boolean,
|
|
||||||
isIncludeCurrent: boolean
|
|
||||||
}): Promise<unknown>;
|
|
||||||
|
|
||||||
queryPicOrVideoMsgsDesktop(...args: unknown[]): unknown;
|
queryPicOrVideoMsgsDesktop(...args: unknown[]): unknown;
|
||||||
|
|
||||||
queryEmoticonMsgs(...args: unknown[]): unknown;
|
queryEmoticonMsgs(msgId: string, msgTime: string, msgSeq: string, Params: QueryMsgsParams): Promise<unknown>;
|
||||||
|
|
||||||
queryTroopEmoticonMsgs(...args: unknown[]): unknown;
|
queryTroopEmoticonMsgs(msgId: string, msgTime: string, msgSeq: string, Params: QueryMsgsParams): Promise<unknown>;
|
||||||
|
|
||||||
queryMsgsAndAbstractsWithFilter(msgId: string, msgTime: string, megSeq: string, param: {
|
queryMsgsAndAbstractsWithFilter(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): unknown;
|
||||||
chatInfo: {
|
|
||||||
chatType: number,
|
|
||||||
peerUid: string
|
|
||||||
},
|
|
||||||
filterMsgType: [],
|
|
||||||
filterSendersUid: [],
|
|
||||||
filterMsgFromTime: string,
|
|
||||||
filterMsgToTime: string,
|
|
||||||
pageLimit: number,
|
|
||||||
isReverseOrder: boolean,
|
|
||||||
isIncludeCurrent: boolean
|
|
||||||
}): unknown;
|
|
||||||
|
|
||||||
setFocusOnGuild(...args: unknown[]): unknown;
|
setFocusOnGuild(...args: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -512,7 +493,19 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
setMsgEmojiLikes(...args: unknown[]): unknown;
|
setMsgEmojiLikes(...args: unknown[]): unknown;
|
||||||
|
|
||||||
getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, cookie: string, bForward: boolean, number: number): Promise<unknown>;
|
getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, cookie: string, bForward: boolean, number: number): Promise<{
|
||||||
|
result: number,
|
||||||
|
errMsg: string,
|
||||||
|
emojiLikesList:
|
||||||
|
Array<{
|
||||||
|
tinyId: string,
|
||||||
|
nickName: string,
|
||||||
|
headUrl: string
|
||||||
|
}>,
|
||||||
|
cookie: string,
|
||||||
|
isLastPage: boolean,
|
||||||
|
isFirstPage: boolean
|
||||||
|
}>;
|
||||||
|
|
||||||
setMsgEmojiLikesForRole(...args: unknown[]): unknown;
|
setMsgEmojiLikesForRole(...args: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -534,7 +527,7 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
queryCalendar(...args: unknown[]): unknown;
|
queryCalendar(...args: unknown[]): unknown;
|
||||||
|
|
||||||
queryFirstMsgSeq(...args: unknown[]): unknown;
|
queryFirstMsgSeq(peer: Peer, ...args: unknown[]): unknown;
|
||||||
|
|
||||||
queryRoamCalendar(...args: unknown[]): unknown;
|
queryRoamCalendar(...args: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -628,8 +621,10 @@ export interface NodeIKernelMsgService {
|
|||||||
// this.gameSession = tempChatGameSession;
|
// this.gameSession = tempChatGameSession;
|
||||||
prepareTempChat(args: unknown): unknown;//主动临时消息 不做
|
prepareTempChat(args: unknown): unknown;//主动临时消息 不做
|
||||||
|
|
||||||
|
sendSsoCmdReqByContend(cmd: string, param: string): Promise<unknown>;
|
||||||
|
|
||||||
//chattype,uid->Promise<any>
|
//chattype,uid->Promise<any>
|
||||||
getTempChatInfo(ChatType: number, Uid: string): unknown;
|
getTempChatInfo(ChatType: number, Uid: string): Promise<TmpChatInfoApi>;
|
||||||
|
|
||||||
setContactLocalTop(...args: unknown[]): unknown;
|
setContactLocalTop(...args: unknown[]): unknown;
|
||||||
|
|
||||||
|
@@ -1,10 +1,36 @@
|
|||||||
import { AnyCnameRecord } from 'node:dns';
|
import { AnyCnameRecord } from 'node:dns';
|
||||||
import { BizKey, ModifyProfileParams, UserDetailInfoByUin } from '../entities';
|
import { BaseInfo, BizKey, CoreInfo, ModifyProfileParams, SimpleInfo, UserDetailInfoByUin } from '../entities';
|
||||||
import { NodeIKernelProfileListener } from '../listeners';
|
import { NodeIKernelProfileListener } from '../listeners';
|
||||||
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 {
|
||||||
|
|
||||||
|
getUidByUin(callfrom: string, uin: Array<string>): Promise<Map<string,string>>;//uin->uid
|
||||||
|
|
||||||
|
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>>;
|
||||||
|
|
||||||
|
fetchUserDetailInfo(trace: string, uids: string[], arg2: number, arg3: number[]): Promise<unknown>;
|
||||||
|
|
||||||
addKernelProfileListener(listener: NodeIKernelProfileListener): number;
|
addKernelProfileListener(listener: NodeIKernelProfileListener): number;
|
||||||
|
|
||||||
removeKernelProfileListener(listenerId: number): void;
|
removeKernelProfileListener(listenerId: number): void;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { 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";
|
||||||
export interface FSABRecentContactParams {
|
export interface FSABRecentContactParams {
|
||||||
@@ -39,7 +39,13 @@ export interface NodeIKernelRecentContactService {
|
|||||||
errCode: number,
|
errCode: number,
|
||||||
errMsg: string,
|
errMsg: string,
|
||||||
sortedContactList: Array<number>,
|
sortedContactList: Array<number>,
|
||||||
changedList: Array<any>
|
changedList: Array<{
|
||||||
|
remark: any;
|
||||||
|
peerName: any;
|
||||||
|
sendMemberName: any;
|
||||||
|
sendNickName: any;
|
||||||
|
peerUid: string; peerUin: string, msgTime: string, chatType: ChatType, msgId: string
|
||||||
|
}>
|
||||||
}
|
}
|
||||||
}>; // 1 arguments
|
}>; // 1 arguments
|
||||||
|
|
||||||
|
@@ -200,8 +200,6 @@ export interface NodeIKernelRichMediaService {
|
|||||||
|
|
||||||
getGroupFileInfo(arg1: unknown, arg2: unknown): unknown;
|
getGroupFileInfo(arg1: unknown, arg2: unknown): unknown;
|
||||||
|
|
||||||
getGroupFileList(arg1: unknown, arg2: unknown): unknown;
|
|
||||||
|
|
||||||
getGroupTransferList(arg1: unknown, arg2: unknown): unknown;
|
getGroupTransferList(arg1: unknown, arg2: unknown): unknown;
|
||||||
|
|
||||||
renameGroupFile(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown, arg5: unknown): unknown;
|
renameGroupFile(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown, arg5: unknown): unknown;
|
||||||
|
@@ -21,7 +21,7 @@ export interface NodeIKernelRobotService {
|
|||||||
|
|
||||||
removeKernelRobotListener(ListenerId: number): unknown;
|
removeKernelRobotListener(ListenerId: number): unknown;
|
||||||
|
|
||||||
getAllRobotFriendsFromCache(): unknown;
|
getAllRobotFriendsFromCache(): Promise<unknown>;
|
||||||
|
|
||||||
fetchAllRobots(arg1: unknown, arg2: unknown): unknown;
|
fetchAllRobots(arg1: unknown, arg2: unknown): unknown;
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
export interface NodeIKernelUixConvertService {
|
export interface NodeIKernelUixConvertService {
|
||||||
getUin(uid: string[]): Promise<{ uidInfo: Map<string, string> }>;
|
getUin(uid: string[]): Promise<{ uinInfo: Map<string, string> }>;
|
||||||
|
|
||||||
getUid(uin: string[]): Promise<{ uinInfo: Map<string, string> }>;
|
getUid(uin: string[]): Promise<{ uidInfo: Map<string, string> }>;
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import { appid, qqPkgInfo, qqVersionConfigInfo } from '@/common/utils/QQBasicInfo';
|
import { getFullQQVesion, QQVersionAppid } from '@/common/utils/QQBasicInfo';
|
||||||
import { hostname, systemName, systemVersion } from '@/common/utils/system';
|
import { hostname, systemName, systemVersion } from '@/common/utils/system';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
@@ -34,42 +34,42 @@ export interface WrapperSessionInitConfig {
|
|||||||
account_path: string // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
account_path: string // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
||||||
}
|
}
|
||||||
clientVer: string // 9.9.8-22355
|
clientVer: string // 9.9.8-22355
|
||||||
a2: '',
|
a2: string,
|
||||||
d2: '',
|
d2: string,
|
||||||
d2Key: '',
|
d2Key: string,
|
||||||
machineId: '',
|
machineId: string,
|
||||||
platform: 3, // 3是Windows?
|
platform: PlatformType, // 3是Windows?
|
||||||
platVer: string, // 系统版本号, 应该可以固定
|
platVer: string, // 系统版本号, 应该可以固定
|
||||||
appid: string,
|
appid: string,
|
||||||
rdeliveryConfig: {
|
rdeliveryConfig: {
|
||||||
appKey: '',
|
appKey: string,
|
||||||
systemId: 0,
|
systemId: number,
|
||||||
appId: '',
|
appId: string,
|
||||||
logicEnvironment: '',
|
logicEnvironment: string,
|
||||||
platform: 3,
|
platform: PlatformType,
|
||||||
language: '',
|
language: string,
|
||||||
sdkVersion: '',
|
sdkVersion: string,
|
||||||
userId: '',
|
userId: string,
|
||||||
appVersion: '',
|
appVersion: string,
|
||||||
osVersion: '',
|
osVersion: string,
|
||||||
bundleId: '',
|
bundleId: string,
|
||||||
serverUrl: '',
|
serverUrl: string,
|
||||||
fixedAfterHitKeys: ['']
|
fixedAfterHitKeys: string[]
|
||||||
}
|
}
|
||||||
'defaultFileDownloadPath': string, // 这个可以通过环境变量获取?
|
defaultFileDownloadPath: string, // 这个可以通过环境变量获取?
|
||||||
'deviceInfo': {
|
deviceInfo: {
|
||||||
'guid': string,
|
guid: string,
|
||||||
'buildVer': string,
|
buildVer: string,
|
||||||
'localId': 2052,
|
localId: number,
|
||||||
'devName': string,
|
devName: string,
|
||||||
'devType': string,
|
devType: string,
|
||||||
'vendorName': '',
|
vendorName: string,
|
||||||
'osVer': string,
|
osVer: string,
|
||||||
'vendorOsName': string,
|
vendorOsName: string,
|
||||||
'setMute': false,
|
setMute: boolean,
|
||||||
'vendorType': 0
|
vendorType: VendorType
|
||||||
},
|
},
|
||||||
'deviceConfig': '{"appearance":{"isSplitViewMode":true},"msg":{}}'
|
deviceConfig: '{"appearance":{"isSplitViewMode":true},"msg":{}}'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sessionConfig: WrapperSessionInitConfig | any = {};
|
export const sessionConfig: WrapperSessionInitConfig | any = {};
|
||||||
@@ -77,9 +77,9 @@ export const sessionConfig: WrapperSessionInitConfig | any = {};
|
|||||||
export async function genSessionConfig(selfUin: string, selfUid: string, account_path: string): Promise<WrapperSessionInitConfig> {
|
export async function genSessionConfig(selfUin: string, selfUid: string, account_path: string): Promise<WrapperSessionInitConfig> {
|
||||||
const downloadPath = path.join(account_path, 'NapCat', 'temp');
|
const downloadPath = path.join(account_path, 'NapCat', 'temp');
|
||||||
fs.mkdirSync(downloadPath, { recursive: true });
|
fs.mkdirSync(downloadPath, { recursive: true });
|
||||||
let guid: string = await getMachineId();
|
let guid: string = await getMachineId();//26702 支持JS获取guid值 在LoginService中获取 TODO mlikiow a
|
||||||
//console.log(guid);
|
//console.log(guid);
|
||||||
// guid = '52afb776-82f6-4e59-9d38-44705b112d0a';
|
// guid = '52afb776-82f6-4e59-9d38-44705b112d0a';
|
||||||
//let guid: string = await getMachineId();
|
//let guid: string = await getMachineId();
|
||||||
const config: WrapperSessionInitConfig = {
|
const config: WrapperSessionInitConfig = {
|
||||||
selfUin,
|
selfUin,
|
||||||
@@ -87,20 +87,20 @@ export async function genSessionConfig(selfUin: string, selfUid: string, account
|
|||||||
desktopPathConfig: {
|
desktopPathConfig: {
|
||||||
account_path // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
account_path // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
||||||
},
|
},
|
||||||
clientVer: qqVersionConfigInfo.curVersion, // 9.9.8-22355
|
clientVer: getFullQQVesion(), // 9.9.8-22355
|
||||||
a2: '',
|
a2: '',
|
||||||
d2: '',
|
d2: '',
|
||||||
d2Key: '',
|
d2Key: '',
|
||||||
machineId: '',
|
machineId: '',
|
||||||
platform: 3, // 3是Windows?
|
platform: PlatformType.KWINDOWS, // 3是Windows?
|
||||||
platVer: systemVersion, // 系统版本号, 应该可以固定
|
platVer: systemVersion, // 系统版本号, 应该可以固定
|
||||||
appid: appid,
|
appid: QQVersionAppid,
|
||||||
rdeliveryConfig: {
|
rdeliveryConfig: {
|
||||||
appKey: '',
|
appKey: '',
|
||||||
systemId: 0,
|
systemId: 0,
|
||||||
appId: '',
|
appId: '',
|
||||||
logicEnvironment: '',
|
logicEnvironment: '',
|
||||||
platform: 3,
|
platform: PlatformType.KWINDOWS,
|
||||||
language: '',
|
language: '',
|
||||||
sdkVersion: '',
|
sdkVersion: '',
|
||||||
userId: '',
|
userId: '',
|
||||||
@@ -110,22 +110,21 @@ export async function genSessionConfig(selfUin: string, selfUid: string, account
|
|||||||
serverUrl: '',
|
serverUrl: '',
|
||||||
fixedAfterHitKeys: ['']
|
fixedAfterHitKeys: ['']
|
||||||
},
|
},
|
||||||
'defaultFileDownloadPath': downloadPath,
|
defaultFileDownloadPath: downloadPath,
|
||||||
'deviceInfo': {
|
deviceInfo: {
|
||||||
guid,
|
guid,
|
||||||
'buildVer': qqPkgInfo.version,
|
buildVer: getFullQQVesion(),
|
||||||
'localId': 2052,
|
localId: 2052,
|
||||||
'devName': hostname,
|
devName: hostname,
|
||||||
'devType': systemName,
|
devType: systemName,
|
||||||
'vendorName': '',
|
vendorName: '',
|
||||||
'osVer': systemVersion,
|
osVer: systemVersion,
|
||||||
'vendorOsName': systemName,
|
vendorOsName: systemName,
|
||||||
'setMute': false,
|
setMute: false,
|
||||||
'vendorType': 0
|
vendorType: VendorType.KNOSETONIOS
|
||||||
},
|
},
|
||||||
'deviceConfig': '{"appearance":{"isSplitViewMode":true},"msg":{}}'
|
deviceConfig: '{"appearance":{"isSplitViewMode":true},"msg":{}}'
|
||||||
};
|
};
|
||||||
Object.assign(sessionConfig, config);
|
Object.assign(sessionConfig, config);
|
||||||
// log(sessionConfig);
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,6 @@ import {
|
|||||||
NodeIKernelRichMediaService,
|
NodeIKernelRichMediaService,
|
||||||
NodeIKernelAvatarService,
|
NodeIKernelAvatarService,
|
||||||
} from './services';
|
} from './services';
|
||||||
import { qqVersionConfigInfo } from '@/common/utils/QQBasicInfo';
|
|
||||||
import { NodeIKernelStorageCleanService } from './services/NodeIKernelStorageCleanService';
|
import { NodeIKernelStorageCleanService } from './services/NodeIKernelStorageCleanService';
|
||||||
import { NodeIKernelRobotService } from './services/NodeIKernelRobotService';
|
import { NodeIKernelRobotService } from './services/NodeIKernelRobotService';
|
||||||
import { dirname } from "node:path"
|
import { dirname } from "node:path"
|
||||||
@@ -42,6 +41,8 @@ import { NodeIKernelCollectionService } from './services/NodeIKernelCollectionSe
|
|||||||
import { NodeIKernelRecentContactService } from './services/NodeIKernelRecentContactService';
|
import { NodeIKernelRecentContactService } from './services/NodeIKernelRecentContactService';
|
||||||
import { NodeIKernelMSFService } from './services/NodeIKernelMSFService';
|
import { NodeIKernelMSFService } from './services/NodeIKernelMSFService';
|
||||||
import { NodeIkernelTestPerformanceService } from './services/NodeIkernelTestPerformanceService';
|
import { NodeIkernelTestPerformanceService } from './services/NodeIkernelTestPerformanceService';
|
||||||
|
import { NodeIKernelECDHService } from './services/NodeIKernelECDHService';
|
||||||
|
import { getFullQQVesion } from '@/common/utils/QQBasicInfo';
|
||||||
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
@@ -157,6 +158,10 @@ export interface NodeIQQNTWrapperSession {
|
|||||||
|
|
||||||
startNT(): void;
|
startNT(): void;
|
||||||
|
|
||||||
|
getBdhUploadService(): unknown;
|
||||||
|
|
||||||
|
getECDHService(): NodeIKernelECDHService;
|
||||||
|
|
||||||
getMsgService(): NodeIKernelMsgService;
|
getMsgService(): NodeIKernelMsgService;
|
||||||
|
|
||||||
getProfileService(): NodeIKernelProfileService;
|
getProfileService(): NodeIKernelProfileService;
|
||||||
@@ -287,7 +292,7 @@ export interface WrapperNodeApi {
|
|||||||
|
|
||||||
let wrapperNodePath = path.resolve(path.dirname(process.execPath), './resources/app/wrapper.node');
|
let wrapperNodePath = path.resolve(path.dirname(process.execPath), './resources/app/wrapper.node');
|
||||||
if (!fs.existsSync(wrapperNodePath)) {
|
if (!fs.existsSync(wrapperNodePath)) {
|
||||||
wrapperNodePath = path.join(path.dirname(process.execPath), `resources/app/versions/${qqVersionConfigInfo.curVersion}/wrapper.node`);
|
wrapperNodePath = path.join(path.dirname(process.execPath), `resources/app/versions/${getFullQQVesion()}/wrapper.node`);
|
||||||
}
|
}
|
||||||
const nativemodule: any = { exports: {} };
|
const nativemodule: any = { exports: {} };
|
||||||
process.dlopen(nativemodule, wrapperNodePath);
|
process.dlopen(nativemodule, wrapperNodePath);
|
||||||
|
@@ -92,9 +92,9 @@ napCatCore.getQuickLoginList().then((res) => {
|
|||||||
|
|
||||||
WebUiDataRuntime.setQQQuickLoginCall(async (uin: string) => {
|
WebUiDataRuntime.setQQQuickLoginCall(async (uin: string) => {
|
||||||
const QuickLogin: Promise<{ result: boolean, message: string }> = new Promise((resolve, reject) => {
|
const QuickLogin: Promise<{ result: boolean, message: string }> = new Promise((resolve, reject) => {
|
||||||
if (quickLoginQQ) {
|
if (uin) {
|
||||||
log('正在快速登录 ', quickLoginQQ);
|
log('正在快速登录 ', uin);
|
||||||
napCatCore.quickLogin(quickLoginQQ).then(res => {
|
napCatCore.quickLogin(uin).then(res => {
|
||||||
if (res.loginErrorInfo.errMsg) {
|
if (res.loginErrorInfo.errMsg) {
|
||||||
resolve({ result: false, message: res.loginErrorInfo.errMsg });
|
resolve({ result: false, message: res.loginErrorInfo.errMsg });
|
||||||
}
|
}
|
||||||
|
4
src/nwebui/Readme.md
Normal file
4
src/nwebui/Readme.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# NewWebui
|
||||||
|
基于Vue3实现的现代化轻量化NapCat管理面板
|
||||||
|
## 进度
|
||||||
|
画饼
|
@@ -2,7 +2,6 @@
|
|||||||
import { NTQQCollectionApi } from '@/core/apis/collection';
|
import { NTQQCollectionApi } from '@/core/apis/collection';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { NTQQUserApi } from '@/core/apis';
|
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { selfInfo } from '@/core/data';
|
import { selfInfo } from '@/core/data';
|
||||||
|
|
||||||
|
@@ -1,16 +1,12 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
// import * as ntqqApi from "../../../ntqqapi/api";
|
|
||||||
import {
|
import {
|
||||||
NTQQMsgApi,
|
NTQQMsgApi,
|
||||||
NTQQFriendApi,
|
NTQQFriendApi,
|
||||||
NTQQGroupApi,
|
NTQQGroupApi,
|
||||||
NTQQUserApi,
|
NTQQUserApi,
|
||||||
NTQQFileApi,
|
NTQQFileApi,
|
||||||
// NTQQFileCacheApi,
|
|
||||||
} from '@/core';
|
} from '@/core';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { log, logDebug } from '@/common/utils/log';
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
method: string,
|
method: string,
|
||||||
args: any[],
|
args: any[],
|
||||||
@@ -20,12 +16,8 @@ export default class Debug extends BaseAction<Payload, any> {
|
|||||||
actionName = ActionName.Debug;
|
actionName = ActionName.Debug;
|
||||||
|
|
||||||
protected async _handle(payload: Payload): Promise<any> {
|
protected async _handle(payload: Payload): Promise<any> {
|
||||||
//logDebug('debug call ntqq api', payload);
|
const ntqqApi = [NTQQMsgApi, NTQQFriendApi, NTQQGroupApi, NTQQUserApi, NTQQFileApi,];
|
||||||
const ntqqApi = [NTQQMsgApi, NTQQFriendApi, NTQQGroupApi, NTQQUserApi, NTQQFileApi,
|
|
||||||
// NTQQFileCacheApi,
|
|
||||||
];
|
|
||||||
for (const ntqqApiClass of ntqqApi) {
|
for (const ntqqApiClass of ntqqApi) {
|
||||||
// logDebug('ntqqApiClass', ntqqApiClass);
|
|
||||||
const method = (<any>ntqqApiClass)[payload.method];
|
const method = (<any>ntqqApiClass)[payload.method];
|
||||||
if (method) {
|
if (method) {
|
||||||
const result = method(...payload.args);
|
const result = method(...payload.args);
|
||||||
@@ -36,8 +28,5 @@ export default class Debug extends BaseAction<Payload, any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw `${payload.method}方法 不存在`;
|
throw `${payload.method}方法 不存在`;
|
||||||
|
|
||||||
// const info = await NTQQApi.getUserDetailInfo(friends[0].uid);
|
|
||||||
// return info
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ export class FetchCustomFace extends BaseAction<Payload, string[]> {
|
|||||||
actionName = ActionName.FetchCustomFace;
|
actionName = ActionName.FetchCustomFace;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
|
//48 可能正好是QQ需要的一个页面的数量 Tagged Mlikiowa
|
||||||
const ret = await NTQQMsgApi.fetchFavEmojiList(payload.count || 48);
|
const ret = await NTQQMsgApi.fetchFavEmojiList(payload.count || 48);
|
||||||
return ret.emojiInfoList.map(e => e.url);
|
return ret.emojiInfoList.map(e => e.url);
|
||||||
}
|
}
|
||||||
|
32
src/onebot11/action/extends/FetchEmojioLike.ts
Normal file
32
src/onebot11/action/extends/FetchEmojioLike.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
//getMsgEmojiLikesList
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName } from '../types';
|
||||||
|
import { NTQQMsgApi } from '@/core/apis';
|
||||||
|
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||||
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
user_id: { type: 'string' },
|
||||||
|
group_id: { type: 'string' },
|
||||||
|
emojiId: { type: 'string' },
|
||||||
|
emojiType: { type: 'string' },
|
||||||
|
message_id: { type: ['string', 'number'] },
|
||||||
|
count: { type: 'number' }
|
||||||
|
},
|
||||||
|
required: ['emojiId', 'emojiType', 'message_id']
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export class FetchEmojioLike extends BaseAction<Payload, any> {
|
||||||
|
actionName = ActionName.FetchEmojioLike;
|
||||||
|
PayloadSchema = SchemaData;
|
||||||
|
protected async _handle(payload: Payload) {
|
||||||
|
const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
|
||||||
|
if (!msgIdPeer) throw new Error('消息不存在');
|
||||||
|
const msg = (await NTQQMsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0];
|
||||||
|
const ret = await NTQQMsgApi.getMsgEmojiLikesList(msgIdPeer.Peer, msg.msgSeq, payload.emojiId, payload.emojiType, payload.count);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
@@ -2,9 +2,7 @@
|
|||||||
import { NTQQCollectionApi } from '@/core/apis/collection';
|
import { NTQQCollectionApi } from '@/core/apis/collection';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { NTQQUserApi } from '@/core/apis';
|
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { selfInfo } from '@/core/data';
|
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
@@ -1,12 +1,19 @@
|
|||||||
import { rawFriends } from '@/core/data';
|
import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { BuddyCategoryType } from '@/core/entities/';
|
import { BuddyCategoryType } from '@/core/entities/';
|
||||||
|
import { NTQQFriendApi } from '@/core';
|
||||||
|
import { OB11Constructor } from '@/onebot11/constructor';
|
||||||
|
|
||||||
export class GetFriendWithCategory extends BaseAction<void, Array<BuddyCategoryType>> {
|
export class GetFriendWithCategory extends BaseAction<void, any> {
|
||||||
actionName = ActionName.GetFriendsWithCategory;
|
actionName = ActionName.GetFriendsWithCategory;
|
||||||
|
|
||||||
protected async _handle(payload: void) {
|
protected async _handle(payload: void) {
|
||||||
return rawFriends;
|
if (requireMinNTQQBuild('26702')) {
|
||||||
|
//全新逻辑
|
||||||
|
return OB11Constructor.friendsV2(await NTQQFriendApi.getBuddyV2ExWithCate(true));
|
||||||
|
} else {
|
||||||
|
throw new Error('this ntqq version not support, must be 26702 or later');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,6 @@ export class GetRobotUinRange extends BaseAction<void, Array<any>> {
|
|||||||
actionName = ActionName.GetRobotUinRange;
|
actionName = ActionName.GetRobotUinRange;
|
||||||
|
|
||||||
protected async _handle(payload: void) {
|
protected async _handle(payload: void) {
|
||||||
// console.log(await NTQQUserApi.getRobotUinRange());
|
|
||||||
return await NTQQUserApi.getRobotUinRange();
|
return await NTQQUserApi.getRobotUinRange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,8 +20,8 @@ export class OCRImage extends BaseAction<Payload, any> {
|
|||||||
actionName = ActionName.OCRImage;
|
actionName = ActionName.OCRImage;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
const { path, isLocal, errMsg } = (await uri2local(payload.image));
|
const { path, isLocal, errMsg, success } = (await uri2local(payload.image));
|
||||||
if (errMsg) {
|
if (!success) {
|
||||||
throw `OCR ${payload.image}失败,image字段可能格式不正确`;
|
throw `OCR ${payload.image}失败,image字段可能格式不正确`;
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName, BaseCheckResult } from '../types';
|
import { ActionName, BaseCheckResult } from '../types';
|
||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
import { NTQQUserApi } from '@/core/apis/user';
|
|
||||||
import { checkFileReceived, uri2local } from '@/common/utils/file';
|
import { checkFileReceived, uri2local } from '@/common/utils/file';
|
||||||
import { NTQQGroupApi } from '@/core';
|
import { NTQQGroupApi } from '@/core';
|
||||||
// import { log } from "../../../common/utils";
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
file: string,
|
file: string,
|
||||||
@@ -26,8 +24,8 @@ export default class SetGroupHeader extends BaseAction<Payload, any> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
protected async _handle(payload: Payload): Promise<any> {
|
protected async _handle(payload: Payload): Promise<any> {
|
||||||
const { path, isLocal, errMsg } = (await uri2local(payload.file));
|
const { path, isLocal, errMsg,success } = (await uri2local(payload.file));
|
||||||
if (errMsg) {
|
if (!success) {
|
||||||
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { NTQQUserApi } from '@/core/apis';
|
import { NTQQUserApi } from '@/core/apis';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName, BaseCheckResult } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { NTQQUserApi } from '@/core/apis';
|
import { NTQQUserApi } from '@/core/apis';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
// 设置在线状态
|
// 设置在线状态
|
||||||
@@ -20,12 +20,6 @@ export class SetOnlineStatus extends BaseAction<Payload, null> {
|
|||||||
actionName = ActionName.SetOnlineStatus;
|
actionName = ActionName.SetOnlineStatus;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
// 可设置状态
|
|
||||||
// { status: 10, extStatus: 1027, batteryStatus: 0 }
|
|
||||||
// { status: 30, extStatus: 0, batteryStatus: 0 }
|
|
||||||
// { status: 50, extStatus: 0, batteryStatus: 0 }
|
|
||||||
// { status: 60, extStatus: 0, batteryStatus: 0 }
|
|
||||||
// { status: 70, extStatus: 0, batteryStatus: 0 }
|
|
||||||
const ret = await NTQQUserApi.setSelfOnlineStatus(payload.status, payload.extStatus, payload.batteryStatus);
|
const ret = await NTQQUserApi.setSelfOnlineStatus(payload.status, payload.extStatus, payload.batteryStatus);
|
||||||
if (ret.result !== 0) {
|
if (ret.result !== 0) {
|
||||||
throw new Error('设置在线状态失败');
|
throw new Error('设置在线状态失败');
|
||||||
|
@@ -3,7 +3,6 @@ import { ActionName, BaseCheckResult } from '../types';
|
|||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
import { NTQQUserApi } from '@/core/apis/user';
|
import { NTQQUserApi } from '@/core/apis/user';
|
||||||
import { checkFileReceived, uri2local } from '@/common/utils/file';
|
import { checkFileReceived, uri2local } from '@/common/utils/file';
|
||||||
// import { log } from "../../../common/utils";
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
file: string
|
file: string
|
||||||
@@ -24,8 +23,8 @@ export default class SetAvatar extends BaseAction<Payload, null> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
protected async _handle(payload: Payload): Promise<null> {
|
protected async _handle(payload: Payload): Promise<null> {
|
||||||
const { path, isLocal, errMsg } = (await uri2local(payload.file));
|
const { path, isLocal, errMsg, success } = (await uri2local(payload.file));
|
||||||
if (errMsg) {
|
if (!success) {
|
||||||
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
|
26
src/onebot11/action/extends/TestApi01.ts
Normal file
26
src/onebot11/action/extends/TestApi01.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName, BaseCheckResult } from '../types';
|
||||||
|
import { napCatCore, NTQQGroupApi } from '@/core';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
cmd: { type: 'string' },
|
||||||
|
param: { type: 'string' }
|
||||||
|
},
|
||||||
|
required: ['cmd', 'param'],
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export default class TestApi01 extends BaseAction<Payload, any> {
|
||||||
|
actionName = ActionName.TestApi01;
|
||||||
|
// 用不着复杂检测
|
||||||
|
protected async check(payload: Payload): Promise<BaseCheckResult> {
|
||||||
|
return { valid: true };
|
||||||
|
}
|
||||||
|
protected async _handle(payload: Payload): Promise<any> {
|
||||||
|
return await napCatCore.session.getMsgService().sendSsoCmdReqByContend(payload.cmd, payload.param);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,18 +1,14 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName, BaseCheckResult } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { NTQQSystemApi, NTQQUserApi } from '@/core/apis';
|
import { NTQQSystemApi } from '@/core/apis';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import Ajv from 'ajv';
|
|
||||||
// 设置在线状态
|
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
words: {
|
words: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: { type: 'string' }
|
||||||
type: 'string',
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
required: ['words'],
|
required: ['words'],
|
||||||
|
@@ -1,7 +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 { NTQQGroupApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis';
|
import { NTQQGroupApi } from '@/core/apis';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
@@ -1,15 +1,12 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import { ob11Config } from '@/onebot11/config';
|
import { ob11Config } from '@/onebot11/config';
|
||||||
import { log, logDebug } from '@/common/utils/log';
|
import { UUIDConverter } from '@/common/utils/helper';
|
||||||
import { sleep } from '@/common/utils/helper';
|
import { ActionName } from '../types';
|
||||||
import { uri2local } from '@/common/utils/file';
|
import { ChatType, ElementType, FileElement, Peer, RawMessage, VideoElement } from '@/core/entities';
|
||||||
import { ActionName, BaseCheckResult } from '../types';
|
import { NTQQFileApi, NTQQFriendApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis';
|
||||||
import { ChatType, FileElement, Peer, RawMessage, VideoElement } from '@/core/entities';
|
|
||||||
import { NTQQFileApi, NTQQMsgApi } from '@/core/apis';
|
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import Ajv from 'ajv';
|
import { getGroup } from '@/core/data';
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
|
||||||
|
|
||||||
export interface GetFilePayload {
|
export interface GetFilePayload {
|
||||||
file: string; // 文件名或者fileUuid
|
file: string; // 文件名或者fileUuid
|
||||||
@@ -46,6 +43,65 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
}
|
}
|
||||||
protected async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
protected async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
||||||
const { enableLocalFile2Url } = ob11Config;
|
const { enableLocalFile2Url } = ob11Config;
|
||||||
|
let UuidData: {
|
||||||
|
high: string;
|
||||||
|
low: string;
|
||||||
|
} | undefined;
|
||||||
|
try {
|
||||||
|
UuidData = UUIDConverter.decode(payload.file);
|
||||||
|
if (UuidData) {
|
||||||
|
const peerUin = UuidData.high;
|
||||||
|
const msgId = UuidData.low;
|
||||||
|
const isGroup = await getGroup(peerUin);
|
||||||
|
let peer: Peer | undefined;
|
||||||
|
//识别Peer
|
||||||
|
if (isGroup) {
|
||||||
|
peer = { chatType: ChatType.group, peerUid: peerUin };
|
||||||
|
}
|
||||||
|
const PeerUid = await NTQQUserApi.getUidByUin(peerUin);
|
||||||
|
if (PeerUid) {
|
||||||
|
const isBuddy = await NTQQFriendApi.isBuddy(PeerUid);
|
||||||
|
if (isBuddy) {
|
||||||
|
peer = { chatType: ChatType.friend, peerUid: PeerUid };
|
||||||
|
} else {
|
||||||
|
peer = { chatType: ChatType.temp, peerUid: PeerUid };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!peer) {
|
||||||
|
throw new Error('chattype not support');
|
||||||
|
}
|
||||||
|
const msgList = await NTQQMsgApi.getMsgsByMsgId(peer, [msgId]);
|
||||||
|
if (msgList.msgList.length == 0) {
|
||||||
|
throw new Error('msg not found');
|
||||||
|
}
|
||||||
|
const msg = msgList.msgList[0];
|
||||||
|
const findEle = msg.elements.find(e => e.elementType == ElementType.VIDEO || e.elementType == ElementType.FILE || e.elementType == ElementType.PTT);
|
||||||
|
if (!findEle) {
|
||||||
|
throw new Error('element not found');
|
||||||
|
}
|
||||||
|
const downloadPath = await NTQQFileApi.downloadMedia(msgId, msg.chatType, msg.peerUid, findEle.elementId, '', '');
|
||||||
|
const fileSize = findEle?.videoElement?.fileSize || findEle?.fileElement?.fileSize || findEle?.pttElement?.fileSize || '0';
|
||||||
|
const fileName = findEle?.videoElement?.fileName || findEle?.fileElement?.fileName || findEle?.pttElement?.fileName || '';
|
||||||
|
const res: GetFileResponse = {
|
||||||
|
file: downloadPath,
|
||||||
|
url: downloadPath,
|
||||||
|
file_size: fileSize,
|
||||||
|
file_name: fileName
|
||||||
|
};
|
||||||
|
if (enableLocalFile2Url) {
|
||||||
|
try {
|
||||||
|
res.base64 = await fs.readFile(downloadPath, 'base64');
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('文件下载失败. ' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//不手动删除?文件持久化了
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems;
|
const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems;
|
||||||
if (NTSearchNameResult.length !== 0) {
|
if (NTSearchNameResult.length !== 0) {
|
||||||
const MsgId = NTSearchNameResult[0].msgId;
|
const MsgId = NTSearchNameResult[0].msgId;
|
||||||
@@ -69,7 +125,7 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
const res: GetFileResponse = {
|
const res: GetFileResponse = {
|
||||||
file: downloadPath,
|
file: downloadPath,
|
||||||
url: downloadPath,
|
url: downloadPath,
|
||||||
file_size: NTSearchNameResult[0].fileSize.toString(),
|
file_size: NTSearchNameResult[0].fileSize.toString(),
|
||||||
file_name: NTSearchNameResult[0].fileName
|
file_name: NTSearchNameResult[0].fileName
|
||||||
};
|
};
|
||||||
if (enableLocalFile2Url) {
|
if (enableLocalFile2Url) {
|
||||||
@@ -82,7 +138,6 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
//不手动删除?文件持久化了
|
//不手动删除?文件持久化了
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
//下面逻辑是有UUID的情况
|
|
||||||
throw new Error('file not found');
|
throw new Error('file not found');
|
||||||
// let cache = await dbUtil.getFileCacheByName(payload.file);
|
// let cache = await dbUtil.getFileCacheByName(payload.file);
|
||||||
// if (!cache) {
|
// if (!cache) {
|
||||||
|
@@ -24,12 +24,12 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
|
|||||||
actionName = ActionName.GoCQHTTP_GetForwardMsg;
|
actionName = ActionName.GoCQHTTP_GetForwardMsg;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload): Promise<any> {
|
protected async _handle(payload: Payload): Promise<any> {
|
||||||
const msgId = payload.message_id || payload.id;
|
const msgIdMixOb11Id = payload.message_id || payload.id;
|
||||||
if (!msgId) {
|
if (!msgIdMixOb11Id) {
|
||||||
throw Error('message_id is required');
|
throw Error('message_id or id is required');
|
||||||
}
|
}
|
||||||
const rootMsgId = MessageUnique.getShortIdByMsgId(msgId);
|
const rootMsgId = MessageUnique.getShortIdByMsgId(msgIdMixOb11Id);
|
||||||
const rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || parseInt(msgId));
|
const rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || parseInt(msgIdMixOb11Id));
|
||||||
if (!rootMsg) {
|
if (!rootMsg) {
|
||||||
throw Error('msg not found');
|
throw Error('msg not found');
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
|
|||||||
const msgList = data.msgList;
|
const msgList = data.msgList;
|
||||||
const messages = await Promise.all(msgList.map(async msg => {
|
const messages = await Promise.all(msgList.map(async msg => {
|
||||||
const resMsg = await OB11Constructor.message(msg);
|
const resMsg = await OB11Constructor.message(msg);
|
||||||
resMsg.message_id = await MessageUnique.createMsg({ guildId:'',chatType:msg.chatType,peerUid:msg.peerUid },msg.msgId)!;
|
resMsg.message_id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)!;
|
||||||
return resMsg;
|
return resMsg;
|
||||||
}));
|
}));
|
||||||
messages.map(msg => {
|
messages.map(msg => {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { OB11Message, OB11User } from '../../types';
|
import { OB11Message, OB11User } from '../../types';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { ChatType } from '@/core/entities';
|
import { ChatType, RawMessage } from '@/core/entities';
|
||||||
import { NTQQMsgApi } from '@/core/apis/msg';
|
import { NTQQMsgApi } from '@/core/apis/msg';
|
||||||
import { OB11Constructor } from '../../constructor';
|
import { OB11Constructor } from '../../constructor';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
@@ -17,9 +17,10 @@ const SchemaData = {
|
|||||||
properties: {
|
properties: {
|
||||||
user_id: { type: ['number', 'string'] },
|
user_id: { type: ['number', 'string'] },
|
||||||
message_seq: { type: 'number' },
|
message_seq: { type: 'number' },
|
||||||
count: { type: 'number' }
|
count: { type: 'number' },
|
||||||
|
reverseOrder: { type: 'boolean' }
|
||||||
},
|
},
|
||||||
required: ['user_id', 'message_seq', 'count']
|
required: ['user_id']
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
type Payload = FromSchema<typeof SchemaData>;
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
@@ -28,21 +29,29 @@ export default class GetFriendMsgHistory extends BaseAction<Payload, Response> {
|
|||||||
actionName = ActionName.GetFriendMsgHistory;
|
actionName = ActionName.GetFriendMsgHistory;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload): Promise<Response> {
|
protected async _handle(payload: Payload): Promise<Response> {
|
||||||
|
//处理参数
|
||||||
const uid = await NTQQUserApi.getUidByUin(payload.user_id.toString());
|
const uid = await NTQQUserApi.getUidByUin(payload.user_id.toString());
|
||||||
if (!uid) {
|
const MsgCount = payload.count || 20;
|
||||||
throw `记录${payload.user_id}不存在`;
|
const isReverseOrder = payload.reverseOrder || true;
|
||||||
}
|
if (!uid) throw `记录${payload.user_id}不存在`;
|
||||||
const startMsgId = (await MessageUnique.getMsgIdAndPeerByShortId(payload.message_seq))?.MsgId || '0';
|
|
||||||
const friend = await NTQQFriendApi.isBuddy(uid);
|
const friend = await NTQQFriendApi.isBuddy(uid);
|
||||||
const historyResult = (await NTQQMsgApi.getMsgHistory({
|
const peer = { chatType: friend ? ChatType.friend : ChatType.temp, peerUid: uid };
|
||||||
chatType: friend ? ChatType.friend : ChatType.temp,
|
|
||||||
peerUid: uid
|
//拉取消息
|
||||||
}, startMsgId, parseInt(payload.count?.toString()) || 20));
|
let msgList: RawMessage[];
|
||||||
//logDebug(historyResult);
|
if (!payload.message_seq || payload.message_seq == 0) {
|
||||||
const msgList = historyResult.msgList;
|
msgList = (await NTQQMsgApi.getLastestMsgByUids(peer, MsgCount)).msgList;
|
||||||
|
} else {
|
||||||
|
const startMsgId = MessageUnique.getMsgIdAndPeerByShortId(payload.message_seq)?.MsgId;
|
||||||
|
if (!startMsgId) throw `消息${payload.message_seq}不存在`;
|
||||||
|
msgList = (await NTQQMsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList;
|
||||||
|
}
|
||||||
|
if(isReverseOrder) msgList.reverse();
|
||||||
await Promise.all(msgList.map(async msg => {
|
await Promise.all(msgList.map(async msg => {
|
||||||
msg.id = await MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
//转换消息
|
||||||
const ob11MsgList = await Promise.all(msgList.map(msg => OB11Constructor.message(msg)));
|
const ob11MsgList = await Promise.all(msgList.map(msg => OB11Constructor.message(msg)));
|
||||||
return { 'messages': ob11MsgList };
|
return { 'messages': ob11MsgList };
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@ import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
|||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
group_id: { type: [ 'number' , 'string' ] },
|
group_id: { type: ['number', 'string'] },
|
||||||
type: { enum: [WebHonorType.ALL, WebHonorType.EMOTION, WebHonorType.LEGEND, WebHonorType.PERFROMER, WebHonorType.STORONGE_NEWBI, WebHonorType.TALKACTIVE] }
|
type: { enum: [WebHonorType.ALL, WebHonorType.EMOTION, WebHonorType.LEGEND, WebHonorType.PERFROMER, WebHonorType.STORONGE_NEWBI, WebHonorType.TALKACTIVE] }
|
||||||
},
|
},
|
||||||
required: ['group_id']
|
required: ['group_id']
|
||||||
|
@@ -2,7 +2,7 @@ import BaseAction from '../BaseAction';
|
|||||||
import { OB11Message, OB11User } from '../../types';
|
import { OB11Message, OB11User } from '../../types';
|
||||||
import { getGroup, groups } from '@/core/data';
|
import { getGroup, groups } from '@/core/data';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { ChatType } from '@/core/entities';
|
import { ChatType, Peer, RawMessage } from '@/core/entities';
|
||||||
import { NTQQMsgApi } from '@/core/apis/msg';
|
import { NTQQMsgApi } from '@/core/apis/msg';
|
||||||
import { OB11Constructor } from '../../constructor';
|
import { OB11Constructor } from '../../constructor';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
@@ -16,7 +16,8 @@ const SchemaData = {
|
|||||||
properties: {
|
properties: {
|
||||||
group_id: { type: ['number', 'string'] },
|
group_id: { type: ['number', 'string'] },
|
||||||
message_seq: { type: 'number' },
|
message_seq: { type: 'number' },
|
||||||
count: { type: 'number' }
|
count: { type: 'number' },
|
||||||
|
reverseOrder: { type: 'boolean' }
|
||||||
},
|
},
|
||||||
required: ['group_id']
|
required: ['group_id']
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
@@ -27,25 +28,28 @@ export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Resp
|
|||||||
actionName = ActionName.GoCQHTTP_GetGroupMsgHistory;
|
actionName = ActionName.GoCQHTTP_GetGroupMsgHistory;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload): Promise<Response> {
|
protected async _handle(payload: Payload): Promise<Response> {
|
||||||
|
//处理参数
|
||||||
const group = await getGroup(payload.group_id.toString());
|
const group = await getGroup(payload.group_id.toString());
|
||||||
if (!group) {
|
const isReverseOrder = payload.reverseOrder || true;
|
||||||
throw `群${payload.group_id}不存在`;
|
const MsgCount = payload.count || 20;
|
||||||
|
const peer: Peer = { chatType: ChatType.group, peerUid: payload.group_id.toString() };
|
||||||
|
if (!group) throw `群${payload.group_id}不存在`;
|
||||||
|
|
||||||
|
//拉取消息
|
||||||
|
let msgList: RawMessage[];
|
||||||
|
if (!payload.message_seq || payload.message_seq == 0) {
|
||||||
|
msgList = (await NTQQMsgApi.getLastestMsgByUids(peer, MsgCount)).msgList;
|
||||||
|
} else {
|
||||||
|
const startMsgId = MessageUnique.getMsgIdAndPeerByShortId(payload.message_seq)?.MsgId;
|
||||||
|
if (!startMsgId) throw `消息${payload.message_seq}不存在`;
|
||||||
|
msgList = (await NTQQMsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList;
|
||||||
}
|
}
|
||||||
let targetMsgShortId, count = parseInt(payload.count?.toString() ?? '20');
|
if(isReverseOrder) msgList.reverse();
|
||||||
const peer = {
|
|
||||||
chatType: ChatType.group,
|
|
||||||
peerUid: group.groupCode
|
|
||||||
};
|
|
||||||
if (!payload.message_seq) {
|
|
||||||
const latestMsgId = (await NTQQMsgApi.getLastestMsgByUids(peer)).msgList[0].msgId;
|
|
||||||
targetMsgShortId = await MessageUnique.createMsg(peer, latestMsgId || '0');
|
|
||||||
}
|
|
||||||
const startMsgId = (await MessageUnique.getMsgIdAndPeerByShortId(targetMsgShortId ?? (payload.message_seq ?? 0)))?.MsgId || '0';
|
|
||||||
const historyResult = (await NTQQMsgApi.getMsgHistory(peer, startMsgId, count));
|
|
||||||
const msgList = historyResult.msgList;
|
|
||||||
await Promise.all(msgList.map(async msg => {
|
await Promise.all(msgList.map(async msg => {
|
||||||
msg.id = await MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
//转换消息
|
||||||
const ob11MsgList = await Promise.all(msgList.map(msg => OB11Constructor.message(msg)));
|
const ob11MsgList = await Promise.all(msgList.map(msg => OB11Constructor.message(msg)));
|
||||||
return { 'messages': ob11MsgList };
|
return { 'messages': ob11MsgList };
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ import { ActionName } from '../types';
|
|||||||
import { NTQQUserApi } from '@/core/apis/user';
|
import { NTQQUserApi } from '@/core/apis/user';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { calcQQLevel } from '@/common/utils/qqlevel';
|
import { calcQQLevel } from '@/common/utils/qqlevel';
|
||||||
|
import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -20,24 +21,45 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
|
|||||||
actionName = ActionName.GoCQHTTP_GetStrangerInfo;
|
actionName = ActionName.GoCQHTTP_GetStrangerInfo;
|
||||||
|
|
||||||
protected async _handle(payload: Payload): Promise<OB11User> {
|
protected async _handle(payload: Payload): Promise<OB11User> {
|
||||||
const user_id = payload.user_id.toString();
|
if (!requireMinNTQQBuild('26702')) {
|
||||||
const extendData = await NTQQUserApi.getUserDetailInfoByUin(user_id);
|
const user_id = payload.user_id.toString();
|
||||||
const uid = (await NTQQUserApi.getUidByUin(user_id))!;
|
const extendData = await NTQQUserApi.getUserDetailInfoByUin(user_id);
|
||||||
if (!uid || uid.indexOf('*') != -1) {
|
const uid = (await NTQQUserApi.getUidByUin(user_id))!;
|
||||||
const ret = {
|
if (!uid || uid.indexOf('*') != -1) {
|
||||||
...extendData,
|
const ret = {
|
||||||
user_id: parseInt(extendData.info.uin) || 0,
|
...extendData,
|
||||||
nickname: extendData.info.nick,
|
user_id: parseInt(extendData.info.uin) || 0,
|
||||||
sex: OB11UserSex.unknown,
|
nickname: extendData.info.nick,
|
||||||
age: (extendData.info.birthday_year == 0) ? 0 : new Date().getFullYear() - extendData.info.birthday_year,
|
sex: OB11UserSex.unknown,
|
||||||
qid: extendData.info.qid,
|
age: (extendData.info.birthday_year == 0) ? 0 : new Date().getFullYear() - extendData.info.birthday_year,
|
||||||
level: extendData.info.qqLevel && calcQQLevel(extendData.info.qqLevel) || 0,
|
qid: extendData.info.qid,
|
||||||
login_days: 0,
|
level: extendData.info.qqLevel && calcQQLevel(extendData.info.qqLevel) || 0,
|
||||||
uid: ''
|
login_days: 0,
|
||||||
};
|
uid: ''
|
||||||
return ret;
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
const data = { ...extendData, ...(await NTQQUserApi.getUserDetailInfo(uid)) };
|
||||||
|
return OB11Constructor.stranger(data);
|
||||||
|
} else {
|
||||||
|
const user_id = payload.user_id.toString();
|
||||||
|
const extendData = await NTQQUserApi.getUserDetailInfoByUinV2(user_id);
|
||||||
|
const uid = (await NTQQUserApi.getUidByUin(user_id))!;
|
||||||
|
if (!uid || uid.indexOf('*') != -1) {
|
||||||
|
const ret = {
|
||||||
|
...extendData,
|
||||||
|
user_id: parseInt(extendData.detail.uin) || 0,
|
||||||
|
nickname: extendData.detail.simpleInfo.coreInfo.nick,
|
||||||
|
sex: OB11UserSex.unknown,
|
||||||
|
age: 0,
|
||||||
|
level: extendData.detail.commonExt.qqLevel && calcQQLevel(extendData.detail.commonExt.qqLevel) || 0,
|
||||||
|
login_days: 0,
|
||||||
|
uid: ''
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
const data = { ...extendData, ...(await NTQQUserApi.getUserDetailInfo(uid)) };
|
||||||
|
return OB11Constructor.stranger(data);
|
||||||
}
|
}
|
||||||
const data = { ...extendData, ...(await NTQQUserApi.getUserDetailInfo(uid)) };
|
|
||||||
return OB11Constructor.stranger(data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@ import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
|||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
group_id: { type: [ 'number' , 'string' ] },
|
group_id: { type: ['number', 'string'] },
|
||||||
content: { type: 'string' },
|
content: { type: 'string' },
|
||||||
image: { type: 'string' },
|
image: { type: 'string' },
|
||||||
pinned: { type: 'number' },
|
pinned: { type: 'number' },
|
||||||
@@ -24,8 +24,8 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
|||||||
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 { errMsg, path, isLocal } = (await uri2local(payload.image));
|
const { errMsg, path, isLocal, success } = (await uri2local(payload.image));
|
||||||
if (errMsg) {
|
if (!success) {
|
||||||
throw `群公告${payload.image}设置失败,image字段可能格式不正确`;
|
throw `群公告${payload.image}设置失败,image字段可能格式不正确`;
|
||||||
}
|
}
|
||||||
if (!path) {
|
if (!path) {
|
||||||
@@ -54,8 +54,6 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
|||||||
if (PublishGroupBulletinResult.result != 0) {
|
if (PublishGroupBulletinResult.result != 0) {
|
||||||
throw `设置群公告失败,错误信息:${PublishGroupBulletinResult.errMsg}`;
|
throw `设置群公告失败,错误信息:${PublishGroupBulletinResult.errMsg}`;
|
||||||
}
|
}
|
||||||
// 下面实现扬了
|
|
||||||
//await WebApi.setGroupNotice(payload.group_id, payload.content) ;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ import { ActionName } from '../types';
|
|||||||
import { SendMsgElementConstructor } from '@/core/entities/constructor';
|
import { SendMsgElementConstructor } from '@/core/entities/constructor';
|
||||||
import { ChatType, SendFileElement } from '@/core/entities';
|
import { ChatType, SendFileElement } from '@/core/entities';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { SendMsg, sendMsg } from '@/onebot11/action/msg/SendMsg';
|
import { sendMsg } from '@/onebot11/action/msg/SendMsg';
|
||||||
import { uri2local } from '@/common/utils/file';
|
import { uri2local } from '@/common/utils/file';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
@@ -34,7 +34,7 @@ export default class GoCQHTTPUploadGroupFile extends BaseAction<Payload, null> {
|
|||||||
file = `file://${file}`;
|
file = `file://${file}`;
|
||||||
}
|
}
|
||||||
const downloadResult = await uri2local(file);
|
const downloadResult = await uri2local(file);
|
||||||
if (downloadResult.errMsg) {
|
if (!downloadResult.success) {
|
||||||
throw new Error(downloadResult.errMsg);
|
throw new Error(downloadResult.errMsg);
|
||||||
}
|
}
|
||||||
const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(downloadResult.path, payload.name, payload.folder_id);
|
const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(downloadResult.path, payload.name, payload.folder_id);
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { getGroup } from '@/core/data';
|
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { SendMsgElementConstructor } from '@/core/entities/constructor';
|
import { SendMsgElementConstructor } from '@/core/entities/constructor';
|
||||||
import { ChatType, Peer, SendFileElement } from '@/core/entities';
|
import { ChatType, Peer, SendFileElement } from '@/core/entities';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { SendMsg, sendMsg } from '@/onebot11/action/msg/SendMsg';
|
import { sendMsg } from '@/onebot11/action/msg/SendMsg';
|
||||||
import { uri2local } from '@/common/utils/file';
|
import { uri2local } from '@/common/utils/file';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { NTQQFriendApi, NTQQUserApi } from '@/core';
|
import { NTQQFriendApi, NTQQUserApi } from '@/core';
|
||||||
@@ -41,7 +40,7 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
|
|||||||
file = `file://${file}`;
|
file = `file://${file}`;
|
||||||
}
|
}
|
||||||
const downloadResult = await uri2local(file);
|
const downloadResult = await uri2local(file);
|
||||||
if (downloadResult.errMsg) {
|
if (!downloadResult.success) {
|
||||||
throw new Error(downloadResult.errMsg);
|
throw new Error(downloadResult.errMsg);
|
||||||
}
|
}
|
||||||
const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(downloadResult.path, payload.name);
|
const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(downloadResult.path, payload.name);
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
import { getGroup } from '@/core/data';
|
|
||||||
import { OB11Group } from '../../types';
|
|
||||||
import { OB11Constructor } from '../../constructor';
|
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { NTQQMsgApi } from '@/core/apis/msg';
|
|
||||||
import { GroupEssenceMsgRet, WebApi } from '@/core/apis/webapi';
|
import { GroupEssenceMsgRet, WebApi } from '@/core/apis/webapi';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
@@ -2,12 +2,9 @@ import { OB11Group } from '../../types';
|
|||||||
import { OB11Constructor } from '../../constructor';
|
import { OB11Constructor } from '../../constructor';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { groups } from '@/core/data';
|
|
||||||
import { NTQQGroupApi } from '@/core/apis';
|
import { NTQQGroupApi } from '@/core/apis';
|
||||||
import { Group } from '@/core/entities';
|
import { Group } from '@/core/entities';
|
||||||
import { log } from '@/common/utils/log';
|
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
// no_cache get时传字符串
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@@ -21,11 +18,7 @@ class GetGroupList extends BaseAction<Payload, OB11Group[]> {
|
|||||||
actionName = ActionName.GetGroupList;
|
actionName = ActionName.GetGroupList;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
let groupList: Group[] = Array.from(groups.values());
|
const groupList: Group[] = await NTQQGroupApi.getGroups(payload?.no_cache === true || payload.no_cache === 'true');
|
||||||
if (groupList.length === 0 || payload?.no_cache === true || payload.no_cache === 'true') {
|
|
||||||
groupList = await NTQQGroupApi.getGroups(true);
|
|
||||||
// log('get groups', groups);
|
|
||||||
}
|
|
||||||
return OB11Constructor.groups(groupList);
|
return OB11Constructor.groups(groupList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { OB11GroupMember } from '../../types';
|
import { OB11GroupMember } from '../../types';
|
||||||
import { getGroup, getGroupMember, groupMembers, selfInfo } from '@/core/data';
|
|
||||||
import { OB11Constructor } from '../../constructor';
|
import { OB11Constructor } from '../../constructor';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
@@ -8,8 +7,8 @@ import { logDebug } from '@/common/utils/log';
|
|||||||
import { WebApi } from '@/core/apis/webapi';
|
import { WebApi } from '@/core/apis/webapi';
|
||||||
import { NTQQGroupApi } from '@/core';
|
import { NTQQGroupApi } from '@/core';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { getGroupMember, selfInfo } from '@/core/data';
|
||||||
// no_cache get时传字符串
|
import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo';
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@@ -26,17 +25,12 @@ class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
|
|||||||
actionName = ActionName.GetGroupMemberInfo;
|
actionName = ActionName.GetGroupMemberInfo;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
const group = await getGroup(payload.group_id.toString());
|
const isNocache = payload.no_cache == true || payload.no_cache === 'true';
|
||||||
const role = (await getGroupMember(payload.group_id, selfInfo.uin))?.role;
|
const uid = await NTQQUserApi.getUidByUin(payload.user_id.toString());
|
||||||
const isPrivilege = role === 3 || role === 4;
|
if (!uid) {
|
||||||
if (!group) {
|
throw (`Uin2Uid Error ${payload.user_id}不存在`);
|
||||||
throw (`群(${payload.group_id})不存在`);
|
|
||||||
}
|
}
|
||||||
if (payload.no_cache == true || payload.no_cache === 'true') {
|
const member = await NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache);
|
||||||
groupMembers.set(group.groupCode, await NTQQGroupApi.getGroupMembers(payload.group_id.toString()));
|
|
||||||
}
|
|
||||||
const member = await getGroupMember(payload.group_id.toString(), payload.user_id.toString());
|
|
||||||
//早返回
|
|
||||||
if (!member) {
|
if (!member) {
|
||||||
throw (`群(${payload.group_id})成员${payload.user_id}不存在`);
|
throw (`群(${payload.group_id})成员${payload.user_id}不存在`);
|
||||||
}
|
}
|
||||||
@@ -47,26 +41,37 @@ class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
logDebug('获取群成员详细信息失败, 只能返回基础信息', e);
|
logDebug('获取群成员详细信息失败, 只能返回基础信息', e);
|
||||||
}
|
}
|
||||||
|
const date = Math.round(Date.now() / 1000);
|
||||||
const retMember = OB11Constructor.groupMember(payload.group_id.toString(), member);
|
const retMember = OB11Constructor.groupMember(payload.group_id.toString(), member);
|
||||||
if (isPrivilege) {
|
if (!requireMinNTQQBuild('26702')) {
|
||||||
const webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString());
|
const SelfInfoInGroup = await NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), selfInfo.uid, isNocache);
|
||||||
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
let isPrivilege = false;
|
||||||
if (webGroupMembers[i]?.uin && webGroupMembers[i].uin === retMember.user_id) {
|
if (SelfInfoInGroup) {
|
||||||
retMember.join_time = webGroupMembers[i]?.join_time;
|
isPrivilege = SelfInfoInGroup.role === 3 || SelfInfoInGroup.role === 4;
|
||||||
retMember.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
}
|
||||||
retMember.qage = webGroupMembers[i]?.qage;
|
if (isPrivilege) {
|
||||||
retMember.level = webGroupMembers[i]?.lv.level.toString();
|
const webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString());
|
||||||
|
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
||||||
|
if (webGroupMembers[i]?.uin && webGroupMembers[i].uin === retMember.user_id) {
|
||||||
|
retMember.join_time = webGroupMembers[i]?.join_time;
|
||||||
|
retMember.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
||||||
|
retMember.qage = webGroupMembers[i]?.qage;
|
||||||
|
retMember.level = webGroupMembers[i]?.lv.level.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const LastestMsgList = await NTQQGroupApi.getLastestMsg(payload.group_id.toString(), [payload.user_id.toString()]);
|
||||||
|
if (LastestMsgList?.msgList?.length && LastestMsgList?.msgList?.length > 0) {
|
||||||
|
const last_send_time = LastestMsgList.msgList[0].msgTime;
|
||||||
|
if (last_send_time && last_send_time != '0' && last_send_time != '') {
|
||||||
|
retMember.last_sent_time = parseInt(last_send_time);
|
||||||
|
retMember.join_time = Math.round(Date.now() / 1000);//兜底数据 防止群管乱杀
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const LastestMsgList = await NTQQGroupApi.getLastestMsg(payload.group_id.toString(), [payload.user_id.toString()]);
|
retMember.last_sent_time = parseInt((await getGroupMember(payload.group_id.toString(), retMember.user_id))?.lastSpeakTime || date.toString());
|
||||||
if (LastestMsgList?.msgList?.length && LastestMsgList?.msgList?.length > 0) {
|
retMember.join_time = parseInt((await getGroupMember(payload.group_id.toString(), retMember.user_id))?.joinTime || date.toString());
|
||||||
const last_send_time = LastestMsgList.msgList[0].msgTime;
|
|
||||||
if (last_send_time && last_send_time != '0' && last_send_time != '') {
|
|
||||||
retMember.last_sent_time = parseInt(last_send_time);
|
|
||||||
retMember.join_time = Math.round(Date.now() / 1000);//兜底数据 防止群管乱杀
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return retMember;
|
return retMember;
|
||||||
}
|
}
|
||||||
|
84
src/onebot11/action/group/GetGroupMemberInfoOld.ts
Normal file
84
src/onebot11/action/group/GetGroupMemberInfoOld.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { OB11GroupMember } from '../../types';
|
||||||
|
import { getGroup, getGroupMember, groupMembers, selfInfo } from '@/core/data';
|
||||||
|
import { OB11Constructor } from '../../constructor';
|
||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName } from '../types';
|
||||||
|
import { NTQQUserApi } from '@/core/apis/user';
|
||||||
|
import { logDebug } from '@/common/utils/log';
|
||||||
|
import { WebApi } from '@/core/apis/webapi';
|
||||||
|
import { NTQQGroupApi } from '@/core';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo';
|
||||||
|
|
||||||
|
// no_cache get时传字符串
|
||||||
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
group_id: { type: ['number', 'string'] },
|
||||||
|
user_id: { type: ['number', 'string'] },
|
||||||
|
no_cache: { type: ['boolean', 'string'] },
|
||||||
|
},
|
||||||
|
required: ['group_id', 'user_id']
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
|
||||||
|
actionName = ActionName.GetGroupMemberInfo;
|
||||||
|
PayloadSchema = SchemaData;
|
||||||
|
protected async _handle(payload: Payload) {
|
||||||
|
if (requireMinNTQQBuild('26702')) {
|
||||||
|
const V2Data = await NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), payload.user_id.toString(), payload.no_cache == true || payload.no_cache === 'true');
|
||||||
|
if (V2Data) {
|
||||||
|
return OB11Constructor.groupMember(payload.group_id.toString(), V2Data);
|
||||||
|
} else {
|
||||||
|
throw (`群(${payload.group_id})成员${payload.user_id}不存在`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const group = await getGroup(payload.group_id.toString());
|
||||||
|
const role = (await getGroupMember(payload.group_id, selfInfo.uin))?.role;
|
||||||
|
const isPrivilege = role === 3 || role === 4;
|
||||||
|
if (!group) {
|
||||||
|
throw (`群(${payload.group_id})不存在`);
|
||||||
|
}
|
||||||
|
if (payload.no_cache == true || payload.no_cache === 'true') {
|
||||||
|
groupMembers.set(group.groupCode, await NTQQGroupApi.getGroupMembers(payload.group_id.toString()));
|
||||||
|
}
|
||||||
|
const member = await getGroupMember(payload.group_id.toString(), payload.user_id.toString());
|
||||||
|
//早返回
|
||||||
|
if (!member) {
|
||||||
|
throw (`群(${payload.group_id})成员${payload.user_id}不存在`);
|
||||||
|
}
|
||||||
|
//console.log('GetGroupMemberInfo', JSON.stringify(await NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), member.uid, true), null, 4));
|
||||||
|
try {
|
||||||
|
const info = (await NTQQUserApi.getUserDetailInfo(member.uid));
|
||||||
|
logDebug('群成员详细信息结果', info);
|
||||||
|
Object.assign(member, info);
|
||||||
|
} catch (e) {
|
||||||
|
logDebug('获取群成员详细信息失败, 只能返回基础信息', e);
|
||||||
|
}
|
||||||
|
const retMember = OB11Constructor.groupMember(payload.group_id.toString(), member);
|
||||||
|
if (isPrivilege) {
|
||||||
|
const webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString());
|
||||||
|
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
||||||
|
if (webGroupMembers[i]?.uin && webGroupMembers[i].uin === retMember.user_id) {
|
||||||
|
retMember.join_time = webGroupMembers[i]?.join_time;
|
||||||
|
retMember.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
||||||
|
retMember.qage = webGroupMembers[i]?.qage;
|
||||||
|
retMember.level = webGroupMembers[i]?.lv.level.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const LastestMsgList = await NTQQGroupApi.getLastestMsg(payload.group_id.toString(), [payload.user_id.toString()]);
|
||||||
|
if (LastestMsgList?.msgList?.length && LastestMsgList?.msgList?.length > 0) {
|
||||||
|
const last_send_time = LastestMsgList.msgList[0].msgTime;
|
||||||
|
if (last_send_time && last_send_time != '0' && last_send_time != '') {
|
||||||
|
retMember.last_sent_time = parseInt(last_send_time);
|
||||||
|
retMember.join_time = Math.round(Date.now() / 1000);//兜底数据 防止群管乱杀
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retMember;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default GetGroupMemberInfo;
|
@@ -1,4 +1,4 @@
|
|||||||
import { getGroup, getGroupMember, groupMembers, selfInfo } from '@/core/data';
|
import { getGroup, getGroupMember, selfInfo } from '@/core/data';
|
||||||
import { OB11GroupMember } from '../../types';
|
import { OB11GroupMember } from '../../types';
|
||||||
import { OB11Constructor } from '../../constructor';
|
import { OB11Constructor } from '../../constructor';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
@@ -6,6 +6,7 @@ import { ActionName } from '../types';
|
|||||||
import { NTQQGroupApi } from '@/core';
|
import { NTQQGroupApi } from '@/core';
|
||||||
import { WebApi } from '@/core/apis/webapi';
|
import { WebApi } from '@/core/apis/webapi';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -22,20 +23,16 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
|
|||||||
actionName = ActionName.GetGroupMemberList;
|
actionName = ActionName.GetGroupMemberList;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
const role = (await getGroupMember(payload.group_id, selfInfo.uin))?.role;
|
const isNocache = payload.no_cache == true || payload.no_cache === 'true';
|
||||||
|
|
||||||
const group = await getGroup(payload.group_id.toString());
|
const GroupList = await NTQQGroupApi.getGroups(isNocache);
|
||||||
|
const group = GroupList.find(item => item.groupCode == payload.group_id);
|
||||||
if (!group) {
|
if (!group) {
|
||||||
throw (`群${payload.group_id}不存在`);
|
throw (`群${payload.group_id}不存在`);
|
||||||
}
|
}
|
||||||
|
const groupMembers = await NTQQGroupApi.getGroupMembers(payload.group_id.toString());
|
||||||
// 从Data里面获取
|
let _groupMembers = Array.from(groupMembers.values())
|
||||||
let _groupMembers: OB11GroupMember[] = OB11Constructor.groupMembers(group);
|
.map(item => { return OB11Constructor.groupMember(group.groupCode, item); });
|
||||||
if (payload.no_cache == true || payload.no_cache === 'true') {
|
|
||||||
// webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString());'
|
|
||||||
const _groupMembers = await NTQQGroupApi.getGroupMembers(payload.group_id.toString());
|
|
||||||
groupMembers.set(group.groupCode, _groupMembers);
|
|
||||||
}
|
|
||||||
|
|
||||||
const MemberMap: Map<number, OB11GroupMember> = new Map<number, OB11GroupMember>();
|
const MemberMap: Map<number, OB11GroupMember> = new Map<number, OB11GroupMember>();
|
||||||
// 转为Map 方便索引
|
// 转为Map 方便索引
|
||||||
@@ -47,31 +44,47 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
|
|||||||
MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]);
|
MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isPrivilege = role === 3 || role === 4;
|
if (!requireMinNTQQBuild('26702')) {
|
||||||
if (isPrivilege) {
|
const selfRole = groupMembers.get(selfInfo.uid)?.role;
|
||||||
const webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString());
|
const isPrivilege = selfRole === 3 || selfRole === 4;
|
||||||
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
|
||||||
if (!webGroupMembers[i]?.uin) {
|
if (isPrivilege) {
|
||||||
continue;
|
const webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString());
|
||||||
|
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
||||||
|
if (!webGroupMembers[i]?.uin) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const MemberData = MemberMap.get(webGroupMembers[i]?.uin);
|
||||||
|
if (MemberData) {
|
||||||
|
MemberData.join_time = webGroupMembers[i]?.join_time;
|
||||||
|
MemberData.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
||||||
|
MemberData.qage = webGroupMembers[i]?.qage;
|
||||||
|
MemberData.level = webGroupMembers[i]?.lv.level.toString();
|
||||||
|
MemberMap.set(webGroupMembers[i]?.uin, MemberData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const MemberData = MemberMap.get(webGroupMembers[i]?.uin);
|
} else {
|
||||||
if (MemberData) {
|
if (isNocache) {
|
||||||
MemberData.join_time = webGroupMembers[i]?.join_time;
|
const DateMap = await NTQQGroupApi.getGroupMemberLastestSendTimeCache(payload.group_id.toString());//开始从本地拉取
|
||||||
MemberData.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
for (const DateUin of DateMap.keys()) {
|
||||||
MemberData.qage = webGroupMembers[i]?.qage;
|
const MemberData = MemberMap.get(parseInt(DateUin));
|
||||||
MemberData.level = webGroupMembers[i]?.lv.level.toString();
|
if (MemberData) {
|
||||||
MemberMap.set(webGroupMembers[i]?.uin, MemberData);
|
MemberData.last_sent_time = parseInt(DateMap.get(DateUin)!);
|
||||||
|
//join_time 有基础数据兜底
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_groupMembers.forEach(item => {
|
||||||
|
item.last_sent_time = date;
|
||||||
|
item.join_time = date;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const DateMap = await NTQQGroupApi.getGroupMemberLastestSendTimeCache(payload.group_id.toString());//开始从本地拉取
|
_groupMembers.forEach(async item => {
|
||||||
for (const DateUin of DateMap.keys()) {
|
item.last_sent_time = parseInt((await getGroupMember(payload.group_id.toString(), item.user_id))?.lastSpeakTime || date.toString());
|
||||||
const MemberData = MemberMap.get(parseInt(DateUin));
|
item.join_time = parseInt((await getGroupMember(payload.group_id.toString(), item.user_id))?.joinTime || date.toString());
|
||||||
if (MemberData) {
|
});
|
||||||
MemberData.last_sent_time = parseInt(DateMap.get(DateUin)!);
|
|
||||||
//join_time 有基础数据兜底
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 还原索引到Array 一同返回
|
// 还原索引到Array 一同返回
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
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 { NTQQGroupApi, NTQQMsgApi } from '@/core';
|
import { NTQQGroupApi } from '@/core';
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
@@ -18,7 +18,7 @@ export default class SetEssenceMsg extends BaseAction<Payload, any> {
|
|||||||
actionName = ActionName.SetEssenceMsg;
|
actionName = ActionName.SetEssenceMsg;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload): Promise<any> {
|
protected async _handle(payload: Payload): Promise<any> {
|
||||||
const msg = await MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
|
const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
throw new Error('msg not found');
|
throw new Error('msg not found');
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ const SchemaData = {
|
|||||||
properties: {
|
properties: {
|
||||||
flag: { type: 'string' },
|
flag: { type: 'string' },
|
||||||
approve: { type: ['string', 'boolean'] },
|
approve: { type: ['string', 'boolean'] },
|
||||||
reason: { type: 'string', nullable: true, }
|
reason: { type: 'string', nullable: true }
|
||||||
},
|
},
|
||||||
required: ['flag'],
|
required: ['flag'],
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
@@ -24,7 +24,7 @@ export default class SetGroupAddRequest extends BaseAction<Payload, null> {
|
|||||||
const approve = payload.approve?.toString() !== 'false';
|
const approve = payload.approve?.toString() !== 'false';
|
||||||
await NTQQGroupApi.handleGroupRequest(flag,
|
await NTQQGroupApi.handleGroupRequest(flag,
|
||||||
approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
|
approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
|
||||||
payload.reason
|
payload.reason || ''
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ import { getGroupMember } from '@/core/data';
|
|||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { NTQQGroupApi } from '@/core/apis/group';
|
import { NTQQGroupApi } from '@/core/apis/group';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { NTQQUserApi } from '@/core';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -20,12 +21,8 @@ export default class SetGroupBan extends BaseAction<Payload, null> {
|
|||||||
actionName = ActionName.SetGroupBan;
|
actionName = ActionName.SetGroupBan;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload): Promise<null> {
|
protected async _handle(payload: Payload): Promise<null> {
|
||||||
const member = await getGroupMember(payload.group_id, payload.user_id);
|
|
||||||
if (!member) {
|
|
||||||
throw `群成员${payload.user_id}不存在`;
|
|
||||||
}
|
|
||||||
await NTQQGroupApi.banMember(payload.group_id.toString(),
|
await NTQQGroupApi.banMember(payload.group_id.toString(),
|
||||||
[{ uid: member.uid, timeStamp: parseInt(payload.duration.toString()) }]);
|
[{ uid: (await NTQQUserApi.getUidByUin(payload.user_id.toString()))!, timeStamp: parseInt(payload.duration.toString()) }]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ import { getGroupMember } from '@/core/data';
|
|||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { NTQQGroupApi } from '@/core/apis/group';
|
import { NTQQGroupApi } from '@/core/apis/group';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { NTQQUserApi } from '@/core';
|
||||||
|
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
@@ -21,12 +22,8 @@ export default class SetGroupKick extends BaseAction<Payload, null> {
|
|||||||
actionName = ActionName.SetGroupKick;
|
actionName = ActionName.SetGroupKick;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload): Promise<null> {
|
protected async _handle(payload: Payload): Promise<null> {
|
||||||
const member = await getGroupMember(payload.group_id, payload.user_id);
|
|
||||||
if (!member) {
|
|
||||||
throw `群成员${payload.user_id}不存在`;
|
|
||||||
}
|
|
||||||
const rejectReq = payload.reject_add_request?.toString() == 'true';
|
const rejectReq = payload.reject_add_request?.toString() == 'true';
|
||||||
await NTQQGroupApi.kickMember(payload.group_id.toString(), [member.uid], rejectReq);
|
await NTQQGroupApi.kickMember(payload.group_id.toString(), [(await NTQQUserApi.getUidByUin(payload.user_id.toString()))!], rejectReq);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,9 +35,7 @@ import SetGroupCard from './group/SetGroupCard';
|
|||||||
import GetImage from './file/GetImage';
|
import GetImage from './file/GetImage';
|
||||||
import GetRecord from './file/GetRecord';
|
import GetRecord from './file/GetRecord';
|
||||||
import { GoCQHTTPMarkMsgAsRead, MarkAllMsgAsRead, MarkGroupMsgAsRead, MarkPrivateMsgAsRead } from './msg/MarkMsgAsRead';
|
import { GoCQHTTPMarkMsgAsRead, MarkAllMsgAsRead, MarkGroupMsgAsRead, MarkPrivateMsgAsRead } from './msg/MarkMsgAsRead';
|
||||||
import CleanCache from './system/CleanCache';
|
|
||||||
import GoCQHTTPUploadGroupFile from './go-cqhttp/UploadGroupFile';
|
import GoCQHTTPUploadGroupFile from './go-cqhttp/UploadGroupFile';
|
||||||
import { GetConfigAction, SetConfigAction } from '@/onebot11/action/extends/Config';
|
|
||||||
import GetGroupAddRequest from '@/onebot11/action/extends/GetGroupAddRequest';
|
import GetGroupAddRequest from '@/onebot11/action/extends/GetGroupAddRequest';
|
||||||
import SetQQAvatar from '@/onebot11/action/extends/SetQQAvatar';
|
import SetQQAvatar from '@/onebot11/action/extends/SetQQAvatar';
|
||||||
import GoCQHTTPDownloadFile from './go-cqhttp/DownloadFile';
|
import GoCQHTTPDownloadFile from './go-cqhttp/DownloadFile';
|
||||||
@@ -77,8 +75,11 @@ import { GetProfileLike } from './extends/GetProfileLike';
|
|||||||
import SetGroupHeader from './extends/SetGroupHeader';
|
import SetGroupHeader from './extends/SetGroupHeader';
|
||||||
import { FetchCustomFace } from './extends/FetchCustomFace';
|
import { FetchCustomFace } from './extends/FetchCustomFace';
|
||||||
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivareFile';
|
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivareFile';
|
||||||
|
import TestApi01 from './extends/TestApi01';
|
||||||
|
import { FetchEmojioLike } from './extends/FetchEmojioLike';
|
||||||
|
|
||||||
export const actionHandlers = [
|
export const actionHandlers = [
|
||||||
|
new FetchEmojioLike(),
|
||||||
new RebootNormal(),
|
new RebootNormal(),
|
||||||
new GetFile(),
|
new GetFile(),
|
||||||
new Debug(),
|
new Debug(),
|
||||||
@@ -160,9 +161,9 @@ export const actionHandlers = [
|
|||||||
new GetProfileLike(),
|
new GetProfileLike(),
|
||||||
new SetGroupHeader(),
|
new SetGroupHeader(),
|
||||||
new FetchCustomFace(),
|
new FetchCustomFace(),
|
||||||
new GoCQHTTPUploadPrivateFile()
|
new GoCQHTTPUploadPrivateFile(),
|
||||||
|
new TestApi01()
|
||||||
];
|
];
|
||||||
|
|
||||||
function initActionMap() {
|
function initActionMap() {
|
||||||
const actionMap = new Map<string, BaseAction<any, any>>();
|
const actionMap = new Map<string, BaseAction<any, any>>();
|
||||||
for (const action of actionHandlers) {
|
for (const action of actionHandlers) {
|
||||||
|
@@ -3,12 +3,15 @@ import { ActionName } from '../types';
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||||
|
import { sleep } from '@/common/utils/helper';
|
||||||
|
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||||
|
import { NodeIKernelMsgListener } from '@/core';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
message_id: {
|
message_id: {
|
||||||
oneOf:[
|
oneOf: [
|
||||||
{ type: 'number' },
|
{ type: 'number' },
|
||||||
{ type: 'string' }
|
{ type: 'string' }
|
||||||
]
|
]
|
||||||
@@ -23,9 +26,27 @@ class DeleteMsg extends BaseAction<Payload, void> {
|
|||||||
actionName = ActionName.DeleteMsg;
|
actionName = ActionName.DeleteMsg;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
const msg = await MessageUnique.getMsgIdAndPeerByShortId(Number(payload.message_id));
|
const msg = MessageUnique.getMsgIdAndPeerByShortId(Number(payload.message_id));
|
||||||
if (msg) {
|
if (msg) {
|
||||||
|
const ret = NTEventDispatch.RegisterListen<NodeIKernelMsgListener['onMsgInfoListUpdate']>
|
||||||
|
(
|
||||||
|
'NodeIKernelMsgListener/onMsgInfoListUpdate',
|
||||||
|
1,
|
||||||
|
5000,
|
||||||
|
(msgs) => {
|
||||||
|
if (msgs.find(m => m.msgId === msg.MsgId && m.recallTime !== '0')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
).catch(e => new Promise<undefined>((resolve, reject) => { resolve(undefined); }));
|
||||||
await NTQQMsgApi.recallMsg(msg.Peer, [msg.MsgId]);
|
await NTQQMsgApi.recallMsg(msg.Peer, [msg.MsgId]);
|
||||||
|
const data = await ret;
|
||||||
|
if (!data) {
|
||||||
|
throw new Error('Recall failed');
|
||||||
|
}
|
||||||
|
//await sleep(100);
|
||||||
|
//await NTQQMsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ class ForwardSingleMsg extends BaseAction<Payload, null> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async _handle(payload: Payload): Promise<null> {
|
protected async _handle(payload: Payload): Promise<null> {
|
||||||
const msg = await MessageUnique.getMsgIdAndPeerByShortId(payload.message_id);
|
const msg = MessageUnique.getMsgIdAndPeerByShortId(payload.message_id);
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
throw new Error(`无法找到消息${payload.message_id}`);
|
throw new Error(`无法找到消息${payload.message_id}`);
|
||||||
}
|
}
|
||||||
|
@@ -27,15 +27,23 @@ class GetMsg extends BaseAction<Payload, OB11Message> {
|
|||||||
if (!payload.message_id) {
|
if (!payload.message_id) {
|
||||||
throw Error('参数message_id不能为空');
|
throw Error('参数message_id不能为空');
|
||||||
}
|
}
|
||||||
const MsgShortId = await MessageUnique.getShortIdByMsgId(payload.message_id.toString());
|
const MsgShortId = MessageUnique.getShortIdByMsgId(payload.message_id.toString());
|
||||||
const msgIdWithPeer = await MessageUnique.getMsgIdAndPeerByShortId(MsgShortId || parseInt(payload.message_id.toString()));
|
const msgIdWithPeer = MessageUnique.getMsgIdAndPeerByShortId(MsgShortId || parseInt(payload.message_id.toString()));
|
||||||
if (!msgIdWithPeer) {
|
if (!msgIdWithPeer) {
|
||||||
throw ('消息不存在');
|
throw ('消息不存在');
|
||||||
}
|
}
|
||||||
|
const peer = { guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType };
|
||||||
const msg = await NTQQMsgApi.getMsgsByMsgId(
|
const msg = await NTQQMsgApi.getMsgsByMsgId(
|
||||||
{ guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType },
|
peer,
|
||||||
[msgIdWithPeer?.MsgId || payload.message_id.toString()]);
|
[msgIdWithPeer?.MsgId || payload.message_id.toString()]);
|
||||||
return await OB11Constructor.message(msg.msgList[0]);
|
const retMsg = await OB11Constructor.message(msg.msgList[0]);
|
||||||
|
try {
|
||||||
|
retMsg.message_id = MessageUnique.createMsg(peer, msg.msgList[0].msgId)!;
|
||||||
|
retMsg.message_seq = retMsg.message_id;
|
||||||
|
retMsg.real_id = retMsg.message_id;
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
return retMsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,33 +6,31 @@ import {
|
|||||||
IdMusicSignPostData,
|
IdMusicSignPostData,
|
||||||
NTQQFileApi,
|
NTQQFileApi,
|
||||||
NTQQMsgApi,
|
NTQQMsgApi,
|
||||||
|
Peer,
|
||||||
SendArkElement,
|
SendArkElement,
|
||||||
SendMessageElement,
|
SendMessageElement,
|
||||||
SendMsgElementConstructor,
|
SendMsgElementConstructor,
|
||||||
SignMusicWrapper
|
SignMusicWrapper
|
||||||
} from '@/core';
|
} from '@/core';
|
||||||
import { getGroupMember } from '@/core/data';
|
import { getGroupMember } from '@/core/data';
|
||||||
import { logDebug, logError, logWarn } from '@/common/utils/log';
|
import { logError, logWarn } from '@/common/utils/log';
|
||||||
import { uri2local } from '@/common/utils/file';
|
import { uri2local } from '@/common/utils/file';
|
||||||
import { ob11Config } from '@/onebot11/config';
|
import { ob11Config } from '@/onebot11/config';
|
||||||
import { RequestUtil } from '@/common/utils/request';
|
import { RequestUtil } from '@/common/utils/request';
|
||||||
import fs from 'node:fs';
|
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||||
|
console.log(process.pid);
|
||||||
export type MessageContext = {
|
export type MessageContext = {
|
||||||
group?: Group,
|
|
||||||
deleteAfterSentFiles: string[],
|
deleteAfterSentFiles: string[],
|
||||||
|
peer:Peer
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleOb11FileLikeMessage(
|
async function handleOb11FileLikeMessage(
|
||||||
{ data: { file, name: payloadFileName } }: OB11MessageFileBase,
|
{ data: inputdata }: OB11MessageFileBase,
|
||||||
{ deleteAfterSentFiles }: MessageContext
|
{ deleteAfterSentFiles }: MessageContext
|
||||||
) {
|
) {
|
||||||
const uri = file;
|
//有的奇怪的框架将url作为参数 而不是file 此时优先url 同时注意可能传入的是非file://开头的目录 By Mlikiowa
|
||||||
|
const { path, isLocal, fileName, errMsg,success } = (await uri2local(inputdata?.url || inputdata.file));
|
||||||
|
|
||||||
const { path, isLocal, fileName, errMsg } = (await uri2local(uri));
|
if (!success) {
|
||||||
|
|
||||||
if (errMsg) {
|
|
||||||
logError('文件下载失败', errMsg);
|
logError('文件下载失败', errMsg);
|
||||||
throw Error('文件下载失败' + errMsg);
|
throw Error('文件下载失败' + errMsg);
|
||||||
}
|
}
|
||||||
@@ -41,7 +39,7 @@ async function handleOb11FileLikeMessage(
|
|||||||
deleteAfterSentFiles.push(path);
|
deleteAfterSentFiles.push(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { path, fileName: payloadFileName || fileName };
|
return { path, fileName: inputdata.name || fileName };
|
||||||
}
|
}
|
||||||
|
|
||||||
const _handlers: {
|
const _handlers: {
|
||||||
@@ -55,12 +53,12 @@ const _handlers: {
|
|||||||
[OB11MessageDataType.text]: async ({ data: { text } }) => SendMsgElementConstructor.text(text),
|
[OB11MessageDataType.text]: async ({ data: { text } }) => SendMsgElementConstructor.text(text),
|
||||||
|
|
||||||
[OB11MessageDataType.at]: async ({ data: { qq: atQQ } }, context) => {
|
[OB11MessageDataType.at]: async ({ data: { qq: atQQ } }, context) => {
|
||||||
if (!context.group) return undefined;
|
if (!context.peer) return undefined;
|
||||||
|
|
||||||
if (atQQ === 'all') return SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员');
|
if (atQQ === 'all') return SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员');
|
||||||
|
|
||||||
// then the qq is a group member
|
// then the qq is a group member
|
||||||
const atMember = await getGroupMember(context.group.groupCode, atQQ);
|
const atMember = await getGroupMember(context.peer.peerUid, atQQ);
|
||||||
return atMember ?
|
return atMember ?
|
||||||
SendMsgElementConstructor.at(atQQ, atMember.uid, AtType.atUser, atMember.cardName || atMember.nick) :
|
SendMsgElementConstructor.at(atQQ, atMember.uid, AtType.atUser, atMember.cardName || atMember.nick) :
|
||||||
undefined;
|
undefined;
|
||||||
@@ -209,7 +207,7 @@ const handlers = <{
|
|||||||
|
|
||||||
export default async function createSendElements(
|
export default async function createSendElements(
|
||||||
messageData: OB11MessageData[],
|
messageData: OB11MessageData[],
|
||||||
group?: Group,
|
peer: Peer,
|
||||||
ignoreTypes: OB11MessageDataType[] = []
|
ignoreTypes: OB11MessageDataType[] = []
|
||||||
) {
|
) {
|
||||||
const deleteAfterSentFiles: string[] = [];
|
const deleteAfterSentFiles: string[] = [];
|
||||||
@@ -220,7 +218,7 @@ export default async function createSendElements(
|
|||||||
}
|
}
|
||||||
const callResult = handlers[sendMsg.type](
|
const callResult = handlers[sendMsg.type](
|
||||||
sendMsg,
|
sendMsg,
|
||||||
{ group, deleteAfterSentFiles }
|
{ peer, deleteAfterSentFiles }
|
||||||
)?.catch(undefined);
|
)?.catch(undefined);
|
||||||
callResultList.push(callResult);
|
callResultList.push(callResult);
|
||||||
}
|
}
|
||||||
@@ -231,7 +229,7 @@ export default async function createSendElements(
|
|||||||
|
|
||||||
export async function createSendElementsParallel(
|
export async function createSendElementsParallel(
|
||||||
messageData: OB11MessageData[],
|
messageData: OB11MessageData[],
|
||||||
group?: Group,
|
peer: Peer,
|
||||||
ignoreTypes: OB11MessageDataType[] = []
|
ignoreTypes: OB11MessageDataType[] = []
|
||||||
) {
|
) {
|
||||||
const deleteAfterSentFiles: string[] = [];
|
const deleteAfterSentFiles: string[] = [];
|
||||||
@@ -239,7 +237,7 @@ export async function createSendElementsParallel(
|
|||||||
await Promise.all(
|
await Promise.all(
|
||||||
messageData.map(async sendMsg => ignoreTypes.includes(sendMsg.type) ?
|
messageData.map(async sendMsg => ignoreTypes.includes(sendMsg.type) ?
|
||||||
undefined :
|
undefined :
|
||||||
handlers[sendMsg.type](sendMsg, { group, deleteAfterSentFiles }))
|
handlers[sendMsg.type](sendMsg, { peer, deleteAfterSentFiles }))
|
||||||
).then(
|
).then(
|
||||||
results => results.filter(
|
results => results.filter(
|
||||||
element => element !== undefined
|
element => element !== undefined
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { ChatType, ElementType, Group, NTQQMsgApi, Peer, RawMessage, SendMessageElement } from '@/core';
|
import { ChatType, ElementType, Group, NTQQMsgApi, Peer, RawMessage, SendMessageElement } from '@/core';
|
||||||
import { OB11MessageNode } from '@/onebot11/types';
|
import { OB11MessageDataType, OB11MessageNode } from '@/onebot11/types';
|
||||||
import { selfInfo } from '@/core/data';
|
import { selfInfo } from '@/core/data';
|
||||||
import createSendElements from '@/onebot11/action/msg/SendMsg/create-send-elements';
|
import createSendElements from '@/onebot11/action/msg/SendMsg/create-send-elements';
|
||||||
import { logDebug, logError } from '@/common/utils/log';
|
import { logDebug, logError } from '@/common/utils/log';
|
||||||
@@ -24,135 +24,92 @@ async function cloneMsg(msg: RawMessage): Promise<RawMessage | undefined> {
|
|||||||
if (sendElements.length === 0) {
|
if (sendElements.length === 0) {
|
||||||
logDebug('需要clone的消息无法解析,将会忽略掉', msg);
|
logDebug('需要clone的消息无法解析,将会忽略掉', msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//logDebug('克隆消息', sendElements);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const nodeMsg = await NTQQMsgApi.sendMsg(selfPeer, sendElements, true);
|
const nodeMsg = await NTQQMsgApi.sendMsg(selfPeer, sendElements, true);
|
||||||
await sleep(500); // 防止风控
|
|
||||||
return nodeMsg;
|
return nodeMsg;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError(e, '克隆转发消息失败,将忽略本条消息', msg);
|
logError(e, '克隆转发消息失败,将忽略本条消息', msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[], group: Group | undefined): Promise<RawMessage | null> {
|
export async function handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<RawMessage | null> {
|
||||||
const selfPeer = {
|
const selfPeer = {
|
||||||
chatType: ChatType.friend,
|
chatType: ChatType.friend,
|
||||||
peerUid: selfInfo.uid
|
peerUid: selfInfo.uid
|
||||||
};
|
};
|
||||||
let nodeMsgIds: string[] = [];
|
let nodeMsgIds: string[] = [];
|
||||||
|
|
||||||
// 先判断一遍是不是id和自定义混用
|
|
||||||
const needClone =
|
|
||||||
messageNodes.filter(node => node.data.id).length &&
|
|
||||||
messageNodes.filter(node => !node.data.id).length;
|
|
||||||
|
|
||||||
for (const messageNode of messageNodes) {
|
for (const messageNode of messageNodes) {
|
||||||
// 一个node表示一个人的消息
|
|
||||||
const nodeId = messageNode.data.id;
|
const nodeId = messageNode.data.id;
|
||||||
// 有nodeId表示一个子转发消息卡片
|
|
||||||
if (nodeId) {
|
if (nodeId) {
|
||||||
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId));
|
//对Mgsid和OB11ID混用情况兜底
|
||||||
if (!needClone) {
|
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
|
||||||
nodeMsgIds.push(nodeMsg!.MsgId);
|
if (!nodeMsg) {
|
||||||
} else {
|
logError('转发消息失败,未找到消息', nodeId);
|
||||||
if (nodeMsg!.Peer.peerUid !== selfInfo.uid) {
|
continue;
|
||||||
// need cloning
|
|
||||||
const rawClone = await NTQQMsgApi.getMsgsByMsgId(nodeMsg?.Peer!, [nodeMsg?.MsgId!]);
|
|
||||||
const clonedMsg = await cloneMsg(rawClone.msgList[0]);
|
|
||||||
if (clonedMsg) {
|
|
||||||
nodeMsgIds.push(clonedMsg.msgId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
nodeMsgIds.push(nodeMsg.MsgId);
|
||||||
} else {
|
} else {
|
||||||
// 自定义的消息
|
// 自定义的消息
|
||||||
// 提取消息段,发给自己生成消息id
|
|
||||||
try {
|
try {
|
||||||
const { sendElements } = await createSendElements(normalize(messageNode.data.content), group);
|
const OB11Data = normalize(messageNode.data.content);
|
||||||
//logDebug('开始生成转发节点', sendElements);
|
//筛选node消息
|
||||||
const sendElementsSplit: SendMessageElement[][] = [];
|
const isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息
|
||||||
let splitIndex = 0;
|
if (isNodeMsg !== 0) {
|
||||||
for (const sendElement of sendElements) {
|
if (isNodeMsg !== OB11Data.length) { logError('子消息中包含非node消息 跳过不合法部分'); continue; }
|
||||||
if (!sendElementsSplit[splitIndex]) {
|
const nodeMsg = await handleForwardNode(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
||||||
sendElementsSplit[splitIndex] = [];
|
if (nodeMsg) { nodeMsgIds.push(nodeMsg.msgId); MessageUnique.createMsg(selfPeer, nodeMsg.msgId); }
|
||||||
}
|
//完成子卡片生成跳过后续
|
||||||
|
continue;
|
||||||
if (sendElement.elementType === ElementType.FILE || sendElement.elementType === ElementType.VIDEO) {
|
|
||||||
if (sendElementsSplit[splitIndex].length > 0) {
|
|
||||||
splitIndex++;
|
|
||||||
}
|
|
||||||
sendElementsSplit[splitIndex] = [sendElement];
|
|
||||||
splitIndex++;
|
|
||||||
} else {
|
|
||||||
sendElementsSplit[splitIndex].push(sendElement);
|
|
||||||
}
|
|
||||||
//logDebug(sendElementsSplit);
|
|
||||||
}
|
}
|
||||||
// log("分割后的转发节点", sendElementsSplit)
|
const { sendElements } = await createSendElements(OB11Data, destPeer);
|
||||||
|
//拆分消息
|
||||||
|
const MixElement = sendElements.filter(element => element.elementType !== ElementType.FILE && element.elementType !== ElementType.VIDEO);
|
||||||
|
const SingleElement = sendElements.filter(element => element.elementType === ElementType.FILE || element.elementType === ElementType.VIDEO).map(e => [e]);
|
||||||
|
const AllElement: SendMessageElement[][] = [MixElement, ...SingleElement].filter(e => e !== undefined && e.length !== 0);
|
||||||
const MsgNodeList: Promise<RawMessage | undefined>[] = [];
|
const MsgNodeList: Promise<RawMessage | undefined>[] = [];
|
||||||
for (const sendElementsSplitElement of sendElementsSplit) {
|
for (const sendElementsSplitElement of AllElement) {
|
||||||
MsgNodeList.push(sendMsg(selfPeer, sendElementsSplitElement, [], true));
|
MsgNodeList.push(sendMsg(selfPeer, sendElementsSplitElement, [], true).catch(e => new Promise((resolve, reject) => { resolve(undefined); })));
|
||||||
await sleep(Math.trunc(sendElementsSplit.length / 10) * 100);
|
|
||||||
//await sleep(10);
|
|
||||||
}
|
}
|
||||||
for (const msgNode of MsgNodeList) {
|
(await Promise.allSettled(MsgNodeList)).map((result) => {
|
||||||
const result = await msgNode;
|
if (result.status === 'fulfilled' && result.value) {
|
||||||
if (result) {
|
nodeMsgIds.push(result.value.msgId);
|
||||||
nodeMsgIds.push(result.msgId);
|
MessageUnique.createMsg(selfPeer, result.value.msgId);
|
||||||
}
|
}
|
||||||
//logDebug('转发节点生成成功', result.msgId);
|
});
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logDebug('生成转发消息节点失败', e);
|
logDebug('生成转发消息节点失败', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 检查srcPeer是否一致,不一致则需要克隆成自己的消息, 让所有srcPeer都变成自己的,使其保持一致才能够转发
|
|
||||||
const nodeMsgArray: Array<RawMessage> = [];
|
const nodeMsgArray: Array<RawMessage> = [];
|
||||||
|
|
||||||
let srcPeer: Peer | undefined = undefined;
|
let srcPeer: Peer | undefined = undefined;
|
||||||
let needSendSelf = false;
|
let needSendSelf = false;
|
||||||
|
//检测是否处于同一个Peer 不在同一个peer则全部消息由自身发送
|
||||||
for (const msgId of nodeMsgIds) {
|
for (const msgId of nodeMsgIds) {
|
||||||
const nodeMsgPeer = await MessageUnique.getPeerByMsgId(msgId);
|
const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId);
|
||||||
const nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer?.Peer!, [msgId])).msgList[0];
|
if (!nodeMsgPeer) {
|
||||||
if (nodeMsg) {
|
logError('转发消息失败,未找到消息', msgId);
|
||||||
nodeMsgArray.push(nodeMsg);
|
continue;
|
||||||
if (!srcPeer) {
|
|
||||||
srcPeer = { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid };
|
|
||||||
} else if (srcPeer.peerUid !== nodeMsg.peerUid) {
|
|
||||||
needSendSelf = true;
|
|
||||||
srcPeer = selfPeer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
|
||||||
|
srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid };
|
||||||
|
if (srcPeer.peerUid !== nodeMsg.peerUid) {
|
||||||
|
needSendSelf = true;
|
||||||
|
}
|
||||||
|
nodeMsgArray.push(nodeMsg);
|
||||||
}
|
}
|
||||||
// logDebug('nodeMsgArray', nodeMsgArray);
|
|
||||||
nodeMsgIds = nodeMsgArray.map(msg => msg.msgId);
|
nodeMsgIds = nodeMsgArray.map(msg => msg.msgId);
|
||||||
|
let retMsgIds: string[] = [];
|
||||||
if (needSendSelf) {
|
if (needSendSelf) {
|
||||||
//logDebug('需要克隆转发消息');
|
|
||||||
for (const [index, msg] of nodeMsgArray.entries()) {
|
for (const [index, msg] of nodeMsgArray.entries()) {
|
||||||
if (msg.peerUid !== selfInfo.uid) {
|
if (msg.peerUid === selfInfo.uid) continue;
|
||||||
const clonedMsg = await cloneMsg(msg);
|
const ClonedMsg = await cloneMsg(msg);
|
||||||
if (clonedMsg) {
|
if (ClonedMsg) retMsgIds.push(ClonedMsg.msgId);
|
||||||
nodeMsgIds[index] = clonedMsg.msgId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
retMsgIds = nodeMsgIds;
|
||||||
}
|
}
|
||||||
// elements之间用换行符分隔
|
if (nodeMsgIds.length === 0) throw Error('转发消息失败,生成节点为空');
|
||||||
// let _sendForwardElements: SendMessageElement[] = []
|
|
||||||
// for(let i = 0; i < sendForwardElements.length; i++){
|
|
||||||
// _sendForwardElements.push(sendForwardElements[i])
|
|
||||||
// _sendForwardElements.push(SendMsgElementConstructor.text("\n\n"))
|
|
||||||
// }
|
|
||||||
// const nodeMsg = await NTQQApi.sendMsg(selfPeer, _sendForwardElements, true);
|
|
||||||
// nodeIds.push(nodeMsg.msgId)
|
|
||||||
// await sleep(500);
|
|
||||||
// 开发转发
|
|
||||||
if (nodeMsgIds.length === 0) {
|
|
||||||
throw Error('转发消息失败,生成节点为空');
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
logDebug('开发转发', srcPeer, destPeer, nodeMsgIds);
|
logDebug('开发转发', srcPeer, destPeer, nodeMsgIds);
|
||||||
return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, nodeMsgIds);
|
return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, nodeMsgIds);
|
||||||
|
@@ -10,6 +10,7 @@ import { ActionName, BaseCheckResult } from '@/onebot11/action/types';
|
|||||||
import { getGroup } from '@/core/data';
|
import { getGroup } from '@/core/data';
|
||||||
import { ChatType, ElementType, Group, NTQQFileApi, NTQQFriendApi, NTQQMsgApi, NTQQUserApi, Peer, SendMessageElement, } from '@/core';
|
import { ChatType, ElementType, Group, NTQQFileApi, NTQQFriendApi, NTQQMsgApi, NTQQUserApi, Peer, SendMessageElement, } from '@/core';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
import fsPromise from 'node:fs/promises';
|
||||||
import { logDebug, logError } from '@/common/utils/log';
|
import { logDebug, logError } from '@/common/utils/log';
|
||||||
import { decodeCQCode } from '@/onebot11/cqcode';
|
import { decodeCQCode } from '@/onebot11/cqcode';
|
||||||
import createSendElements from './create-send-elements';
|
import createSendElements from './create-send-elements';
|
||||||
@@ -66,25 +67,16 @@ export async function sendMsg(peer: Peer, sendElements: SendMessageElement[], de
|
|||||||
}
|
}
|
||||||
const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, timeout);
|
const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, timeout);
|
||||||
try {
|
try {
|
||||||
returnMsg!.id = await MessageUnique.createMsg({ chatType: peer.chatType, guildId: '', peerUid: peer.peerUid }, returnMsg!.msgId);
|
returnMsg!.id = MessageUnique.createMsg({ chatType: peer.chatType, guildId: '', peerUid: peer.peerUid }, returnMsg!.msgId);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logDebug('发送消息id获取失败', e);
|
logDebug('发送消息id获取失败', e);
|
||||||
returnMsg!.id = 0;
|
returnMsg!.id = 0;
|
||||||
}
|
}
|
||||||
|
deleteAfterSentFiles.map((f) => { fsPromise.unlink(f).then().catch(e => logError('发送消息删除文件失败', e)); });
|
||||||
deleteAfterSentFiles.map((f) => {
|
|
||||||
try {
|
|
||||||
fs.unlinkSync(f);
|
|
||||||
} catch (e) {
|
|
||||||
logError('发送消息删除文件失败', e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return returnMsg;
|
return returnMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode): Promise<{
|
async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode): Promise<Peer> {
|
||||||
peer: Peer, group?: Group
|
|
||||||
}> {
|
|
||||||
// This function determines the type of message by the existence of user_id / group_id,
|
// This function determines the type of message by the existence of user_id / group_id,
|
||||||
// not message_type.
|
// not message_type.
|
||||||
// This redundant design of Ob11 here should be blamed.
|
// This redundant design of Ob11 here should be blamed.
|
||||||
@@ -92,11 +84,8 @@ async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode)
|
|||||||
if ((contextMode === ContextMode.Group || contextMode === ContextMode.Normal) && payload.group_id) {
|
if ((contextMode === ContextMode.Group || contextMode === ContextMode.Normal) && payload.group_id) {
|
||||||
const group = (await getGroup(payload.group_id))!; // checked before
|
const group = (await getGroup(payload.group_id))!; // checked before
|
||||||
return {
|
return {
|
||||||
peer: {
|
chatType: ChatType.group,
|
||||||
chatType: ChatType.group,
|
peerUid: group.groupCode
|
||||||
peerUid: group.groupCode
|
|
||||||
},
|
|
||||||
group: group,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if ((contextMode === ContextMode.Private || contextMode === ContextMode.Normal) && payload.user_id) {
|
if ((contextMode === ContextMode.Private || contextMode === ContextMode.Normal) && payload.user_id) {
|
||||||
@@ -104,10 +93,9 @@ async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode)
|
|||||||
const isBuddy = await NTQQFriendApi.isBuddy(Uid!);
|
const isBuddy = await NTQQFriendApi.isBuddy(Uid!);
|
||||||
//console.log("[调试代码] UIN:", payload.user_id, " UID:", Uid, " IsBuddy:", isBuddy);
|
//console.log("[调试代码] UIN:", payload.user_id, " UID:", Uid, " IsBuddy:", isBuddy);
|
||||||
return {
|
return {
|
||||||
peer: {
|
chatType: isBuddy ? ChatType.friend : ChatType.temp,
|
||||||
chatType: isBuddy ? ChatType.friend : ChatType.temp,
|
peerUid: Uid!,
|
||||||
peerUid: Uid!
|
guildId: payload.group_id || ''//临时主动发起时需要传入群号
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
throw '请指定 group_id 或 user_id';
|
throw '请指定 group_id 或 user_id';
|
||||||
@@ -134,7 +122,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
return { valid: false, message: `群${payload.group_id}不存在` };
|
return { valid: false, message: `群${payload.group_id}不存在` };
|
||||||
}
|
}
|
||||||
if (payload.user_id && payload.message_type !== 'group') {
|
if (payload.user_id && payload.message_type !== 'group') {
|
||||||
const uid = await NTQQUserApi.getUidByUin(payload.user_id);
|
const uid = await NTQQUserApi.getUidByUin(payload.user_id.toString());
|
||||||
const isBuddy = await NTQQFriendApi.isBuddy(uid!);
|
const isBuddy = await NTQQFriendApi.isBuddy(uid!);
|
||||||
// 此处有问题
|
// 此处有问题
|
||||||
if (!isBuddy) {
|
if (!isBuddy) {
|
||||||
@@ -145,7 +133,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async _handle(payload: OB11PostSendMsg): Promise<{ message_id: number }> {
|
protected async _handle(payload: OB11PostSendMsg): Promise<{ message_id: number }> {
|
||||||
const { peer, group } = await createContext(payload, this.contextMode);
|
const peer = await createContext(payload, this.contextMode);
|
||||||
|
|
||||||
const messages = normalize(
|
const messages = normalize(
|
||||||
payload.message,
|
payload.message,
|
||||||
@@ -153,9 +141,9 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
||||||
const returnMsg = await handleForwardNode(peer, messages as OB11MessageNode[], group);
|
const returnMsg = await handleForwardNode(peer, messages as OB11MessageNode[]);
|
||||||
if (returnMsg) {
|
if (returnMsg) {
|
||||||
const msgShortId = await MessageUnique.createMsg({ guildId: '', peerUid: peer.peerUid, chatType: peer.chatType }, returnMsg!.msgId);
|
const msgShortId = MessageUnique.createMsg({ guildId: '', peerUid: peer.peerUid, chatType: peer.chatType }, returnMsg!.msgId);
|
||||||
return { message_id: msgShortId! };
|
return { message_id: msgShortId! };
|
||||||
} else {
|
} else {
|
||||||
throw Error('发送转发消息失败');
|
throw Error('发送转发消息失败');
|
||||||
@@ -169,7 +157,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
}
|
}
|
||||||
// log("send msg:", peer, sendElements)
|
// log("send msg:", peer, sendElements)
|
||||||
|
|
||||||
const { sendElements, deleteAfterSentFiles } = await createSendElements(messages, group);
|
const { sendElements, deleteAfterSentFiles } = await createSendElements(messages, peer);
|
||||||
//console.log(peer, JSON.stringify(sendElements,null,2));
|
//console.log(peer, JSON.stringify(sendElements,null,2));
|
||||||
const returnMsg = await sendMsg(peer, sendElements, deleteAfterSentFiles);
|
const returnMsg = await sendMsg(peer, sendElements, deleteAfterSentFiles);
|
||||||
return { message_id: returnMsg!.id! };
|
return { message_id: returnMsg!.id! };
|
||||||
|
@@ -11,5 +11,4 @@ class SendPrivateMsg extends SendMsg {
|
|||||||
return super.check(payload);
|
return super.check(payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SendPrivateMsg;
|
export default SendPrivateMsg;
|
||||||
|
@@ -14,7 +14,6 @@ const SchemaData = {
|
|||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
type Payload = FromSchema<typeof SchemaData>;
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
export class SetMsgEmojiLike extends BaseAction<Payload, any> {
|
export class SetMsgEmojiLike extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.SetMsgEmojiLike;
|
actionName = ActionName.SetMsgEmojiLike;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
|
@@ -4,7 +4,6 @@ import CanSendRecord from './CanSendRecord';
|
|||||||
interface ReturnType {
|
interface ReturnType {
|
||||||
yes: boolean
|
yes: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class CanSendImage extends CanSendRecord {
|
export default class CanSendImage extends CanSendRecord {
|
||||||
actionName = ActionName.CanSendImage;
|
actionName = ActionName.CanSendImage;
|
||||||
}
|
}
|
||||||
|
@@ -3,8 +3,6 @@ import { OB11User } from '../../types';
|
|||||||
import { OB11Constructor } from '../../constructor';
|
import { OB11Constructor } from '../../constructor';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { napCatCore } from '@/core';
|
|
||||||
|
|
||||||
|
|
||||||
class GetLoginInfo extends BaseAction<null, OB11User> {
|
class GetLoginInfo extends BaseAction<null, OB11User> {
|
||||||
actionName = ActionName.GetLoginInfo;
|
actionName = ActionName.GetLoginInfo;
|
||||||
|
@@ -15,8 +15,8 @@ export interface InvalidCheckResult {
|
|||||||
|
|
||||||
export enum ActionName {
|
export enum ActionName {
|
||||||
// 以下为扩展napcat扩展
|
// 以下为扩展napcat扩展
|
||||||
SharePeer = 'ArkShareGroup',
|
SharePeer = 'ArkSharePeer',
|
||||||
ShareGroupEx = 'ArkSharePeer',
|
ShareGroupEx = 'ArkShareGroupEx',
|
||||||
RebootNormal = 'reboot_normal',//无快速登录重新启动
|
RebootNormal = 'reboot_normal',//无快速登录重新启动
|
||||||
GetRobotUinRange = 'get_robot_uin_range',
|
GetRobotUinRange = 'get_robot_uin_range',
|
||||||
SetOnlineStatus = 'set_online_status',
|
SetOnlineStatus = 'set_online_status',
|
||||||
@@ -101,5 +101,7 @@ export enum ActionName {
|
|||||||
GetProfileLike = 'get_profile_like',
|
GetProfileLike = 'get_profile_like',
|
||||||
SetGroupHeader = 'set_group_head',
|
SetGroupHeader = 'set_group_head',
|
||||||
FetchCustomFace = 'fetch_custom_face',
|
FetchCustomFace = 'fetch_custom_face',
|
||||||
GOCQHTTP_UploadPrivateFile = 'upload_private_file'
|
GOCQHTTP_UploadPrivateFile = 'upload_private_file',
|
||||||
|
TestApi01 = 'test_api_01',
|
||||||
|
FetchEmojioLike = 'fetch_emoji_like'
|
||||||
}
|
}
|
||||||
|
@@ -5,8 +5,7 @@ import BaseAction from '../BaseAction';
|
|||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { NTQQFriendApi } from '@/core';
|
import { NTQQFriendApi } from '@/core';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { requireMinNTQQBuild } from '@/common/utils/QQBasicInfo';
|
||||||
|
|
||||||
// no_cache get时传字符串
|
// no_cache get时传字符串
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -20,6 +19,10 @@ export default class GetFriendList extends BaseAction<Payload, OB11User[]> {
|
|||||||
actionName = ActionName.GetFriendList;
|
actionName = ActionName.GetFriendList;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
|
if (requireMinNTQQBuild('26702')) {
|
||||||
|
//全新逻辑
|
||||||
|
return OB11Constructor.friendsV2(await NTQQFriendApi.getBuddyV2(payload?.no_cache === true || payload?.no_cache === 'true'));
|
||||||
|
}
|
||||||
if (friends.size === 0 || payload?.no_cache === true || payload?.no_cache === 'true') {
|
if (friends.size === 0 || payload?.no_cache === true || payload?.no_cache === 'true') {
|
||||||
const _friends = await NTQQFriendApi.getFriends(true);
|
const _friends = await NTQQFriendApi.getFriends(true);
|
||||||
// log('强制刷新好友列表,结果: ', _friends)
|
// log('强制刷新好友列表,结果: ', _friends)
|
||||||
|
@@ -1,12 +1,52 @@
|
|||||||
|
|
||||||
|
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 { NTQQUserApi } from '@/core';
|
import { NTQQMsgApi, NTQQUserApi } from '@/core';
|
||||||
|
import { OB11Constructor } from '@/onebot11/constructor';
|
||||||
|
|
||||||
export default class GetRecentContact extends BaseAction<void, any> {
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
count: { type: ['number', 'string'] }
|
||||||
|
}
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export default class GetRecentContact extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.GetRecentContact;
|
actionName = ActionName.GetRecentContact;
|
||||||
protected async _handle(payload: void) {
|
PayloadSchema = SchemaData;
|
||||||
//没有效果
|
protected async _handle(payload: Payload) {
|
||||||
return await NTQQUserApi.getRecentContactListSnapShot(10);
|
const ret = await NTQQUserApi.getRecentContactListSnapShot(parseInt((payload.count || 10).toString()));
|
||||||
|
const data = await Promise.all(ret.info.changedList.map(async (t) => {
|
||||||
|
const FastMsg = await NTQQMsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]);
|
||||||
|
if (FastMsg.msgList.length > 0) {
|
||||||
|
//扩展ret.info.changedList
|
||||||
|
const lastestMsg = await OB11Constructor.message(FastMsg.msgList[0]);
|
||||||
|
return {
|
||||||
|
lastestMsg: lastestMsg,
|
||||||
|
peerUin: t.peerUin,
|
||||||
|
remark: t.remark,
|
||||||
|
msgTime: t.msgTime,
|
||||||
|
chatType: t.chatType,
|
||||||
|
msgId: t.msgId,
|
||||||
|
sendNickName: t.sendNickName,
|
||||||
|
sendMemberName: t.sendMemberName,
|
||||||
|
peerName: t.peerName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
peerUin: t.peerUin,
|
||||||
|
remark: t.remark,
|
||||||
|
msgTime: t.msgTime,
|
||||||
|
chatType: t.chatType,
|
||||||
|
msgId: t.msgId,
|
||||||
|
sendNickName: t.sendNickName,
|
||||||
|
sendMemberName: t.sendMemberName,
|
||||||
|
peerName: t.peerName
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,6 @@ const SchemaData = {
|
|||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
type Payload = FromSchema<typeof SchemaData>;
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
export default class SendLike extends BaseAction<Payload, null> {
|
export default class SendLike extends BaseAction<Payload, null> {
|
||||||
actionName = ActionName.SendLike;
|
actionName = ActionName.SendLike;
|
||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
|
@@ -1,10 +1,4 @@
|
|||||||
import fs from 'node:fs';
|
|
||||||
import path from 'node:path';
|
|
||||||
import { selfInfo } from '@/core/data';
|
|
||||||
import { logDebug, logError } from '@/common/utils/log';
|
|
||||||
import { ConfigBase } from '@/common/utils/ConfigBase';
|
import { ConfigBase } from '@/common/utils/ConfigBase';
|
||||||
import { json } from 'stream/consumers';
|
|
||||||
|
|
||||||
export interface OB11Config {
|
export interface OB11Config {
|
||||||
http: {
|
http: {
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
@@ -36,7 +30,7 @@ export interface OB11Config {
|
|||||||
Record: boolean,
|
Record: boolean,
|
||||||
RecordList: Array<string>
|
RecordList: Array<string>
|
||||||
},
|
},
|
||||||
read(): OB11Config;
|
read(): OB11Config | null;
|
||||||
|
|
||||||
save(config: OB11Config): void;
|
save(config: OB11Config): void;
|
||||||
}
|
}
|
||||||
|
@@ -12,8 +12,10 @@ import {
|
|||||||
import {
|
import {
|
||||||
AtType,
|
AtType,
|
||||||
ChatType,
|
ChatType,
|
||||||
|
ChatType2,
|
||||||
FaceIndex,
|
FaceIndex,
|
||||||
Friend,
|
Friend,
|
||||||
|
FriendV2,
|
||||||
GrayTipElementSubType,
|
GrayTipElementSubType,
|
||||||
Group,
|
Group,
|
||||||
GroupMember,
|
GroupMember,
|
||||||
@@ -22,6 +24,7 @@ import {
|
|||||||
RawMessage,
|
RawMessage,
|
||||||
SelfInfo,
|
SelfInfo,
|
||||||
Sex,
|
Sex,
|
||||||
|
SimpleInfo,
|
||||||
TipGroupElementType,
|
TipGroupElementType,
|
||||||
User,
|
User,
|
||||||
VideoElement
|
VideoElement
|
||||||
@@ -35,15 +38,16 @@ import { OB11GroupNoticeEvent } from './event/notice/OB11GroupNoticeEvent';
|
|||||||
|
|
||||||
import { calcQQLevel } from '../common/utils/qqlevel';
|
import { calcQQLevel } from '../common/utils/qqlevel';
|
||||||
import { log, logDebug, logError, logWarn } from '../common/utils/log';
|
import { log, logDebug, logError, logWarn } from '../common/utils/log';
|
||||||
import { sleep } from '../common/utils/helper';
|
import { sleep, UUIDConverter } from '../common/utils/helper';
|
||||||
import { OB11GroupTitleEvent } from './event/notice/OB11GroupTitleEvent';
|
import { OB11GroupTitleEvent } from './event/notice/OB11GroupTitleEvent';
|
||||||
import { OB11GroupCardEvent } from './event/notice/OB11GroupCardEvent';
|
import { OB11GroupCardEvent } from './event/notice/OB11GroupCardEvent';
|
||||||
import { OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent';
|
import { OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent';
|
||||||
import { ob11Config } from '@/onebot11/config';
|
import { ob11Config } from '@/onebot11/config';
|
||||||
import { deleteGroup, getGroupMember, groupMembers, selfInfo, tempGroupCodeMap } from '@/core/data';
|
import { deleteGroup, getGroupMember, groupMembers, selfInfo } from '@/core/data';
|
||||||
import { NTQQFileApi, NTQQGroupApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis';
|
import { NTQQFileApi, NTQQGroupApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis';
|
||||||
import { OB11GroupMsgEmojiLikeEvent } from '@/onebot11/event/notice/OB11MsgEmojiLikeEvent';
|
import { OB11GroupMsgEmojiLikeEvent } from '@/onebot11/event/notice/OB11MsgEmojiLikeEvent';
|
||||||
import { OB11FriendPokeEvent, OB11GroupPokeEvent } from './event/notice/OB11PokeEvent';
|
import { OB11FriendPokeEvent, OB11GroupPokeEvent } from './event/notice/OB11PokeEvent';
|
||||||
|
import { OB11FriendAddNoticeEvent } from './event/notice/OB11FriendAddNoticeEvent';
|
||||||
import { OB11BaseNoticeEvent } from './event/notice/OB11BaseNoticeEvent';
|
import { OB11BaseNoticeEvent } from './event/notice/OB11BaseNoticeEvent';
|
||||||
import { OB11GroupEssenceEvent } from './event/notice/OB11GroupEssenceEvent';
|
import { OB11GroupEssenceEvent } from './event/notice/OB11GroupEssenceEvent';
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||||
@@ -62,7 +66,7 @@ export class OB11Constructor {
|
|||||||
real_id: msg.id!,
|
real_id: msg.id!,
|
||||||
message_type: msg.chatType == ChatType.group ? 'group' : 'private',
|
message_type: msg.chatType == ChatType.group ? 'group' : 'private',
|
||||||
sender: {
|
sender: {
|
||||||
user_id: parseInt(msg.senderUin!),
|
user_id: parseInt(msg.senderUin || '0'),
|
||||||
nickname: msg.sendNickName,
|
nickname: msg.sendNickName,
|
||||||
card: msg.sendMemberName || '',
|
card: msg.sendMemberName || '',
|
||||||
},
|
},
|
||||||
@@ -89,44 +93,56 @@ export class OB11Constructor {
|
|||||||
}
|
}
|
||||||
else if (msg.chatType == ChatType.friend) {
|
else if (msg.chatType == ChatType.friend) {
|
||||||
resMsg.sub_type = 'friend';
|
resMsg.sub_type = 'friend';
|
||||||
const user = await NTQQUserApi.getUserDetailInfoByUin(msg.senderUin!);
|
resMsg.sender.nickname = (await NTQQUserApi.getUserDetailInfo(msg.senderUid)).nick;
|
||||||
resMsg.sender.nickname = user.info.nick;
|
//const user = await NTQQUserApi.getUserDetailInfoByUin(msg.senderUin!);
|
||||||
|
//resMsg.sender.nickname = user.info.nick;
|
||||||
}
|
}
|
||||||
else if (msg.chatType == ChatType.temp) {
|
else if (msg.chatType as unknown as ChatType2 == ChatType2.KCHATTYPETEMPC2CFROMGROUP) {
|
||||||
resMsg.sub_type = 'group';
|
resMsg.sub_type = 'group';
|
||||||
const tempGroupCode = tempGroupCodeMap[msg.peerUin];
|
let ret = await NTQQMsgApi.getTempChatInfo(ChatType2.KCHATTYPETEMPC2CFROMGROUP, msg.senderUid);
|
||||||
if (tempGroupCode) {
|
if (ret.result === 0) {
|
||||||
resMsg.group_id = parseInt(tempGroupCode);
|
resMsg.group_id = parseInt(ret.tmpChatInfo!.groupCode);
|
||||||
|
resMsg.sender.nickname = ret.tmpChatInfo!.fromNick;
|
||||||
|
} else {
|
||||||
|
resMsg.group_id = 284840486;//兜底数据
|
||||||
|
resMsg.sender.nickname = "临时会话";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const element of msg.elements) {
|
for (const element of msg.elements) {
|
||||||
const message_data: OB11MessageData | any = {
|
let message_data: OB11MessageData = {
|
||||||
data: {},
|
data: {} as any,
|
||||||
type: 'unknown'
|
type: 'unknown' as any
|
||||||
};
|
};
|
||||||
if (element.textElement && element.textElement?.atType !== AtType.notAt) {
|
if (element.textElement && element.textElement?.atType !== AtType.notAt) {
|
||||||
message_data['type'] = OB11MessageDataType.at;
|
let qq: `${number}` | 'all';
|
||||||
|
let name: string | undefined;
|
||||||
if (element.textElement.atType == AtType.atAll) {
|
if (element.textElement.atType == AtType.atAll) {
|
||||||
// message_data["data"]["mention"] = "all"
|
qq = 'all';
|
||||||
message_data['data']['qq'] = 'all';
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const atUid = element.textElement.atNtUid;
|
const { atNtUid, content } = element.textElement;
|
||||||
let atQQ = element.textElement.atUid;
|
let atQQ = element.textElement.atUid;
|
||||||
if (!atQQ || atQQ === '0') {
|
if (!atQQ || atQQ === '0') {
|
||||||
const atMember = await getGroupMember(msg.peerUin, atUid);
|
const atMember = await getGroupMember(msg.peerUin, atNtUid);
|
||||||
if (atMember) {
|
if (atMember) {
|
||||||
atQQ = atMember.uin;
|
atQQ = atMember.uin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (atQQ) {
|
if (atQQ) {
|
||||||
// message_data["data"]["mention"] = atQQ
|
qq = atQQ as `${number}`;
|
||||||
message_data['data']['qq'] = atQQ;
|
name = content.replace('@', '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
message_data = {
|
||||||
|
type: OB11MessageDataType.at,
|
||||||
|
data: {
|
||||||
|
qq: qq!,
|
||||||
|
name
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else if (element.textElement) {
|
else if (element.textElement) {
|
||||||
message_data['type'] = 'text';
|
message_data['type'] = OB11MessageDataType.text;
|
||||||
|
|
||||||
let text = element.textElement.content;
|
let text = element.textElement.content;
|
||||||
if (!text.trim()) {
|
if (!text.trim()) {
|
||||||
@@ -139,40 +155,42 @@ export class OB11Constructor {
|
|||||||
message_data['data']['text'] = text;
|
message_data['data']['text'] = text;
|
||||||
}
|
}
|
||||||
else if (element.replyElement) {
|
else if (element.replyElement) {
|
||||||
message_data['type'] = 'reply';
|
message_data['type'] = OB11MessageDataType.reply;
|
||||||
//log("收到回复消息", element.replyElement);
|
//log("收到回复消息", element.replyElement);
|
||||||
try {
|
try {
|
||||||
//做这么多都是因为NC速度太快 可能nt还没有写入数据库
|
const records = msg.records.find(msgRecord => msgRecord.msgId === element.replyElement.sourceMsgIdInRecords);
|
||||||
//const records = msg.records.find(msgRecord => msgRecord.msgId === element.replyElement.sourceMsgIdInRecords);
|
|
||||||
const peer = {
|
const peer = {
|
||||||
chatType: msg.chatType,
|
chatType: msg.chatType,
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
guildId: '',
|
guildId: '',
|
||||||
};
|
};
|
||||||
let replyMsg: RawMessage | undefined;
|
let replyMsg: RawMessage | undefined;
|
||||||
|
if (!records) throw new Error('找不到回复消息');
|
||||||
replyMsg = (await NTQQMsgApi.getMsgsBySeqAndCount({ peerUid: msg.peerUid, guildId: '', chatType: msg.chatType }, element.replyElement.replayMsgSeq, 1, true, true)).msgList[0];
|
replyMsg = (await NTQQMsgApi.getMsgsBySeqAndCount({ peerUid: msg.peerUid, guildId: '', chatType: msg.chatType }, element.replyElement.replayMsgSeq, 1, true, true)).msgList[0];
|
||||||
if (!replyMsg || element.replyElement.replayMsgSeq !== replyMsg.msgSeq) {
|
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
|
||||||
replyMsg = (await NTQQMsgApi.getSingleMsg(peer, element.replyElement.replayMsgSeq)).msgList[0];
|
replyMsg = (await NTQQMsgApi.getSingleMsg(peer, element.replyElement.replayMsgSeq)).msgList[0];
|
||||||
}
|
}
|
||||||
|
if (msg.peerUin == '284840486') {
|
||||||
if (!replyMsg || element.replyElement.replayMsgSeq !== replyMsg.msgSeq) {
|
//合并消息内侧 消息具体定位不到
|
||||||
|
}
|
||||||
|
if ((!replyMsg || records.msgRandom !== replyMsg.msgRandom) && msg.peerUin !== '284840486') {
|
||||||
throw new Error('回复消息消息验证失败');
|
throw new Error('回复消息消息验证失败');
|
||||||
}
|
}
|
||||||
message_data['data']['id'] = MessageUnique.createMsg({ peerUid: msg.peerUid, guildId: '', chatType: msg.chatType }, replyMsg.msgId)?.toString();
|
message_data['data']['id'] = MessageUnique.createMsg({ peerUid: msg.peerUid, guildId: '', chatType: msg.chatType }, replyMsg.msgId)?.toString();
|
||||||
//log("找到回复消息", message_data['data']['id'], replyMsg.msgList[0].msgId)
|
//log("找到回复消息", message_data['data']['id'], replyMsg.msgList[0].msgId)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
message_data['type'] = "unknown";
|
message_data['type'] = 'unknown' as any;
|
||||||
message_data['data'] = undefined;
|
message_data['data'] = undefined;
|
||||||
logError('获取不到引用的消息', e.stack, element.replyElement.replayMsgSeq);
|
logError('获取不到引用的消息', e.stack, element.replyElement.replayMsgSeq);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (element.picElement) {
|
else if (element.picElement) {
|
||||||
message_data['type'] = 'image';
|
message_data['type'] = OB11MessageDataType.image;
|
||||||
// message_data["data"]["file"] = element.picElement.sourcePath
|
// message_data["data"]["file"] = element.picElement.sourcePath
|
||||||
message_data['data']['file'] = element.picElement.fileName;
|
message_data['data']['file'] = element.picElement.fileName;
|
||||||
message_data['data']['subType'] = element.picElement.picSubType;
|
message_data['data']['subType'] = element.picElement.picSubType;
|
||||||
|
message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId);
|
||||||
// message_data["data"]["path"] = element.picElement.sourcePath
|
// message_data["data"]["path"] = element.picElement.sourcePath
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -185,13 +203,12 @@ export class OB11Constructor {
|
|||||||
message_data['data']['file_size'] = element.picElement.fileSize;
|
message_data['data']['file_size'] = element.picElement.fileSize;
|
||||||
}
|
}
|
||||||
else if (element.fileElement) {
|
else if (element.fileElement) {
|
||||||
|
|
||||||
const FileElement = element.fileElement;
|
const FileElement = element.fileElement;
|
||||||
message_data['type'] = OB11MessageDataType.file;
|
message_data['type'] = OB11MessageDataType.file;
|
||||||
message_data['data']['file'] = FileElement.fileName;
|
message_data['data']['file'] = FileElement.fileName;
|
||||||
message_data['data']['path'] = FileElement.filePath;
|
message_data['data']['path'] = FileElement.filePath;
|
||||||
message_data['data']['url'] = FileElement.filePath;
|
message_data['data']['url'] = FileElement.filePath;
|
||||||
message_data['data']['file_id'] = FileElement.fileUuid;
|
message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId);
|
||||||
message_data['data']['file_size'] = FileElement.fileSize;
|
message_data['data']['file_size'] = FileElement.fileSize;
|
||||||
await NTQQFileApi.addFileCache({
|
await NTQQFileApi.addFileCache({
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
@@ -211,12 +228,18 @@ export class OB11Constructor {
|
|||||||
const videoElement: VideoElement = element.videoElement;
|
const videoElement: VideoElement = element.videoElement;
|
||||||
//读取视频链接并兜底
|
//读取视频链接并兜底
|
||||||
let videoUrl;//Array
|
let videoUrl;//Array
|
||||||
|
let peer:Peer = {
|
||||||
|
chatType: msg.chatType,
|
||||||
|
peerUid: msg.peerUid,
|
||||||
|
guildId: '0'
|
||||||
|
};
|
||||||
|
if (msg.peerUin == '284840486') {
|
||||||
|
peer = msg.parentMsgPeer;
|
||||||
|
//合并消息内部 应该进行特殊处理 可能需要重写peer 待测试与研究 Mlikiowa Taged TODO
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
videoUrl = await NTQQFileApi.getVideoUrl({
|
|
||||||
chatType: msg.chatType,
|
videoUrl = await NTQQFileApi.getVideoUrl(peer, msg.msgId, element.elementId);
|
||||||
peerUid: msg.peerUid,
|
|
||||||
guildId: '0'
|
|
||||||
}, msg.msgId, element.elementId);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
videoUrl = undefined;
|
videoUrl = undefined;
|
||||||
}
|
}
|
||||||
@@ -237,7 +260,7 @@ export class OB11Constructor {
|
|||||||
message_data['data']['file'] = videoElement.fileName;
|
message_data['data']['file'] = videoElement.fileName;
|
||||||
message_data['data']['path'] = videoDownUrl;
|
message_data['data']['path'] = videoDownUrl;
|
||||||
message_data['data']['url'] = videoDownUrl;
|
message_data['data']['url'] = videoDownUrl;
|
||||||
message_data['data']['file_id'] = videoElement.fileUuid;
|
message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId);
|
||||||
message_data['data']['file_size'] = videoElement.fileSize;
|
message_data['data']['file_size'] = videoElement.fileSize;
|
||||||
|
|
||||||
await NTQQFileApi.addFileCache({
|
await NTQQFileApi.addFileCache({
|
||||||
@@ -258,19 +281,9 @@ export class OB11Constructor {
|
|||||||
message_data['type'] = OB11MessageDataType.voice;
|
message_data['type'] = OB11MessageDataType.voice;
|
||||||
message_data['data']['file'] = element.pttElement.fileName;
|
message_data['data']['file'] = element.pttElement.fileName;
|
||||||
message_data['data']['path'] = element.pttElement.filePath;
|
message_data['data']['path'] = element.pttElement.filePath;
|
||||||
message_data['data']['file_id'] = element.pttElement.fileUuid;
|
//message_data['data']['file_id'] = element.pttElement.fileUuid;
|
||||||
|
message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId);
|
||||||
message_data['data']['file_size'] = element.pttElement.fileSize;
|
message_data['data']['file_size'] = element.pttElement.fileSize;
|
||||||
// dbUtil.addFileCache({
|
|
||||||
// name: element.pttElement.fileName,
|
|
||||||
// path: element.pttElement.filePath,
|
|
||||||
// size: parseInt(element.pttElement.fileSize) || 0,
|
|
||||||
// url: '',
|
|
||||||
// uuid: element.pttElement.fileUuid || '',
|
|
||||||
// msgId: msg.msgId,
|
|
||||||
// element: element.pttElement,
|
|
||||||
// elementType: ElementType.PTT,
|
|
||||||
// elementId: element.elementId
|
|
||||||
// }).then();
|
|
||||||
await NTQQFileApi.addFileCache({
|
await NTQQFileApi.addFileCache({
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
chatType: msg.chatType,
|
chatType: msg.chatType,
|
||||||
@@ -327,8 +340,29 @@ export class OB11Constructor {
|
|||||||
else if (element.multiForwardMsgElement) {
|
else if (element.multiForwardMsgElement) {
|
||||||
message_data['type'] = OB11MessageDataType.forward;
|
message_data['type'] = OB11MessageDataType.forward;
|
||||||
message_data['data']['id'] = msg.msgId;
|
message_data['data']['id'] = msg.msgId;
|
||||||
|
const ParentMsgPeer = msg.parentMsgPeer ?? { chatType: msg.chatType, guildId: '', peerUid: msg.peerUid };
|
||||||
|
//判断是否在合并消息内
|
||||||
|
msg.parentMsgIdList = msg.parentMsgIdList ?? [];
|
||||||
|
//首次列表不存在则开始创建
|
||||||
|
msg.parentMsgIdList.push(msg.msgId);
|
||||||
|
//let parentMsgId = msg.parentMsgIdList[msg.parentMsgIdList.length - 2 < 0 ? 0 : msg.parentMsgIdList.length - 2];
|
||||||
|
//加入自身MsgId
|
||||||
|
const MultiMsgs = (await NTQQMsgApi.getMultiMsg(ParentMsgPeer, msg.parentMsgIdList[0], msg.msgId))?.msgList;
|
||||||
|
//拉取下级消息
|
||||||
|
if (!MultiMsgs) continue;
|
||||||
|
//拉取失败则跳过
|
||||||
|
message_data['data']['content'] = [];
|
||||||
|
for (const MultiMsg of MultiMsgs) {
|
||||||
|
//对每条拉取的消息传递ParentMsgPeer修正Peer
|
||||||
|
MultiMsg.parentMsgPeer = ParentMsgPeer;
|
||||||
|
MultiMsg.parentMsgIdList = msg.parentMsgIdList;
|
||||||
|
MultiMsg.id = MessageUnique.createMsg(ParentMsgPeer, MultiMsg.msgId);//该ID仅用查看 无法调用
|
||||||
|
const msgList = await OB11Constructor.message(MultiMsg);
|
||||||
|
message_data['data']['content'].push(msgList);
|
||||||
|
//console.log("合并消息", msgList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (message_data.type !== 'unknown' && message_data.data) {
|
if ((message_data.type as string) !== 'unknown' && message_data.data) {
|
||||||
const cqCode = encodeCQCode(message_data);
|
const cqCode = encodeCQCode(message_data);
|
||||||
|
|
||||||
if (messagePostFormat === 'string') {
|
if (messagePostFormat === 'string') {
|
||||||
@@ -350,6 +384,7 @@ export class OB11Constructor {
|
|||||||
if (element.grayTipElement) {
|
if (element.grayTipElement) {
|
||||||
if (element.grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) {
|
if (element.grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) {
|
||||||
const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr);
|
const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr);
|
||||||
|
|
||||||
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
||||||
//判断业务类型
|
//判断业务类型
|
||||||
//Poke事件
|
//Poke事件
|
||||||
@@ -358,11 +393,17 @@ export class OB11Constructor {
|
|||||||
pokedetail = pokedetail.filter(item => item.uid);
|
pokedetail = pokedetail.filter(item => item.uid);
|
||||||
//console.log("[NapCat] 群拍一拍 群:", pokedetail, parseInt(msg.peerUid), " ", await NTQQUserApi.getUinByUid(pokedetail[0].uid), "拍了拍", await NTQQUserApi.getUinByUid(pokedetail[1].uid));
|
//console.log("[NapCat] 群拍一拍 群:", pokedetail, parseInt(msg.peerUid), " ", await NTQQUserApi.getUinByUid(pokedetail[0].uid), "拍了拍", await NTQQUserApi.getUinByUid(pokedetail[1].uid));
|
||||||
if (pokedetail.length == 2) {
|
if (pokedetail.length == 2) {
|
||||||
return new OB11FriendPokeEvent(parseInt((await NTQQUserApi.getUinByUid(pokedetail[0].uid))!), parseInt((await NTQQUserApi.getUinByUid(pokedetail[1].uid))!));
|
return new OB11FriendPokeEvent(parseInt((await NTQQUserApi.getUinByUid(pokedetail[0].uid))!), parseInt((await NTQQUserApi.getUinByUid(pokedetail[1].uid))!), pokedetail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE
|
//下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE
|
||||||
}
|
}
|
||||||
|
if (element.grayTipElement.subElementType == GrayTipElementSubType.INVITE_NEW_MEMBER) {
|
||||||
|
//好友添加成功事件
|
||||||
|
if (element.grayTipElement.xmlElement.templId === '10229' && msg.peerUin !== '') {
|
||||||
|
return new OB11FriendAddNoticeEvent(parseInt(msg.peerUin));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,6 +492,7 @@ export class OB11Constructor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (grayTipElement) {
|
if (grayTipElement) {
|
||||||
|
//console.log('收到群提示消息', grayTipElement);
|
||||||
if (grayTipElement.xmlElement?.templId === '10382') {
|
if (grayTipElement.xmlElement?.templId === '10382') {
|
||||||
const emojiLikeData = new fastXmlParser.XMLParser({
|
const emojiLikeData = new fastXmlParser.XMLParser({
|
||||||
ignoreAttributes: false,
|
ignoreAttributes: false,
|
||||||
@@ -547,7 +589,24 @@ export class OB11Constructor {
|
|||||||
nickname: selfInfo.nick,
|
nickname: selfInfo.nick,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
static friendsV2(friends: FriendV2[]): OB11User[] {
|
||||||
|
const data: OB11User[] = [];
|
||||||
|
friends.forEach(friend => {
|
||||||
|
const sexValue = this.sex(friend.baseInfo.sex!);
|
||||||
|
data.push({
|
||||||
|
...friend.baseInfo,
|
||||||
|
...friend.coreInfo,
|
||||||
|
user_id: parseInt(friend.coreInfo.uin),
|
||||||
|
nickname: friend.coreInfo.nick,
|
||||||
|
remark: friend.coreInfo.nick,
|
||||||
|
sex: sexValue,
|
||||||
|
level: 0,
|
||||||
|
categroyName: friend.categroyName,
|
||||||
|
categoryId: friend.categoryId
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
static friends(friends: Friend[]): OB11User[] {
|
static friends(friends: Friend[]): OB11User[] {
|
||||||
const data: OB11User[] = [];
|
const data: OB11User[] = [];
|
||||||
friends.forEach(friend => {
|
friends.forEach(friend => {
|
||||||
|
@@ -66,16 +66,16 @@ export function encodeCQCode(data: OB11MessageData) {
|
|||||||
|
|
||||||
let result = '[CQ:' + data.type;
|
let result = '[CQ:' + data.type;
|
||||||
for (const name in data.data) {
|
for (const name in data.data) {
|
||||||
let value = data.data[name];
|
const value = data.data[name];
|
||||||
try {
|
if (value === undefined) {
|
||||||
// Check if the value can be converted to a string
|
|
||||||
value = value.toString();
|
|
||||||
} catch (error) {
|
|
||||||
// If it can't be converted, skip this name-value pair
|
|
||||||
// console.warn(`Skipping problematic name-value pair. Name: ${name}, Value: ${value}`);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result += `,${name}=${CQCodeEscape(value)}`;
|
try {
|
||||||
|
const text = value.toString();
|
||||||
|
result += `,${name}=${CQCodeEscape(text)}`;
|
||||||
|
} catch (error) {
|
||||||
|
// If it can't be converted, skip this name-value pair
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result += ']';
|
result += ']';
|
||||||
return result;
|
return result;
|
||||||
|
11
src/onebot11/event/notice/OB11FriendAddNoticeEvent.ts
Normal file
11
src/onebot11/event/notice/OB11FriendAddNoticeEvent.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent';
|
||||||
|
|
||||||
|
export class OB11FriendAddNoticeEvent extends OB11BaseNoticeEvent {
|
||||||
|
notice_type = 'friend_add';
|
||||||
|
user_id: number;
|
||||||
|
|
||||||
|
public constructor(user_Id: number) {
|
||||||
|
super();
|
||||||
|
this.user_id = user_Id;
|
||||||
|
}
|
||||||
|
}
|
@@ -2,5 +2,5 @@ import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent';
|
|||||||
|
|
||||||
export class OB11GroupAdminNoticeEvent extends OB11GroupNoticeEvent {
|
export class OB11GroupAdminNoticeEvent extends OB11GroupNoticeEvent {
|
||||||
notice_type = 'group_admin';
|
notice_type = 'group_admin';
|
||||||
sub_type: 'set' | 'unset'; // "set" | "unset"
|
sub_type: 'set' | 'unset' = 'set'; // "set" | "unset"
|
||||||
}
|
}
|
16
src/onebot11/event/notice/OB11InputStatusEvent.ts
Normal file
16
src/onebot11/event/notice/OB11InputStatusEvent.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent';
|
||||||
|
//输入状态事件 初步完成 Mlikio wa Todo 需要做一些过滤
|
||||||
|
export class OB11InputStatusEvent extends OB11BaseNoticeEvent {
|
||||||
|
notice_type = 'notify';
|
||||||
|
sub_type = 'input_status';
|
||||||
|
status_text = '对方正在输入...';
|
||||||
|
event_type = 1;
|
||||||
|
user_id = 0;
|
||||||
|
constructor(user_id: number, eventType: number, status_text: string) {
|
||||||
|
super();
|
||||||
|
this.user_id = user_id;
|
||||||
|
this.event_type = eventType;
|
||||||
|
this.status_text = status_text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -8,7 +8,6 @@ export interface MsgEmojiLike {
|
|||||||
export class OB11GroupMsgEmojiLikeEvent extends OB11GroupNoticeEvent {
|
export class OB11GroupMsgEmojiLikeEvent extends OB11GroupNoticeEvent {
|
||||||
notice_type = 'group_msg_emoji_like';
|
notice_type = 'group_msg_emoji_like';
|
||||||
message_id: number;
|
message_id: number;
|
||||||
sub_type: 'ban' | 'lift_ban';
|
|
||||||
likes: MsgEmojiLike[];
|
likes: MsgEmojiLike[];
|
||||||
|
|
||||||
constructor(groupId: number, userId: number, messageId: number, likes: MsgEmojiLike[]) {
|
constructor(groupId: number, userId: number, messageId: number, likes: MsgEmojiLike[]) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user