mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
166 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8353533d60 | ||
![]() |
c06df27424 | ||
![]() |
ad82919ddf | ||
![]() |
44dbba17e1 | ||
![]() |
5ba110e1da | ||
![]() |
b6e392fdb2 | ||
![]() |
2280e83aa2 | ||
![]() |
f49b94edb9 | ||
![]() |
2428a12221 | ||
![]() |
9c353f3760 | ||
![]() |
5b86d25d7f | ||
![]() |
2b168e8bbc | ||
![]() |
537db32847 | ||
![]() |
498b7f9f2b | ||
![]() |
9935568597 | ||
![]() |
467003af8c | ||
![]() |
4c9edcc47b | ||
![]() |
24bf9cf121 | ||
![]() |
e06f6f39a9 | ||
![]() |
98ee0c307b | ||
![]() |
5e53ea0bc3 | ||
![]() |
847d88ea77 | ||
![]() |
d5046cc2b3 | ||
![]() |
3ad64b7cbb | ||
![]() |
0dbfe8ca55 | ||
![]() |
91b794d66d | ||
![]() |
0d65e1e314 | ||
![]() |
2d8f58c6d8 | ||
![]() |
65888fa816 | ||
![]() |
857e882c6e | ||
![]() |
add2931834 | ||
![]() |
cdda5f45ee | ||
![]() |
5f73d6a913 | ||
![]() |
0637882fbc | ||
![]() |
3f785bab20 | ||
![]() |
a4ca89bdd6 | ||
![]() |
1a64e796bd | ||
![]() |
a8b85a34f7 | ||
![]() |
e7bec7d6b0 | ||
![]() |
a582026037 | ||
![]() |
1a67a001c5 | ||
![]() |
406deac592 | ||
![]() |
e719ae0676 | ||
![]() |
d8b7726440 | ||
![]() |
49f642e712 | ||
![]() |
70117016ce | ||
![]() |
a4738f6281 | ||
![]() |
b1fc72d696 | ||
![]() |
457c2c2b50 | ||
![]() |
48848d7d1a | ||
![]() |
55b07ca3ab | ||
![]() |
a1d4882e18 | ||
![]() |
3843795d8f | ||
![]() |
f2bf8d42da | ||
![]() |
a3b244e114 | ||
![]() |
3093bdbc68 | ||
![]() |
9ab0799283 | ||
![]() |
236bec11ed | ||
![]() |
de48b0f940 | ||
![]() |
4885d4db86 | ||
![]() |
0c7bbda936 | ||
![]() |
fa07c2c1fb | ||
![]() |
5d17a191f6 | ||
![]() |
67fb74d3c2 | ||
![]() |
dc04cfc1b3 | ||
![]() |
d61d481965 | ||
![]() |
6b346ee1de | ||
![]() |
d0f248aaf9 | ||
![]() |
85c9227515 | ||
![]() |
73b6d3be84 | ||
![]() |
1ff6ce2343 | ||
![]() |
c145935d46 | ||
![]() |
e9ede6924e | ||
![]() |
515a21761d | ||
![]() |
8d6397028b | ||
![]() |
eb4828d81f | ||
![]() |
7e74578312 | ||
![]() |
640e3516d4 | ||
![]() |
bd295a4632 | ||
![]() |
166c30fe2c | ||
![]() |
66c1bab629 | ||
![]() |
66656304f9 | ||
![]() |
07f66e379d | ||
![]() |
7ae8fd60c4 | ||
![]() |
7275066994 | ||
![]() |
385adec186 | ||
![]() |
96b5bec5ab | ||
![]() |
6a9ec4e5f0 | ||
![]() |
d9851493df | ||
![]() |
efdb520414 | ||
![]() |
5548644aeb | ||
![]() |
e3fcd91b2d | ||
![]() |
2cae30ba88 | ||
![]() |
58cd38c4a8 | ||
![]() |
3300304feb | ||
![]() |
f0e376d06b | ||
![]() |
16f7bb48f2 | ||
![]() |
7f383dd29b | ||
![]() |
3dc529edf4 | ||
![]() |
45dedb4872 | ||
![]() |
afcdd01c0d | ||
![]() |
1164877e9a | ||
![]() |
fe92a449ba | ||
![]() |
401b0e2bd0 | ||
![]() |
cf9c71fcc1 | ||
![]() |
15a2400069 | ||
![]() |
d68a39b49e | ||
![]() |
066ca22e24 | ||
![]() |
0418b926fe | ||
![]() |
be40bbdf40 | ||
![]() |
df4f42e79e | ||
![]() |
5f80058f70 | ||
![]() |
0cbe59052d | ||
![]() |
af28a26e37 | ||
![]() |
70c596df93 | ||
![]() |
748b51428c | ||
![]() |
8ad746397c | ||
![]() |
45baed2f9a | ||
![]() |
74185f2d33 | ||
![]() |
90a91e4105 | ||
![]() |
11aa3a0315 | ||
![]() |
0c2e39214f | ||
![]() |
d89620d7a6 | ||
![]() |
edf80775b7 | ||
![]() |
46e56ac726 | ||
![]() |
40b2f6bfd6 | ||
![]() |
911e4921e2 | ||
![]() |
1db9bb419d | ||
![]() |
c6241a94e3 | ||
![]() |
1cbf75ca36 | ||
![]() |
8f85c897c8 | ||
![]() |
29c31b7aba | ||
![]() |
402919d6f2 | ||
![]() |
82608dd5ff | ||
![]() |
f312368df2 | ||
![]() |
374fc64427 | ||
![]() |
95bd74bb0d | ||
![]() |
a9f5069649 | ||
![]() |
957f7ffd8d | ||
![]() |
336dd3ce10 | ||
![]() |
47a7295477 | ||
![]() |
341a0e1c2a | ||
![]() |
c4f73d0eb8 | ||
![]() |
bd9258bae4 | ||
![]() |
e3b3260aa0 | ||
![]() |
676766c99e | ||
![]() |
1025a07593 | ||
![]() |
00c3fcd033 | ||
![]() |
b8457d4aff | ||
![]() |
a2ecf10d19 | ||
![]() |
1e63a2a7e7 | ||
![]() |
964014fc5c | ||
![]() |
fc2bb6d8c3 | ||
![]() |
1b10252d76 | ||
![]() |
ad8af12a10 | ||
![]() |
b040c9b118 | ||
![]() |
f6da7da90b | ||
![]() |
a745185408 | ||
![]() |
d3336f9027 | ||
![]() |
daf42c8203 | ||
![]() |
0a18bae3b5 | ||
![]() |
919705966c | ||
![]() |
2c54aee63e | ||
![]() |
3f80bdf2a3 | ||
![]() |
1c429b8dd3 | ||
![]() |
5669e2b0b7 |
Binary file not shown.
Binary file not shown.
@@ -5,11 +5,11 @@ if %errorLevel% == 0 (
|
|||||||
echo Administrator mode detected.
|
echo Administrator mode detected.
|
||||||
) else (
|
) else (
|
||||||
echo Please run this script in administrator mode.
|
echo Please run this script in administrator mode.
|
||||||
powershell -Command "Start-Process 'cmd.exe' -ArgumentList '/c cd /d \"%cd%\" && \"%~f0\"' -Verb runAs"
|
powershell -Command "Start-Process 'cmd.exe' -ArgumentList '/c cd /d \"%cd%\" && \"%~f0\" %1' -Verb runAs"
|
||||||
exit
|
exit
|
||||||
)
|
)
|
||||||
|
|
||||||
set NAPCAT_PATCH_PATH=%cd%\patchNapCat.js
|
set NAPCAT_PATCH_PACKAGE=%cd%\qqnt.json
|
||||||
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
|
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
|
||||||
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
|
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
|
||||||
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
|
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
|
||||||
@@ -35,6 +35,6 @@ if not exist "%QQpath%" (
|
|||||||
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
||||||
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
|
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
|
||||||
|
|
||||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%"
|
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %1
|
||||||
|
|
||||||
REM "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" 123456
|
REM "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" 123456
|
@@ -5,11 +5,11 @@ if %errorLevel% == 0 (
|
|||||||
echo Administrator mode detected.
|
echo Administrator mode detected.
|
||||||
) else (
|
) else (
|
||||||
echo Please run this script in administrator mode.
|
echo Please run this script in administrator mode.
|
||||||
powershell -Command "Start-Process 'wt.exe' -ArgumentList 'cmd /c cd /d \"%cd%\" && \"%~f0\"' -Verb runAs"
|
powershell -Command "Start-Process 'wt.exe' -ArgumentList 'cmd /c cd /d \"%cd%\" && \"%~f0\" %1' -Verb runAs"
|
||||||
exit
|
exit
|
||||||
)
|
)
|
||||||
|
|
||||||
set NAPCAT_PATCH_PATH=%cd%\patchNapCat.js
|
set NAPCAT_PATCH_PACKAGE=%cd%\qqnt.json
|
||||||
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
|
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
|
||||||
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
|
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
|
||||||
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
|
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
|
||||||
@@ -34,8 +34,6 @@ if not exist "%QQpath%" (
|
|||||||
)
|
)
|
||||||
|
|
||||||
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
||||||
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
|
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > "%NAPCAT_LOAD_PATH%"
|
||||||
|
|
||||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%"
|
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %1
|
||||||
|
|
||||||
REM "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" 123456
|
|
@@ -1 +0,0 @@
|
|||||||
require('./launcher.node').load('external_index', module);
|
|
23
launcher/qqnt.json
Normal file
23
launcher/qqnt.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "qq-chat",
|
||||||
|
"version": "9.9.15-28131",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"description": "QQ",
|
||||||
|
"productName": "QQ",
|
||||||
|
"author": {
|
||||||
|
"name": "Tencent",
|
||||||
|
"email": "QQ-Team@tencent.com"
|
||||||
|
},
|
||||||
|
"homepage": "https://im.qq.com",
|
||||||
|
"sideEffects": true,
|
||||||
|
"bin": {
|
||||||
|
"qd": "externals/devtools/cli/index.js"
|
||||||
|
},
|
||||||
|
"main": "./loadNapCat.js",
|
||||||
|
"buildVersion": "28131",
|
||||||
|
"isPureShell": true,
|
||||||
|
"isByteCodeShell": true,
|
||||||
|
"platform": "win32",
|
||||||
|
"eleArch": "x64"
|
||||||
|
}
|
4
launcher/quickLoginExample.bat
Normal file
4
launcher/quickLoginExample.bat
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
@echo off
|
||||||
|
REM ./launcher.bat 123456
|
||||||
|
REM ./launcher-win10.bat 123456
|
||||||
|
REM 带有REM的为注释 删掉你需要的系统的那行REM这三个单词 修改QQ本脚本启动即可
|
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "2.4.0",
|
"version": "2.6.13",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
16
package.json
16
package.json
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.4.0",
|
"version": "2.6.13",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:framework": "vite build --mode framework",
|
"build:framework": "vite build --mode framework",
|
||||||
"build:shell": "vite build --mode shell",
|
"build:shell": "vite build --mode shell",
|
||||||
@@ -11,9 +11,6 @@
|
|||||||
"depend": "cd dist && npm install --omit=dev"
|
"depend": "cd dist && npm install --omit=dev"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.7",
|
|
||||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
||||||
"@babel/plugin-proposal-decorators": "^7.24.7",
|
|
||||||
"@babel/preset-typescript": "^7.24.7",
|
"@babel/preset-typescript": "^7.24.7",
|
||||||
"@log4js-node/log4js-api": "^1.0.2",
|
"@log4js-node/log4js-api": "^1.0.2",
|
||||||
"@protobuf-ts/plugin": "^2.9.4",
|
"@protobuf-ts/plugin": "^2.9.4",
|
||||||
@@ -21,9 +18,7 @@
|
|||||||
"@rollup/plugin-typescript": "^11.1.6",
|
"@rollup/plugin-typescript": "^11.1.6",
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/figlet": "^1.5.8",
|
|
||||||
"@types/fluent-ffmpeg": "^2.1.24",
|
"@types/fluent-ffmpeg": "^2.1.24",
|
||||||
"@types/jest": "^29.5.12",
|
|
||||||
"@types/node": "^22.0.1",
|
"@types/node": "^22.0.1",
|
||||||
"@types/qrcode-terminal": "^0.12.2",
|
"@types/qrcode-terminal": "^0.12.2",
|
||||||
"@types/ws": "^8.5.12",
|
"@types/ws": "^8.5.12",
|
||||||
@@ -32,14 +27,8 @@
|
|||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.1",
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"i": "^0.3.7",
|
|
||||||
"javascript-obfuscator": "^4.1.0",
|
|
||||||
"rollup": "^4.13.2",
|
|
||||||
"rollup-plugin-dts": "^6.1.0",
|
|
||||||
"rollup-plugin-obfuscator": "^1.1.0",
|
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"vite": "^5.2.6",
|
"vite": "^5.2.6",
|
||||||
"vite-plugin-babel": "^1.2.0",
|
|
||||||
"vite-plugin-cp": "^4.0.8",
|
"vite-plugin-cp": "^4.0.8",
|
||||||
"vite-plugin-dts": "^3.8.2",
|
"vite-plugin-dts": "^3.8.2",
|
||||||
"vite-tsconfig-paths": "^4.3.2"
|
"vite-tsconfig-paths": "^4.3.2"
|
||||||
@@ -57,9 +46,10 @@
|
|||||||
"image-size": "^1.1.1",
|
"image-size": "^1.1.1",
|
||||||
"json-schema-to-ts": "^3.1.0",
|
"json-schema-to-ts": "^3.1.0",
|
||||||
"log4js": "^6.9.1",
|
"log4js": "^6.9.1",
|
||||||
|
"protobufjs": "~7.4.0",
|
||||||
"qrcode-terminal": "^0.12.0",
|
"qrcode-terminal": "^0.12.0",
|
||||||
"silk-wasm": "^3.6.1",
|
"silk-wasm": "^3.6.1",
|
||||||
"strtok3": "8.0.1",
|
"strtok3": "8.0.1",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,45 +0,0 @@
|
|||||||
# Dont Use This Script
|
|
||||||
# 2024.7.3
|
|
||||||
function Get-QQpath {
|
|
||||||
try {
|
|
||||||
$key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ"
|
|
||||||
$uninstallString = $key.UninstallString
|
|
||||||
return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe"
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
throw "get QQ path error: $_"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function Select-QQPath {
|
|
||||||
Add-Type -AssemblyName System.Windows.Forms
|
|
||||||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
|
||||||
|
|
||||||
$dialogTitle = "Select QQ.exe"
|
|
||||||
|
|
||||||
$filePicker = New-Object System.Windows.Forms.OpenFileDialog
|
|
||||||
$filePicker.Title = $dialogTitle
|
|
||||||
$filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*"
|
|
||||||
$filePicker.FilterIndex = 1
|
|
||||||
$null = $filePicker.ShowDialog()
|
|
||||||
if (-not ($filePicker.FileName)) {
|
|
||||||
throw "User did not select an .exe file."
|
|
||||||
}
|
|
||||||
return $filePicker.FileName
|
|
||||||
}
|
|
||||||
|
|
||||||
$params = $args -join " "
|
|
||||||
Try {
|
|
||||||
$QQpath = Get-QQpath
|
|
||||||
}
|
|
||||||
Catch {
|
|
||||||
$QQpath = Select-QQPath
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(Test-Path $QQpath)) {
|
|
||||||
throw "provided QQ path is invalid: $QQpath"
|
|
||||||
}
|
|
||||||
|
|
||||||
$Bootfile = Join-Path $PSScriptRoot "napcat.mjs"
|
|
||||||
$env:ELECTRON_RUN_AS_NODE = 1
|
|
||||||
$commandInfo = Get-Command $QQpath -ErrorAction Stop
|
|
||||||
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& '$($commandInfo.Path)' --enable-logging }"
|
|
@@ -1,90 +0,0 @@
|
|||||||
@echo off
|
|
||||||
REM 检查当前会话是否具有管理员权限
|
|
||||||
openfiles >nul 2>&1
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
REM 如果不是管理员,则重新启动脚本以管理员模式运行
|
|
||||||
echo 请求管理员权限...
|
|
||||||
powershell -Command "Start-Process cmd -ArgumentList '/c %~f0 %*' -Verb RunAs"
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 设置当前工作目录
|
|
||||||
cd /d %~dp0
|
|
||||||
|
|
||||||
REM 获取当前目录路径
|
|
||||||
set currentPath=%cd%
|
|
||||||
set currentPath=%currentPath:\=/%
|
|
||||||
|
|
||||||
REM 生成JavaScript代码
|
|
||||||
set "jsCode=(async () =^>await import('file:///%currentPath%/napcat.mjs'))();"
|
|
||||||
|
|
||||||
REM 将JavaScript代码保存到文件中
|
|
||||||
echo %jsCode% > loadScript.js
|
|
||||||
echo JavaScript code has been generated and saved to loadScript.js
|
|
||||||
|
|
||||||
REM 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址
|
|
||||||
set NAPCAT_PATH=%cd%\loadScript.js
|
|
||||||
|
|
||||||
REM 获取QQ路径
|
|
||||||
|
|
||||||
|
|
||||||
:loop_read
|
|
||||||
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
|
|
||||||
set RetString=%%b
|
|
||||||
goto :napcat_boot
|
|
||||||
)
|
|
||||||
|
|
||||||
:napcat_boot
|
|
||||||
for %%a in (%RetString%) do (
|
|
||||||
set "pathWithoutUninstall=%%~dpa"
|
|
||||||
)
|
|
||||||
|
|
||||||
SET QQPath=%pathWithoutUninstall%QQ.exe
|
|
||||||
|
|
||||||
REM 拿不到QQ路径则退出
|
|
||||||
if not exist "%QQpath%" (
|
|
||||||
echo provided QQ path is invalid: %QQpath%
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 收集dbghelp.dll路径和HASH信息
|
|
||||||
set QQdir=%~dp0
|
|
||||||
set oldDllPath=%QQdir%dbghelp.dll
|
|
||||||
set newDllPath=%currentPath%\dbghelp.dll
|
|
||||||
|
|
||||||
for /f "tokens=*" %%A in ('certutil -hashfile "%oldDllPath%" MD5') do (
|
|
||||||
if not defined oldDllHash set oldDllHash=%%A
|
|
||||||
)
|
|
||||||
for /f "tokens=*" %%A in ('certutil -hashfile "%newDllPath%" MD5') do (
|
|
||||||
if not defined newDllHash set newDllHash=%%A
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 如果文件一致则跳过
|
|
||||||
if "%oldDllHash%" neq "%newDllHash%" (
|
|
||||||
tasklist /fi "imagename eq QQ.exe" 2>nul | find /i "QQ.exe" >nul
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
REM 文件占用则退出
|
|
||||||
echo dbghelp.dll is in use, cannot continue.
|
|
||||||
) else (
|
|
||||||
REM 文件未占用则尝试覆盖
|
|
||||||
copy /y "%newDllPath%" "%oldDllPath%"
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo Failed to copy dbghelp.dll
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
) else (
|
|
||||||
echo dbghelp.dll has been copied to %QQdir%
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 带参数启动QQ
|
|
||||||
REM 判断wt是否存在,存在则通过wt启动,不存在则通过cmd启动
|
|
||||||
REM %QQPath% --enable-logging %*
|
|
||||||
where wt >nul 2>nul
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
wt "cmd" /c "%QQPath%" --enable-logging %*
|
|
||||||
) else (
|
|
||||||
"%QQPath%" --enable-logging %*
|
|
||||||
)
|
|
@@ -1,123 +0,0 @@
|
|||||||
# 检查当前会话是否具有管理员权限
|
|
||||||
function Test-Administrator {
|
|
||||||
$user = [Security.Principal.WindowsIdentity]::GetCurrent()
|
|
||||||
(New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-not (Test-Administrator)) {
|
|
||||||
# 如果不是管理员,则重新启动脚本以管理员模式运行
|
|
||||||
$scriptPath = $myInvocation.MyCommand.Path
|
|
||||||
if (-not $scriptPath) {
|
|
||||||
$scriptPath = $PSCommandPath
|
|
||||||
}
|
|
||||||
$newProcess = New-Object System.Diagnostics.ProcessStartInfo "powershell";
|
|
||||||
$newProcess.Arguments = "-File `"$scriptPath`" $args"
|
|
||||||
$newProcess.Verb = "runas";
|
|
||||||
[System.Diagnostics.Process]::Start($newProcess);
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-QQpath {
|
|
||||||
try {
|
|
||||||
$key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ"
|
|
||||||
$uninstallString = $key.UninstallString
|
|
||||||
return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe"
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
throw "get QQ path error: $_"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function Select-QQPath {
|
|
||||||
Add-Type -AssemblyName System.Windows.Forms
|
|
||||||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
|
||||||
|
|
||||||
$dialogTitle = "Select QQ.exe"
|
|
||||||
|
|
||||||
$filePicker = New-Object System.Windows.Forms.OpenFileDialog
|
|
||||||
$filePicker.Title = $dialogTitle
|
|
||||||
$filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*"
|
|
||||||
$filePicker.FilterIndex = 1
|
|
||||||
$null = $filePicker.ShowDialog()
|
|
||||||
if (-not ($filePicker.FileName)) {
|
|
||||||
throw "User did not select an .exe file."
|
|
||||||
}
|
|
||||||
return $filePicker.FileName
|
|
||||||
}
|
|
||||||
|
|
||||||
# 设置当前工作目录
|
|
||||||
$scriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
Set-Location $scriptDirectory
|
|
||||||
|
|
||||||
# 获取当前目录路径
|
|
||||||
$currentPath = Get-Location
|
|
||||||
|
|
||||||
# 替换\为/
|
|
||||||
$currentPath = $currentPath -replace '\\', '/'
|
|
||||||
|
|
||||||
# 生成JavaScript代码
|
|
||||||
$jsCode = @"
|
|
||||||
(async () => {
|
|
||||||
await import('file:///$currentPath/napcat.mjs');
|
|
||||||
})();
|
|
||||||
"@
|
|
||||||
|
|
||||||
# 将JavaScript代码保存到文件中
|
|
||||||
$jsFilePath = Join-Path $currentPath "loadScript.js"
|
|
||||||
$jsCode | Out-File -FilePath $jsFilePath -Encoding UTF8
|
|
||||||
|
|
||||||
Write-Output "JavaScript code has been generated and saved to $jsFilePath"
|
|
||||||
# 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址
|
|
||||||
$env:NAPCAT_PATH = $jsFilePath
|
|
||||||
|
|
||||||
$params = $args -join " "
|
|
||||||
Try {
|
|
||||||
$QQpath = Get-QQpath
|
|
||||||
}
|
|
||||||
Catch {
|
|
||||||
$QQpath = Select-QQPath
|
|
||||||
}
|
|
||||||
# 拿不到QQ路径则退出
|
|
||||||
if (!(Test-Path $QQpath)) {
|
|
||||||
Write-Output "provided QQ path is invalid: $QQpath"
|
|
||||||
Read-Host "Press any key to continue..."
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
$commandInfo = Get-Command $QQpath -ErrorAction Stop
|
|
||||||
|
|
||||||
# 收集dbghelp.dll路径和HASH信息
|
|
||||||
$QQpath = Split-Path $QQpath
|
|
||||||
$oldDllPath = Join-Path $QQpath "dbghelp.dll"
|
|
||||||
$oldDllHash = Get-FileHash $oldDllPath -Algorithm MD5
|
|
||||||
$newDllPath = Join-Path $currentPath "dbghelp.dll"
|
|
||||||
$newDllHash = Get-FileHash $newDllPath -Algorithm MD5
|
|
||||||
# 如果文件一致则跳过
|
|
||||||
if ($oldDllHash.Hash -ne $newDllHash.Hash) {
|
|
||||||
$processes = Get-Process -Name QQ -ErrorAction SilentlyContinue
|
|
||||||
if ($processes) {
|
|
||||||
# 文件占用则退出
|
|
||||||
Write-Output "dbghelp.dll is in use by the following processes:"
|
|
||||||
$processes | ForEach-Object { Write-Output "$($_.Id) $($_.Name) $($_.Path)" }
|
|
||||||
Write-Output "dbghelp.dll is in use, cannot continue."
|
|
||||||
Read-Host "Press any key to continue..."
|
|
||||||
exit
|
|
||||||
} else {
|
|
||||||
# 文件未占用则尝试覆盖
|
|
||||||
try {
|
|
||||||
Copy-Item -Path "$newDllPath" -Destination "$oldDllPath" -Force
|
|
||||||
Write-Output "dbghelp.dll has been copied to $QQpath"
|
|
||||||
} catch {
|
|
||||||
Write-Output "Failed to copy dbghelp.dll: $_"
|
|
||||||
Read-Host "Press any key to continue..."
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# 带参数启动QQ
|
|
||||||
try {
|
|
||||||
Start-Process powershell -ArgumentList '-noexit', '-noprofile', "-command &{& chcp 65001;& '$($commandInfo.Path)' --enable-logging $params}" -NoNewWindow -ErrorAction Stop
|
|
||||||
} catch {
|
|
||||||
Write-Output "Failed to start process as administrator: $_"
|
|
||||||
Read-Host "Press any key to continue..."
|
|
||||||
}
|
|
@@ -1,93 +0,0 @@
|
|||||||
@echo off
|
|
||||||
REM 检查当前会话是否具有管理员权限
|
|
||||||
openfiles >nul 2>&1
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
REM 如果不是管理员,则重新启动脚本以管理员模式运行
|
|
||||||
echo 请求管理员权限...
|
|
||||||
where wt >nul 2>nul
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
powershell -Command "Start-Process cmd -ArgumentList ' /c %~f0 %*' -Verb RunAs"
|
|
||||||
) else (
|
|
||||||
powershell -Command "Start-Process wt -ArgumentList 'cmd /c %~f0 %*' -Verb RunAs"
|
|
||||||
)
|
|
||||||
|
|
||||||
REM wt "cmd" /c "%~f0 %*"
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 设置当前工作目录
|
|
||||||
cd /d %~dp0
|
|
||||||
|
|
||||||
REM 获取当前目录路径
|
|
||||||
set currentPath=%cd%
|
|
||||||
set currentPath=%currentPath:\=/%
|
|
||||||
|
|
||||||
REM 生成JavaScript代码
|
|
||||||
set "jsCode=(async () =^>await import('file:///%currentPath%/napcat.mjs'))();"
|
|
||||||
|
|
||||||
REM 将JavaScript代码保存到文件中
|
|
||||||
echo %jsCode% > loadScript.js
|
|
||||||
echo JavaScript code has been generated and saved to loadScript.js
|
|
||||||
|
|
||||||
REM 设置NAPCAT_PATH环境变量为 当前目录的loadScript.js地址
|
|
||||||
set NAPCAT_PATH=%cd%\loadScript.js
|
|
||||||
|
|
||||||
REM 获取QQ路径
|
|
||||||
|
|
||||||
|
|
||||||
:loop_read
|
|
||||||
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
|
|
||||||
set RetString=%%b
|
|
||||||
goto :napcat_boot
|
|
||||||
)
|
|
||||||
|
|
||||||
:napcat_boot
|
|
||||||
for %%a in (%RetString%) do (
|
|
||||||
set "pathWithoutUninstall=%%~dpa"
|
|
||||||
)
|
|
||||||
|
|
||||||
SET QQPath=%pathWithoutUninstall%QQ.exe
|
|
||||||
|
|
||||||
REM 拿不到QQ路径则退出
|
|
||||||
if not exist "%QQpath%" (
|
|
||||||
echo provided QQ path is invalid: %QQpath%
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 收集dbghelp.dll路径和HASH信息
|
|
||||||
set QQdir=%~dp0
|
|
||||||
set oldDllPath=%QQdir%dbghelp.dll
|
|
||||||
set newDllPath=%currentPath%\dbghelp.dll
|
|
||||||
|
|
||||||
for /f "tokens=*" %%A in ('certutil -hashfile "%oldDllPath%" MD5') do (
|
|
||||||
if not defined oldDllHash set oldDllHash=%%A
|
|
||||||
)
|
|
||||||
for /f "tokens=*" %%A in ('certutil -hashfile "%newDllPath%" MD5') do (
|
|
||||||
if not defined newDllHash set newDllHash=%%A
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 如果文件一致则跳过
|
|
||||||
if "%oldDllHash%" neq "%newDllHash%" (
|
|
||||||
tasklist /fi "imagename eq QQ.exe" 2>nul | find /i "QQ.exe" >nul
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
REM 文件占用则退出
|
|
||||||
echo dbghelp.dll is in use, cannot continue.
|
|
||||||
) else (
|
|
||||||
REM 文件未占用则尝试覆盖
|
|
||||||
copy /y "%newDllPath%" "%oldDllPath%"
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo Failed to copy dbghelp.dll
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
) else (
|
|
||||||
echo dbghelp.dll has been copied to %QQdir%
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 带参数启动QQ
|
|
||||||
REM 判断wt是否存在,存在则通过wt启动,不存在则通过cmd启动
|
|
||||||
REM %QQPath% --enable-logging %*
|
|
||||||
chcp 65001
|
|
||||||
"%QQPath%" --enable-logging %*
|
|
@@ -1,77 +0,0 @@
|
|||||||
@echo off
|
|
||||||
REM Check if the script is running as administrator
|
|
||||||
openfiles >nul 2>&1
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
REM If not, restart the script in administrator mode
|
|
||||||
echo Requesting administrator privileges...
|
|
||||||
powershell -Command "Start-Process cmd -ArgumentList '/c %~f0 %*' -Verb RunAs"
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
cd /d %~dp0
|
|
||||||
|
|
||||||
set currentPath=%cd%
|
|
||||||
set currentPath=%currentPath:\=/%
|
|
||||||
|
|
||||||
REM Generate JavaScript code
|
|
||||||
set "jsCode=(async () =^>await import('file:///%currentPath%/napcat.mjs'))();"
|
|
||||||
|
|
||||||
REM Save JavaScript code to a file
|
|
||||||
echo %jsCode% > loadScript.js
|
|
||||||
echo JavaScript code has been generated and saved to loadScript.js
|
|
||||||
|
|
||||||
REM Set NAPCAT_PATH environment variable to the address of loadScript.js in the current directory
|
|
||||||
set NAPCAT_PATH=%cd%\loadScript.js
|
|
||||||
|
|
||||||
REM Get QQ path and cache it
|
|
||||||
: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"
|
|
||||||
)
|
|
||||||
|
|
||||||
set "pathWithoutUninstall=%RetString:Uninstall.exe=%"
|
|
||||||
|
|
||||||
SET QQPath=%pathWithoutUninstall%QQ.exe
|
|
||||||
echo %QQPath%>qq_path_cache.txt
|
|
||||||
echo QQ path %QQPath% has been cached to qq_path_cache.txt
|
|
||||||
|
|
||||||
REM Exit if QQ path is invalid
|
|
||||||
if not exist "%QQpath%" (
|
|
||||||
echo provided QQ path is invalid: %QQpath%
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Collect dbghelp.dll path and HASH information
|
|
||||||
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 Compare the HASH of the old and new dbghelp.dll, and replace the old one if they are different
|
|
||||||
if "%oldDllHash%" neq "%newDllHash%" (
|
|
||||||
tasklist /fi "imagename eq QQ.exe" 2>nul | find /i "QQ.exe" >nul
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
REM If the file is in use, prompt the user to close QQ
|
|
||||||
echo dbghelp.dll is in use, please close QQ first.
|
|
||||||
) else (
|
|
||||||
copy /y "%newDllPath%" "%oldDllPath%"
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo Copy dbghelp.dll failed, please check and try again.
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
) else (
|
|
||||||
echo dbghelp.dll has been updated.
|
|
||||||
echo Please run BootWay05_run.bat to start QQ.
|
|
||||||
echo If you update QQ in the future, please run BootWay05_init.bat again.
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
@@ -1,10 +0,0 @@
|
|||||||
@echo off
|
|
||||||
set /p QQPath=<qq_path_cache.txt
|
|
||||||
echo QQ path %QQPath% has been read from qq_path_cache.txt
|
|
||||||
echo If failed to start QQ, please try running this script in administrator mode.
|
|
||||||
|
|
||||||
set NAPCAT_PATH=%cd%\loadScript.js
|
|
||||||
|
|
||||||
REM Launch QQ.exe with params provided
|
|
||||||
|
|
||||||
"%QQPath%" --enable-logging %*
|
|
@@ -1,13 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
chcp 65001
|
|
||||||
|
|
||||||
set /p QQPath=<qq_path_cache.txt
|
|
||||||
echo QQ path %QQPath% has been read from qq_path_cache.txt
|
|
||||||
echo If failed to start QQ, please try running this script in administrator mode.
|
|
||||||
|
|
||||||
set NAPCAT_PATH=%cd%\loadScript.js
|
|
||||||
|
|
||||||
REM Launch QQ.exe with params provided
|
|
||||||
|
|
||||||
"%QQPath%" --enable-logging %*
|
|
Binary file not shown.
@@ -1,66 +1,67 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import { encode, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
|
|
||||||
import fsPromise from 'fs/promises';
|
import fsPromise from 'fs/promises';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
import { spawn } from 'node:child_process';
|
import { spawn } from 'node:child_process';
|
||||||
|
import { encode, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
|
||||||
import { LogWrapper } from './log';
|
import { LogWrapper } from './log';
|
||||||
|
|
||||||
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) {
|
const ALLOW_SAMPLE_RATE = [8000, 12000, 16000, 24000, 32000, 44100, 48000];
|
||||||
async function guessDuration(pttPath: string) {
|
const EXIT_CODES = [0, 255];
|
||||||
const pttFileInfo = await fsPromise.stat(pttPath);
|
const FFMPEG_PATH = process.env.FFMPEG_PATH || 'ffmpeg';
|
||||||
let duration = pttFileInfo.size / 1024 / 3; // 3kb/s
|
|
||||||
duration = Math.floor(duration);
|
|
||||||
duration = Math.max(1, duration);
|
|
||||||
logger.log('通过文件大小估算语音的时长:', duration);
|
|
||||||
return duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
async function guessDuration(pttPath: string, logger: LogWrapper) {
|
||||||
|
const pttFileInfo = await fsPromise.stat(pttPath);
|
||||||
|
const duration = Math.max(1, Math.floor(pttFileInfo.size / 1024 / 3)); // 3kb/s
|
||||||
|
logger.log('通过文件大小估算语音的时长:', duration);
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function convert(filePath: string, pcmPath: string, logger: LogWrapper): Promise<Buffer> {
|
||||||
|
return new Promise<Buffer>((resolve, reject) => {
|
||||||
|
const cp = spawn(FFMPEG_PATH, ['-y', '-i', filePath, '-ar', '24000', '-ac', '1', '-f', 's16le', pcmPath]);
|
||||||
|
cp.on('error', (err: Error) => {
|
||||||
|
logger.log('FFmpeg处理转换出错: ', err.message);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
cp.on('exit', async (code, signal) => {
|
||||||
|
if (code == null || EXIT_CODES.includes(code)) {
|
||||||
|
try {
|
||||||
|
const data = await fsPromise.readFile(pcmPath);
|
||||||
|
await fsPromise.unlink(pcmPath);
|
||||||
|
resolve(data);
|
||||||
|
} catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.log(`FFmpeg exit: code=${code ?? 'unknown'} sig=${signal ?? 'unknown'}`);
|
||||||
|
reject(new Error('FFmpeg处理转换失败'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleWavFile(
|
||||||
|
file: Buffer, filePath: string, pcmPath: string, logger: LogWrapper
|
||||||
|
): Promise<{input: Buffer, sampleRate: number}> {
|
||||||
|
const { fmt } = getWavFileInfo(file);
|
||||||
|
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
|
||||||
|
return { input: await convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
||||||
|
}
|
||||||
|
return { input: file, sampleRate: fmt.sampleRate };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) {
|
||||||
try {
|
try {
|
||||||
const file = await fsPromise.readFile(filePath);
|
const file = await fsPromise.readFile(filePath);
|
||||||
const pttPath = path.join(TEMP_DIR, randomUUID());
|
const pttPath = path.join(TEMP_DIR, randomUUID());
|
||||||
if (!isSilk(file)) {
|
if (!isSilk(file)) {
|
||||||
logger.log(`语音文件${filePath}需要转换成silk`);
|
logger.log(`语音文件${filePath}需要转换成silk`);
|
||||||
const _isWav = isWav(file);
|
const pcmPath = `${pttPath}.pcm`;
|
||||||
const pcmPath = pttPath + '.pcm';
|
const { input, sampleRate } = isWav(file)
|
||||||
let sampleRate = 0;
|
? (await handleWavFile(file, filePath, pcmPath, logger))
|
||||||
const convert = () => {
|
: { input: await convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
||||||
return new Promise<Buffer>((resolve, reject) => {
|
|
||||||
// todo: 通过配置文件获取ffmpeg路径
|
|
||||||
const ffmpegPath = process.env.FFMPEG_PATH || 'ffmpeg';
|
|
||||||
const cp = spawn(ffmpegPath, ['-y', '-i', filePath, '-ar', '24000', '-ac', '1', '-f', 's16le', pcmPath]);
|
|
||||||
cp.on('error', err => {
|
|
||||||
logger.log('FFmpeg处理转换出错: ', err.message);
|
|
||||||
return reject(err);
|
|
||||||
});
|
|
||||||
cp.on('exit', (code, signal) => {
|
|
||||||
const EXIT_CODES = [0, 255];
|
|
||||||
if (code == null || EXIT_CODES.includes(code)) {
|
|
||||||
sampleRate = 24000;
|
|
||||||
const data = fs.readFileSync(pcmPath);
|
|
||||||
fs.unlink(pcmPath, (err) => {
|
|
||||||
});
|
|
||||||
return resolve(data);
|
|
||||||
}
|
|
||||||
logger.log(`FFmpeg exit: code=${code ?? 'unknown'} sig=${signal ?? 'unknown'}`);
|
|
||||||
reject(Error('FFmpeg处理转换失败'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
let input: Buffer;
|
|
||||||
if (!_isWav) {
|
|
||||||
input = await convert();
|
|
||||||
} else {
|
|
||||||
input = file;
|
|
||||||
const allowSampleRate = [8000, 12000, 16000, 24000, 32000, 44100, 48000];
|
|
||||||
const { fmt } = getWavFileInfo(input);
|
|
||||||
// log(`wav文件信息`, fmt)
|
|
||||||
if (!allowSampleRate.includes(fmt.sampleRate)) {
|
|
||||||
input = await convert();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const silk = await encode(input, sampleRate);
|
const silk = await encode(input, sampleRate);
|
||||||
fs.writeFileSync(pttPath, silk.data);
|
await fsPromise.writeFile(pttPath, silk.data);
|
||||||
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
||||||
return {
|
return {
|
||||||
converted: true,
|
converted: true,
|
||||||
@@ -68,15 +69,13 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
|||||||
duration: silk.duration / 1000,
|
duration: silk.duration / 1000,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
const silk = file;
|
|
||||||
let duration = 0;
|
let duration = 0;
|
||||||
try {
|
try {
|
||||||
duration = getDuration(silk) / 1000;
|
duration = getDuration(file) / 1000;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.log('获取语音文件时长失败, 使用文件大小推测时长', filePath, e.stack);
|
logger.log('获取语音文件时长失败, 使用文件大小推测时长', filePath, e.stack);
|
||||||
duration = await guessDuration(filePath);
|
duration = await guessDuration(filePath, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
converted: false,
|
converted: false,
|
||||||
path: filePath,
|
path: filePath,
|
||||||
@@ -84,7 +83,7 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
logger.logError('convert silk failed', error.stack);
|
logger.logError.bind(logger)('convert silk failed', error.stack);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -40,7 +40,7 @@ export abstract class ConfigBase<T> {
|
|||||||
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
|
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
|
||||||
logger.log(`[Core] [Config] 配置文件创建成功!\n`);
|
logger.log(`[Core] [Config] 配置文件创建成功!\n`);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.logError(`[Core] [Config] 创建配置文件时发生错误:`, e.message);
|
logger.logError.bind(logger)(`[Core] [Config] 创建配置文件时发生错误:`, e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -49,9 +49,9 @@ export abstract class ConfigBase<T> {
|
|||||||
return this.configData;
|
return this.configData;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
if (e instanceof SyntaxError) {
|
if (e instanceof SyntaxError) {
|
||||||
logger.logError(`[Core] [Config] 配置文件格式错误,请检查配置文件:`, e.message);
|
logger.logError.bind(logger)(`[Core] [Config] 配置文件格式错误,请检查配置文件:`, e.message);
|
||||||
} else {
|
} else {
|
||||||
logger.logError(`[Core] [Config] 读取配置文件时发生错误:`, e.message);
|
logger.logError.bind(logger)(`[Core] [Config] 读取配置文件时发生错误:`, e.message);
|
||||||
}
|
}
|
||||||
return {} as T;
|
return {} as T;
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ export abstract class ConfigBase<T> {
|
|||||||
try {
|
try {
|
||||||
fs.writeFileSync(configPath, JSON.stringify(newConfigData, this.getKeys(), 2));
|
fs.writeFileSync(configPath, JSON.stringify(newConfigData, this.getKeys(), 2));
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.logError(`保存配置文件 ${configPath} 时发生错误:`, e.message);
|
logger.logError.bind(logger)(`保存配置文件 ${configPath} 时发生错误:`, e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,133 +0,0 @@
|
|||||||
import type { NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core/wrapper';
|
|
||||||
import EventEmitter from 'node:events';
|
|
||||||
|
|
||||||
export type ListenerClassBase = Record<string, string>;
|
|
||||||
|
|
||||||
export interface ListenerIBase {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: any): ListenerClassBase;
|
|
||||||
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NTEventWrapperV2 extends EventEmitter {
|
|
||||||
private wrapperApi: WrapperNodeApi;
|
|
||||||
private wrapperSession: NodeIQQNTWrapperSession;
|
|
||||||
private listenerRefStorage = new Map<string, ListenerIBase>();
|
|
||||||
|
|
||||||
constructor(WrapperApi: WrapperNodeApi, WrapperSession: NodeIQQNTWrapperSession) {
|
|
||||||
super();
|
|
||||||
this.on('error', () => {
|
|
||||||
});
|
|
||||||
this.wrapperApi = WrapperApi;
|
|
||||||
this.wrapperSession = WrapperSession;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatcherListener(ListenerEvent: string, ...args: any[]) {
|
|
||||||
this.emit(ListenerEvent, ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
createProxyDispatch(ListenerMainName: string) {
|
|
||||||
const dispatcherListener = this.dispatcherListener.bind(this);
|
|
||||||
return new Proxy({}, {
|
|
||||||
get(_target: any, prop: any, _receiver: any) {
|
|
||||||
return (...args: any[]) => {
|
|
||||||
dispatcherListener(ListenerMainName + '/' + prop, ...args);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getOrInitListener<T>(listenerMainName: string): Promise<T> {
|
|
||||||
const ListenerType = this.wrapperApi[listenerMainName];
|
|
||||||
//获取NTQQ 外部 Listener包装
|
|
||||||
if (!ListenerType) throw new Error('Init Listener not found');
|
|
||||||
let Listener = this.listenerRefStorage.get(listenerMainName);
|
|
||||||
//判断是否已创建 创建则跳过
|
|
||||||
if (!Listener && ListenerType) {
|
|
||||||
Listener = new ListenerType(this.createProxyDispatch(listenerMainName));
|
|
||||||
if (!Listener) throw new Error('Init Listener failed');
|
|
||||||
//实例化NTQQ Listener外包装
|
|
||||||
const ServiceSubName = /^NodeIKernel(.*?)Listener$/.exec(listenerMainName)![1];
|
|
||||||
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
|
|
||||||
const addfunc = this.createEventFunction<(listener: T) => number>(Service);
|
|
||||||
//添加Listener到NTQQ
|
|
||||||
addfunc!(Listener as T);
|
|
||||||
this.listenerRefStorage.set(listenerMainName, Listener);
|
|
||||||
//保存Listener实例
|
|
||||||
}
|
|
||||||
return Listener as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
async createEventWithListener<EventType extends (...args: any) => any, ListenerType extends (...args: any) => any>
|
|
||||||
(
|
|
||||||
eventName: string,
|
|
||||||
listenerName: string,
|
|
||||||
waitTimes = 1,
|
|
||||||
timeout: number = 3000,
|
|
||||||
checker: (...args: Parameters<ListenerType>) => boolean,
|
|
||||||
...eventArg: Parameters<EventType>
|
|
||||||
) {
|
|
||||||
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(async (resolve, reject) => {
|
|
||||||
const ListenerNameList = listenerName.split('/');
|
|
||||||
const ListenerMainName = ListenerNameList[0];
|
|
||||||
//const ListenerSubName = ListenerNameList[1];
|
|
||||||
this.getOrInitListener<ListenerType>(ListenerMainName);
|
|
||||||
let complete = 0;
|
|
||||||
const retData: Parameters<ListenerType> | undefined = undefined;
|
|
||||||
let retEvent: any = {};
|
|
||||||
const databack = () => {
|
|
||||||
if (complete == 0) {
|
|
||||||
reject(new Error('Timeout: NTEvent EventName:' + eventName + ' ListenerName:' + listenerName + ' EventRet:\n' + JSON.stringify(retEvent, null, 4) + '\n'));
|
|
||||||
} else {
|
|
||||||
resolve([retEvent as Awaited<ReturnType<EventType>>, ...retData!]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const Timeouter = setTimeout(databack, timeout);
|
|
||||||
const callback = (...args: Parameters<ListenerType>) => {
|
|
||||||
if (checker(...args)) {
|
|
||||||
complete++;
|
|
||||||
if (complete >= waitTimes) {
|
|
||||||
clearTimeout(Timeouter);
|
|
||||||
this.removeListener(listenerName, callback);
|
|
||||||
databack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.on(listenerName, callback);
|
|
||||||
const EventFunc = this.createEventFunction<EventType>(eventName);
|
|
||||||
retEvent = await EventFunc!(...(eventArg as any[]));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private createEventFunction<T extends (...args: any) => any>(eventName: string): T | undefined {
|
|
||||||
const eventNameArr = eventName.split('/');
|
|
||||||
type eventType = {
|
|
||||||
[key: string]: () => { [key: string]: (...params: Parameters<T>) => Promise<ReturnType<T>> }
|
|
||||||
}
|
|
||||||
if (eventNameArr.length > 1) {
|
|
||||||
const serviceName = 'get' + eventNameArr[0].replace('NodeIKernel', '');
|
|
||||||
const eventName = eventNameArr[1];
|
|
||||||
//getNodeIKernelGroupListener,GroupService
|
|
||||||
//console.log('2', eventName);
|
|
||||||
const services = (this.wrapperSession as unknown as eventType)[serviceName]();
|
|
||||||
const event = services[eventName]
|
|
||||||
//重新绑定this
|
|
||||||
.bind(services);
|
|
||||||
if (event) {
|
|
||||||
return event as T;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async callEvent<EventType extends (...args: any[]) => Promise<any> | any>(
|
|
||||||
EventName = '', timeout: number = 3000, ...args: Parameters<EventType>) {
|
|
||||||
return new Promise<Awaited<ReturnType<EventType>>>((resolve) => {
|
|
||||||
const EventFunc = this.createEventFunction<EventType>(EventName);
|
|
||||||
EventFunc!(...args).then((retData: Awaited<ReturnType<EventType>> | PromiseLike<Awaited<ReturnType<EventType>>>) => resolve(retData));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//NTEvent2.0
|
|
@@ -236,7 +236,7 @@ export class NTEventWrapper {
|
|||||||
this.createListenerFunction(ListenerMainName);
|
this.createListenerFunction(ListenerMainName);
|
||||||
const eventFunction = this.createEventFunction(serviceAndMethod);
|
const eventFunction = this.createEventFunction(serviceAndMethod);
|
||||||
retEvent = await eventFunction!(...(args));
|
retEvent = await eventFunction!(...(args));
|
||||||
if (!checkerEvent(retEvent)) {
|
if (!checkerEvent(retEvent) && timeoutRef.hasRef()) {
|
||||||
clearTimeout(timeoutRef);
|
clearTimeout(timeoutRef);
|
||||||
reject(
|
reject(
|
||||||
new Error(
|
new Error(
|
||||||
@@ -250,86 +250,8 @@ export class NTEventWrapper {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
async callNormalEvent<
|
|
||||||
Service extends keyof ServiceNamingMapping,
|
|
||||||
ServiceMethod extends Exclude<keyof ServiceNamingMapping[Service], symbol>,
|
|
||||||
Listener extends keyof ListenerNamingMapping,
|
|
||||||
ListenerMethod extends Exclude<keyof ListenerNamingMapping[Listener], symbol>,
|
|
||||||
// eslint-disable-next-line
|
|
||||||
// @ts-ignore
|
|
||||||
EventType extends (...args: any) => any = ServiceNamingMapping[Service][ServiceMethod],
|
|
||||||
// eslint-disable-next-line
|
|
||||||
// @ts-ignore
|
|
||||||
ListenerType extends (...args: any) => any = ListenerNamingMapping[Listener][ListenerMethod]
|
|
||||||
>(
|
|
||||||
serviceAndMethod: `${Service}/${ServiceMethod}`,
|
|
||||||
listenerAndMethod: `${Listener}/${ListenerMethod}`,
|
|
||||||
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) => {
|
|
||||||
const id = randomUUID();
|
|
||||||
let complete = 0;
|
|
||||||
let retData: Parameters<ListenerType> | undefined = undefined;
|
|
||||||
let retEvent: any = {};
|
|
||||||
const databack = () => {
|
|
||||||
if (complete == 0) {
|
|
||||||
reject(
|
|
||||||
new Error(
|
|
||||||
'Timeout: NTEvent EventName:' +
|
|
||||||
serviceAndMethod +
|
|
||||||
' ListenerName:' +
|
|
||||||
listenerAndMethod +
|
|
||||||
' EventRet:\n' +
|
|
||||||
JSON.stringify(retEvent, null, 4) +
|
|
||||||
'\n',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
resolve([retEvent as Awaited<ReturnType<EventType>>, ...retData!]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const ListenerNameList = listenerAndMethod.split('/');
|
|
||||||
const ListenerMainName = ListenerNameList[0];
|
|
||||||
const ListenerSubName = ListenerNameList[1];
|
|
||||||
|
|
||||||
const Timeouter = setTimeout(databack, timeout);
|
|
||||||
|
|
||||||
const eventCallbak = {
|
|
||||||
timeout: timeout,
|
|
||||||
createtime: Date.now(),
|
|
||||||
checker: checker,
|
|
||||||
func: (...args: any[]) => {
|
|
||||||
complete++;
|
|
||||||
//console.log('func', ...args);
|
|
||||||
retData = args as Parameters<ListenerType>;
|
|
||||||
if (complete >= waitTimes) {
|
|
||||||
clearTimeout(Timeouter);
|
|
||||||
databack();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
if (!this.EventTask.get(ListenerMainName)) {
|
|
||||||
this.EventTask.set(ListenerMainName, new Map());
|
|
||||||
}
|
|
||||||
if (!this.EventTask.get(ListenerMainName)?.get(ListenerSubName)) {
|
|
||||||
this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map());
|
|
||||||
}
|
|
||||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak);
|
|
||||||
this.createListenerFunction(ListenerMainName);
|
|
||||||
const EventFunc = this.createEventFunction<EventType>(serviceAndMethod);
|
|
||||||
retEvent = await EventFunc!(...(args as any[]));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
@@ -123,7 +123,7 @@ export interface HttpDownloadOptions {
|
|||||||
headers?: Record<string, string> | string;
|
headers?: Record<string, string> | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function httpDownload(options: string | HttpDownloadOptions): Promise<Buffer> {
|
async function tryDownload(options: string | HttpDownloadOptions, useReferer: boolean = false): Promise<Response> {
|
||||||
// const chunks: Buffer[] = [];
|
// const chunks: Buffer[] = [];
|
||||||
let url: string;
|
let url: string;
|
||||||
let headers: Record<string, string> = {
|
let headers: Record<string, string> = {
|
||||||
@@ -142,15 +142,26 @@ export async function httpDownload(options: string | HttpDownloadOptions): Promi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (useReferer && !headers['Referer']) {
|
||||||
|
headers['Referer'] = url;
|
||||||
|
}
|
||||||
const fetchRes = await fetch(url, { headers }).catch((err) => {
|
const fetchRes = await fetch(url, { headers }).catch((err) => {
|
||||||
if (err.cause) {
|
if (err.cause) {
|
||||||
throw err.cause;
|
throw err.cause;
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
if (!fetchRes.ok) throw new Error(`下载文件失败: ${fetchRes.statusText}`);
|
return fetchRes;
|
||||||
|
}
|
||||||
|
|
||||||
const blob = await fetchRes.blob();
|
export async function httpDownload(options: string | HttpDownloadOptions): Promise<Buffer> {
|
||||||
|
const useReferer = typeof options === 'string';
|
||||||
|
let resp = await tryDownload(options);
|
||||||
|
if (resp.status === 403 && useReferer) {
|
||||||
|
resp = await tryDownload(options, true);
|
||||||
|
}
|
||||||
|
if (!resp.ok) throw new Error(`下载文件失败: ${resp.statusText}`);
|
||||||
|
const blob = await resp.blob();
|
||||||
const buffer = await blob.arrayBuffer();
|
const buffer = await blob.arrayBuffer();
|
||||||
return Buffer.from(buffer);
|
return Buffer.from(buffer);
|
||||||
}
|
}
|
||||||
@@ -160,8 +171,7 @@ type Uri2LocalRes = {
|
|||||||
errMsg: string,
|
errMsg: string,
|
||||||
fileName: string,
|
fileName: string,
|
||||||
ext: string,
|
ext: string,
|
||||||
path: string,
|
path: string
|
||||||
isLocal: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function checkFileV2(filePath: string) {
|
export async function checkFileV2(filePath: string) {
|
||||||
@@ -194,7 +204,6 @@ export async function checkUriType(Uri: string) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}, Uri);
|
}, Uri);
|
||||||
if (LocalFileRet) return LocalFileRet;
|
if (LocalFileRet) return LocalFileRet;
|
||||||
|
|
||||||
const OtherFileRet = await solveProblem((uri: string) => {
|
const OtherFileRet = await solveProblem((uri: string) => {
|
||||||
//再判断是否是Http
|
//再判断是否是Http
|
||||||
if (uri.startsWith('http://') || uri.startsWith('https://')) {
|
if (uri.startsWith('http://') || uri.startsWith('https://')) {
|
||||||
@@ -206,17 +215,17 @@ export async function checkUriType(Uri: string) {
|
|||||||
}
|
}
|
||||||
if (uri.startsWith('file://')) {
|
if (uri.startsWith('file://')) {
|
||||||
let filePath: string;
|
let filePath: string;
|
||||||
// await fs.copyFile(url.pathname, filePath);
|
|
||||||
const pathname = decodeURIComponent(new URL(uri).pathname);
|
const pathname = decodeURIComponent(new URL(uri).pathname);
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
filePath = pathname.slice(1);
|
filePath = pathname.slice(1);
|
||||||
} else {
|
} else {
|
||||||
filePath = pathname;
|
filePath = pathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { Uri: filePath, Type: FileUriType.Local };
|
return { Uri: filePath, Type: FileUriType.Local };
|
||||||
}
|
}
|
||||||
if (uri.startsWith('data:')) {
|
if (uri.startsWith('data:')) {
|
||||||
let data = uri.split(',')[1];
|
const data = uri.split(',')[1];
|
||||||
if (data) return { Uri: data, Type: FileUriType.Base64 };
|
if (data) return { Uri: data, Type: FileUriType.Base64 };
|
||||||
}
|
}
|
||||||
}, Uri);
|
}, Uri);
|
||||||
@@ -228,35 +237,42 @@ export async function checkUriType(Uri: string) {
|
|||||||
export async function uri2local(dir: string, uri: string, filename: string | undefined = undefined): Promise<Uri2LocalRes> {
|
export async function uri2local(dir: string, uri: string, filename: string | undefined = undefined): Promise<Uri2LocalRes> {
|
||||||
const { Uri: HandledUri, Type: UriType } = await checkUriType(uri);
|
const { Uri: HandledUri, Type: UriType } = await checkUriType(uri);
|
||||||
//解析失败
|
//解析失败
|
||||||
|
const tempName = randomUUID();
|
||||||
|
if (!filename) filename = randomUUID();
|
||||||
|
//解析Http和Https协议
|
||||||
|
|
||||||
if (UriType == FileUriType.Unknown) {
|
if (UriType == FileUriType.Unknown) {
|
||||||
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
|
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '' };
|
||||||
}
|
}
|
||||||
//解析File协议和本地文件
|
//解析File协议和本地文件
|
||||||
if (UriType == FileUriType.Local) {
|
if (UriType == FileUriType.Local) {
|
||||||
const fileExt = path.extname(HandledUri);
|
const fileExt = path.extname(HandledUri);
|
||||||
let filename = path.basename(HandledUri, fileExt);
|
let filename = path.basename(HandledUri, fileExt);
|
||||||
filename += fileExt;
|
filename += fileExt;
|
||||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: HandledUri, isLocal: true };
|
//复制文件到临时文件并保持后缀
|
||||||
|
const filenameTemp = tempName + fileExt;
|
||||||
|
const filePath = path.join(dir, filenameTemp);
|
||||||
|
fs.copyFileSync(HandledUri, filePath);
|
||||||
|
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
|
||||||
}
|
}
|
||||||
//接下来都要有文件名
|
//接下来都要有文件名
|
||||||
if (!filename) filename = randomUUID();
|
|
||||||
//解析Http和Https协议
|
|
||||||
|
|
||||||
if (UriType == FileUriType.Remote) {
|
if (UriType == FileUriType.Remote) {
|
||||||
const pathInfo = path.parse(decodeURIComponent(new URL(HandledUri).pathname));
|
const pathInfo = path.parse(decodeURIComponent(new URL(HandledUri).pathname));
|
||||||
if (pathInfo.name) {
|
if (pathInfo.name) {
|
||||||
filename = pathInfo.name;
|
const pathlen = 200 - dir.length - pathInfo.name.length;
|
||||||
|
filename = pathlen > 0 ? pathInfo.name.substring(0, pathlen) : pathInfo.name.substring(pathInfo.name.length, pathInfo.name.length - 10);//过长截断
|
||||||
if (pathInfo.ext) {
|
if (pathInfo.ext) {
|
||||||
filename += pathInfo.ext;
|
filename += pathInfo.ext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filename = filename.replace(/[/\\:*?"<>|]/g, '_');
|
filename = filename.replace(/[/\\:*?"<>|]/g, '_');
|
||||||
const fileExt = path.extname(HandledUri);
|
const fileExt = path.extname(HandledUri).replace(/[/\\:*?"<>|]/g, '_').substring(0, 10);
|
||||||
const filePath = path.join(dir, filename);
|
const filePath = path.join(dir, tempName + fileExt);
|
||||||
const buffer = await httpDownload(HandledUri);
|
const buffer = await httpDownload(HandledUri);
|
||||||
fs.writeFileSync(filePath, buffer);
|
//没有文件就创建
|
||||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: false };
|
fs.writeFileSync(filePath, buffer, { flag: 'wx' });
|
||||||
|
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
|
||||||
}
|
}
|
||||||
//解析Base64
|
//解析Base64
|
||||||
if (UriType == FileUriType.Base64) {
|
if (UriType == FileUriType.Base64) {
|
||||||
@@ -271,7 +287,7 @@ export async function uri2local(dir: string, uri: string, filename: string | und
|
|||||||
fileExt = ext;
|
fileExt = ext;
|
||||||
filename = filename + '.' + ext;
|
filename = filename + '.' + ext;
|
||||||
}
|
}
|
||||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: false };
|
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
|
||||||
}
|
}
|
||||||
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
|
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '' };
|
||||||
}
|
}
|
||||||
|
@@ -163,34 +163,51 @@ export function isEqual(obj1: any, obj2: any) {
|
|||||||
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
||||||
if (os.platform() === 'linux') {
|
if (os.platform() === 'linux') {
|
||||||
return {
|
return {
|
||||||
baseVersion: '3.2.12-27597',
|
baseVersion: '3.2.12.28060',
|
||||||
curVersion: '3.2.12-27597',
|
curVersion: '3.2.12.28060',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '27597',
|
buildId: '27254',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (os.platform() === 'darwin') {
|
||||||
|
return {
|
||||||
|
baseVersion: '6.9.53.28060',
|
||||||
|
curVersion: '6.9.53.28060',
|
||||||
|
prevVersion: '',
|
||||||
|
onErrorVersions: [],
|
||||||
|
buildId: '28060',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
baseVersion: '9.9.15-27597',
|
baseVersion: '9.9.15-28131',
|
||||||
curVersion: '9.9.15-27597',
|
curVersion: '9.9.15-28131',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '27597',
|
buildId: '28131',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getQQPackageInfoPath(exePath: string = ''): string {
|
export function getQQPackageInfoPath(exePath: string = '', version?: string): string {
|
||||||
|
let packagePath;
|
||||||
if (os.platform() === 'darwin') {
|
if (os.platform() === 'darwin') {
|
||||||
return path.join(path.dirname(exePath), '..', 'Resources', 'app', 'package.json');
|
packagePath = path.join(path.dirname(exePath), '..', 'Resources', 'app', 'package.json');
|
||||||
|
} else if (os.platform() === 'linux') {
|
||||||
|
packagePath = path.join(path.dirname(exePath), './resources/app/package.json');
|
||||||
} else {
|
} else {
|
||||||
return path.join(path.dirname(exePath), 'resources', 'app', 'package.json');
|
packagePath = path.join(path.dirname(exePath), './versions/' + version + '/resources/app/package.json');
|
||||||
}
|
}
|
||||||
|
//下面是老版本兼容 未来去掉
|
||||||
|
if (!fs.existsSync(packagePath)) {
|
||||||
|
packagePath = path.join(path.dirname(exePath), './resources/app/versions/' + version + '/package.json');
|
||||||
|
}
|
||||||
|
return packagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getQQVersionConfigPath(exePath: string = ''): string | undefined {
|
export function getQQVersionConfigPath(exePath: string = ''): string | undefined {
|
||||||
let configVersionInfoPath;
|
let configVersionInfoPath;
|
||||||
if (os.platform() === 'win32') {
|
if (os.platform() === 'win32') {
|
||||||
configVersionInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'versions', 'config.json');
|
configVersionInfoPath = path.join(path.dirname(exePath), 'versions', 'config.json');
|
||||||
} else if (os.platform() === 'darwin') {
|
} else if (os.platform() === 'darwin') {
|
||||||
const userPath = os.homedir();
|
const userPath = os.homedir();
|
||||||
const appDataPath = path.resolve(userPath, './Library/Application Support/QQ');
|
const appDataPath = path.resolve(userPath, './Library/Application Support/QQ');
|
||||||
@@ -203,13 +220,18 @@ export function getQQVersionConfigPath(exePath: string = ''): string | undefined
|
|||||||
if (typeof configVersionInfoPath !== 'string') {
|
if (typeof configVersionInfoPath !== 'string') {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
//老版本兼容 未来去掉
|
||||||
|
if (!fs.existsSync(configVersionInfoPath)) {
|
||||||
|
configVersionInfoPath = path.join(path.dirname(exePath), './resources/app/versions/config.json');
|
||||||
|
}
|
||||||
if (!fs.existsSync(configVersionInfoPath)) {
|
if (!fs.existsSync(configVersionInfoPath)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return configVersionInfoPath;
|
return configVersionInfoPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calcQQLevel(level: QQLevel) {
|
export function calcQQLevel(level?: QQLevel) {
|
||||||
|
if (!level) return 0;
|
||||||
const { crownNum, sunNum, moonNum, starNum } = level;
|
const { crownNum, sunNum, moonNum, starNum } = level;
|
||||||
return crownNum * 64 + sunNum * 16 + moonNum * 4 + starNum;
|
return crownNum * 64 + sunNum * 16 + moonNum * 4 + starNum;
|
||||||
}
|
}
|
||||||
|
@@ -19,14 +19,16 @@ export class QQBasicInfoWrapper {
|
|||||||
//基础目录获取
|
//基础目录获取
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.QQMainPath = process.execPath;
|
this.QQMainPath = process.execPath;
|
||||||
this.QQPackageInfoPath = getQQPackageInfoPath(this.QQMainPath);
|
|
||||||
this.QQVersionConfigPath = getQQVersionConfigPath(this.QQMainPath);
|
this.QQVersionConfigPath = getQQVersionConfigPath(this.QQMainPath);
|
||||||
|
|
||||||
|
|
||||||
//基础信息获取 无快更则启用默认模板填充
|
//基础信息获取 无快更则启用默认模板填充
|
||||||
this.isQuickUpdate = !!this.QQVersionConfigPath;
|
this.isQuickUpdate = !!this.QQVersionConfigPath;
|
||||||
this.QQVersionConfig = this.isQuickUpdate
|
this.QQVersionConfig = this.isQuickUpdate
|
||||||
? JSON.parse(fs.readFileSync(this.QQVersionConfigPath!).toString())
|
? JSON.parse(fs.readFileSync(this.QQVersionConfigPath!).toString())
|
||||||
: getDefaultQQVersionConfigInfo();
|
: getDefaultQQVersionConfigInfo();
|
||||||
|
|
||||||
|
this.QQPackageInfoPath = getQQPackageInfoPath(this.QQMainPath, this.QQVersionConfig?.curVersion);
|
||||||
this.QQPackageInfo = JSON.parse(fs.readFileSync(this.QQPackageInfoPath).toString());
|
this.QQPackageInfo = JSON.parse(fs.readFileSync(this.QQPackageInfoPath).toString());
|
||||||
const { appid: IQQVersionAppid, qua: IQQVersionQua } = this.getAppidV2();
|
const { appid: IQQVersionAppid, qua: IQQVersionQua } = this.getAppidV2();
|
||||||
this.QQVersionAppid = IQQVersionAppid;
|
this.QQVersionAppid = IQQVersionAppid;
|
||||||
@@ -56,7 +58,7 @@ export class QQBasicInfoWrapper {
|
|||||||
case 'linux':
|
case 'linux':
|
||||||
return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||||
default:
|
default:
|
||||||
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||||
}
|
}
|
||||||
@@ -65,11 +67,11 @@ export class QQBasicInfoWrapper {
|
|||||||
getAppidInternal() {
|
getAppidInternal() {
|
||||||
switch (systemPlatform) {
|
switch (systemPlatform) {
|
||||||
case 'linux':
|
case 'linux':
|
||||||
return '537243600';
|
return '537246140';
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
return '537243441';
|
return '537246140';
|
||||||
default:
|
default:
|
||||||
return '537243538';
|
return '537246092';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,12 +1,8 @@
|
|||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { networkInterfaces } from 'os';
|
|
||||||
import { randomUUID } from 'crypto';
|
|
||||||
|
|
||||||
// 缓解Win7设备兼容性问题
|
// 缓解Win7设备兼容性问题
|
||||||
let osName: string;
|
let osName: string;
|
||||||
// 设备ID
|
|
||||||
let machineId: Promise<string>;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
osName = os.hostname();
|
osName = os.hostname();
|
||||||
@@ -14,54 +10,6 @@ try {
|
|||||||
osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4);
|
osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
const invalidMacAddresses = new Set([
|
|
||||||
'00:00:00:00:00:00',
|
|
||||||
'ff:ff:ff:ff:ff:ff',
|
|
||||||
'ac:de:48:00:11:22',
|
|
||||||
]);
|
|
||||||
|
|
||||||
function validateMacAddress(candidate: string): boolean {
|
|
||||||
// eslint-disable-next-line no-useless-escape
|
|
||||||
const tempCandidate = candidate.replace(/\-/g, ':').toLowerCase();
|
|
||||||
return !invalidMacAddresses.has(tempCandidate);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getMachineId(): Promise<string> {
|
|
||||||
if (!machineId) {
|
|
||||||
machineId = (async () => {
|
|
||||||
const id = await getMacMachineId();
|
|
||||||
return id ?? randomUUID(); // fallback, generate a UUID
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
|
|
||||||
return machineId;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMac(): string {
|
|
||||||
const ifaces = networkInterfaces();
|
|
||||||
for (const name in ifaces) {
|
|
||||||
const networkInterface = ifaces[name];
|
|
||||||
if (networkInterface) {
|
|
||||||
for (const { mac } of networkInterface) {
|
|
||||||
if (validateMacAddress(mac)) {
|
|
||||||
return mac;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('Unable to retrieve mac address (unexpected format)');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getMacMachineId(): Promise<string | undefined> {
|
|
||||||
try {
|
|
||||||
const crypto = await import('crypto');
|
|
||||||
const macAddress = getMac();
|
|
||||||
return crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex');
|
|
||||||
} catch (err) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const homeDir = os.homedir();
|
const homeDir = os.homedir();
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '2.4.0';
|
export const napCatVersion = '2.6.13';
|
||||||
|
@@ -1,63 +0,0 @@
|
|||||||
import {
|
|
||||||
CacheFileListItem,
|
|
||||||
CacheFileType,
|
|
||||||
ChatCacheListItemBasic,
|
|
||||||
ChatType,
|
|
||||||
InstanceContext,
|
|
||||||
NapCatCore,
|
|
||||||
} from '@/core';
|
|
||||||
|
|
||||||
export class NTQQCacheApi {
|
|
||||||
context: InstanceContext;
|
|
||||||
core: NapCatCore;
|
|
||||||
|
|
||||||
constructor(context: InstanceContext, core: NapCatCore) {
|
|
||||||
this.context = context;
|
|
||||||
this.core = core;
|
|
||||||
}
|
|
||||||
|
|
||||||
async setCacheSilentScan(isSilent: boolean = true) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
getCacheSessionPathList() {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
|
|
||||||
// 参数未验证
|
|
||||||
return this.context.session.getStorageCleanService().clearCacheDataByKeys(cacheKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
addCacheScannedPaths(pathMap: object = {}) {
|
|
||||||
return this.context.session.getStorageCleanService().addCacheScanedPaths(pathMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
scanCache() {
|
|
||||||
//return (await this.context.session.getStorageCleanService().scanCache()).size;
|
|
||||||
}
|
|
||||||
|
|
||||||
getHotUpdateCachePath() {
|
|
||||||
// 未实现
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
getDesktopTmpPath() {
|
|
||||||
// 未实现
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) {
|
|
||||||
return this.context.session.getStorageCleanService().getChatCacheInfo(type, pageSize, 1, pageIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
|
|
||||||
// const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
|
|
||||||
// 需要五个参数
|
|
||||||
// return napCatCore.session.getStorageCleanService().getFileCacheInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
|
|
||||||
return this.context.session.getStorageCleanService().clearChatCacheInfo(chats, fileKeys);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -24,6 +24,7 @@ import pathLib from 'node:path';
|
|||||||
import { defaultVideoThumbB64, getVideoInfo } from '@/common/video';
|
import { defaultVideoThumbB64, getVideoInfo } from '@/common/video';
|
||||||
import ffmpeg from 'fluent-ffmpeg';
|
import ffmpeg from 'fluent-ffmpeg';
|
||||||
import { encodeSilk } from '@/common/audio';
|
import { encodeSilk } from '@/common/audio';
|
||||||
|
import { MessageContext } from '@/onebot/api';
|
||||||
|
|
||||||
export class NTQQFileApi {
|
export class NTQQFileApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
@@ -33,7 +34,7 @@ export class NTQQFileApi {
|
|||||||
constructor(context: InstanceContext, core: NapCatCore) {
|
constructor(context: InstanceContext, core: NapCatCore) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.core = core;
|
this.core = core;
|
||||||
this.rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey', this.context.logger);
|
this.rkeyManager = new RkeyManager(['https://llob.linyuchen.net/rkey', 'http://napcat-sign.wumiao.wang:2082/rkey'], this.context.logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
async copyFile(filePath: string, destPath: string) {
|
async copyFile(filePath: string, destPath: string) {
|
||||||
@@ -71,7 +72,7 @@ export class NTQQFileApi {
|
|||||||
file_uuid: '',
|
file_uuid: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.copyFile(filePath, mediaPath!);
|
await this.copyFile(filePath, mediaPath);
|
||||||
const fileSize = await this.getFileSize(filePath);
|
const fileSize = await this.getFileSize(filePath);
|
||||||
return {
|
return {
|
||||||
md5: fileMd5,
|
md5: fileMd5,
|
||||||
@@ -82,7 +83,7 @@ export class NTQQFileApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async createValidSendFileElement(filePath: string, fileName: string = '', folderId: string = '',): Promise<SendFileElement> {
|
async createValidSendFileElement(context: MessageContext, filePath: string, fileName: string = '', folderId: string = '',): Promise<SendFileElement> {
|
||||||
const {
|
const {
|
||||||
fileName: _fileName,
|
fileName: _fileName,
|
||||||
path,
|
path,
|
||||||
@@ -91,6 +92,7 @@ export class NTQQFileApi {
|
|||||||
if (fileSize === 0) {
|
if (fileSize === 0) {
|
||||||
throw new Error('文件异常,大小为0');
|
throw new Error('文件异常,大小为0');
|
||||||
}
|
}
|
||||||
|
context.deleteAfterSentFiles.push(path);
|
||||||
return {
|
return {
|
||||||
elementType: ElementType.FILE,
|
elementType: ElementType.FILE,
|
||||||
elementId: '',
|
elementId: '',
|
||||||
@@ -103,12 +105,13 @@ export class NTQQFileApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async createValidSendPicElement(picPath: string, summary: string = '', subType: 0 | 1 = 0,): Promise<SendPicElement> {
|
async createValidSendPicElement(context: MessageContext, picPath: string, summary: string = '', subType: 0 | 1 = 0,): Promise<SendPicElement> {
|
||||||
const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType);
|
const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType);
|
||||||
if (fileSize === 0) {
|
if (fileSize === 0) {
|
||||||
throw new Error('文件异常,大小为0');
|
throw new Error('文件异常,大小为0');
|
||||||
}
|
}
|
||||||
const imageSize = await this.core.apis.FileApi.getImageSize(picPath);
|
const imageSize = await this.core.apis.FileApi.getImageSize(picPath);
|
||||||
|
context.deleteAfterSentFiles.push(path);
|
||||||
return {
|
return {
|
||||||
elementType: ElementType.PIC,
|
elementType: ElementType.PIC,
|
||||||
elementId: '',
|
elementId: '',
|
||||||
@@ -130,26 +133,40 @@ export class NTQQFileApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async createValidSendVideoElement(filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> {
|
async createValidSendVideoElement(context: MessageContext, filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> {
|
||||||
const logger = this.core.context.logger;
|
const logger = this.core.context.logger;
|
||||||
const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
|
|
||||||
if (fileSize === 0) {
|
|
||||||
throw new Error('文件异常,大小为0');
|
|
||||||
}
|
|
||||||
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
|
|
||||||
thumb = pathLib.dirname(thumb);
|
|
||||||
let videoInfo = {
|
let videoInfo = {
|
||||||
width: 1920, height: 1080,
|
width: 1920, height: 1080,
|
||||||
time: 15,
|
time: 15,
|
||||||
format: 'mp4',
|
format: 'mp4',
|
||||||
size: fileSize,
|
size: 0,
|
||||||
filePath,
|
filePath,
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
videoInfo = await getVideoInfo(path, logger);
|
videoInfo = await getVideoInfo(filePath, logger);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.logError('获取视频信息失败,将使用默认值', e);
|
logger.logError.bind(logger)('获取视频信息失败,将使用默认值', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fileExt = 'mp4';
|
||||||
|
try {
|
||||||
|
const tempExt = (await fileType.fileTypeFromFile(filePath))?.ext;
|
||||||
|
if (tempExt) fileExt = tempExt;
|
||||||
|
} catch (e) {
|
||||||
|
this.context.logger.logError.bind(logger)('获取文件类型失败', e);
|
||||||
|
}
|
||||||
|
const newFilePath = filePath + '.' + fileExt;
|
||||||
|
fs.copyFileSync(filePath, newFilePath);
|
||||||
|
context.deleteAfterSentFiles.push(newFilePath);
|
||||||
|
filePath = newFilePath;
|
||||||
|
const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
|
||||||
|
if (fileSize === 0) {
|
||||||
|
throw new Error('文件异常,大小为0');
|
||||||
|
}
|
||||||
|
videoInfo.size = fileSize;
|
||||||
|
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
|
||||||
|
thumb = pathLib.dirname(thumb);
|
||||||
|
|
||||||
const thumbPath = new Map();
|
const thumbPath = new Map();
|
||||||
const _thumbPath = await new Promise<string | undefined>((resolve, reject) => {
|
const _thumbPath = await new Promise<string | undefined>((resolve, reject) => {
|
||||||
const thumbFileName = `${md5}_0.png`;
|
const thumbFileName = `${md5}_0.png`;
|
||||||
@@ -179,11 +196,13 @@ export class NTQQFileApi {
|
|||||||
const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0;
|
const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0;
|
||||||
thumbPath.set(0, _thumbPath);
|
thumbPath.set(0, _thumbPath);
|
||||||
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : '';
|
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : '';
|
||||||
|
context.deleteAfterSentFiles.push(path);
|
||||||
|
const uploadName = (fileName || _fileName).toLocaleLowerCase().endsWith('.' + fileExt.toLocaleLowerCase()) ? (fileName || _fileName) : (fileName || _fileName) + '.' + fileExt;
|
||||||
return {
|
return {
|
||||||
elementType: ElementType.VIDEO,
|
elementType: ElementType.VIDEO,
|
||||||
elementId: '',
|
elementId: '',
|
||||||
videoElement: {
|
videoElement: {
|
||||||
fileName: fileName || _fileName,
|
fileName: uploadName,
|
||||||
filePath: path,
|
filePath: path,
|
||||||
videoMd5: md5,
|
videoMd5: md5,
|
||||||
thumbMd5,
|
thumbMd5,
|
||||||
@@ -207,7 +226,9 @@ export class NTQQFileApi {
|
|||||||
throw new Error('文件异常,大小为0');
|
throw new Error('文件异常,大小为0');
|
||||||
}
|
}
|
||||||
if (converted) {
|
if (converted) {
|
||||||
fsPromises.unlink(silkPath);
|
fsPromises.unlink(silkPath).then().catch(
|
||||||
|
(e) => this.context.logger.logError.bind(this.context.logger)('删除临时文件失败', e)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
elementType: ElementType.PTT,
|
elementType: ElementType.PTT,
|
||||||
@@ -246,7 +267,6 @@ export class NTQQFileApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
||||||
//logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
|
|
||||||
// 用于下载收到的消息中的图片等
|
// 用于下载收到的消息中的图片等
|
||||||
if (sourcePath && fs.existsSync(sourcePath)) {
|
if (sourcePath && fs.existsSync(sourcePath)) {
|
||||||
if (force) {
|
if (force) {
|
||||||
@@ -346,8 +366,8 @@ export class NTQQFileApi {
|
|||||||
if (url) {
|
if (url) {
|
||||||
const parsedUrl = new URL(IMAGE_HTTP_HOST + url);
|
const parsedUrl = new URL(IMAGE_HTTP_HOST + url);
|
||||||
const imageAppid = parsedUrl.searchParams.get('appid');
|
const imageAppid = parsedUrl.searchParams.get('appid');
|
||||||
const isNTFlavoredPic = imageAppid && ['1406', '1407'].includes(imageAppid);
|
const isNTV2 = imageAppid && ['1406', '1407'].includes(imageAppid);
|
||||||
if (isNTFlavoredPic) {
|
if (isNTV2) {
|
||||||
let rkey = parsedUrl.searchParams.get('rkey');
|
let rkey = parsedUrl.searchParams.get('rkey');
|
||||||
if (rkey) {
|
if (rkey) {
|
||||||
return IMAGE_HTTP_HOST_NT + url;
|
return IMAGE_HTTP_HOST_NT + url;
|
||||||
@@ -356,11 +376,9 @@ export class NTQQFileApi {
|
|||||||
rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
|
rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
|
||||||
return IMAGE_HTTP_HOST_NT + url + `${rkey}`;
|
return IMAGE_HTTP_HOST_NT + url + `${rkey}`;
|
||||||
} else {
|
} else {
|
||||||
// 老的图片url,不需要rkey
|
|
||||||
return IMAGE_HTTP_HOST + url;
|
return IMAGE_HTTP_HOST + url;
|
||||||
}
|
}
|
||||||
} else if (fileMd5 || md5HexStr) {
|
} else if (fileMd5 || md5HexStr) {
|
||||||
// 没有url,需要自己拼接
|
|
||||||
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`;
|
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`;
|
||||||
}
|
}
|
||||||
this.context.logger.logDebug('图片url获取失败', element);
|
this.context.logger.logDebug('图片url获取失败', element);
|
||||||
|
@@ -24,7 +24,7 @@ export class NTQQGroupApi {
|
|||||||
constructor(context: InstanceContext, core: NapCatCore) {
|
constructor(context: InstanceContext, core: NapCatCore) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.core = core;
|
this.core = core;
|
||||||
this.initCache().then().catch(context.logger.logError);
|
this.initCache().then().catch(context.logger.logError.bind(context.logger));
|
||||||
}
|
}
|
||||||
|
|
||||||
async initCache() {
|
async initCache() {
|
||||||
@@ -34,7 +34,13 @@ export class NTQQGroupApi {
|
|||||||
}
|
}
|
||||||
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
|
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
|
||||||
}
|
}
|
||||||
|
async getCoreAndBaseInfo(uids: string[]) {
|
||||||
|
return await this.core.eventWrapper.callNoListenerEvent(
|
||||||
|
'NodeIKernelProfileService/getCoreAndBaseInfo',
|
||||||
|
'nodeStore',
|
||||||
|
uids,
|
||||||
|
);
|
||||||
|
}
|
||||||
async fetchGroupEssenceList(groupCode: string) {
|
async fetchGroupEssenceList(groupCode: string) {
|
||||||
const pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
const pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
||||||
return this.context.session.getGroupService().fetchGroupEssenceList({
|
return this.context.session.getGroupService().fetchGroupEssenceList({
|
||||||
@@ -262,6 +268,23 @@ export class NTQQGroupApi {
|
|||||||
}
|
}
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
|
async searchGroup(groupCode: string) {
|
||||||
|
const [, ret] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
|
'NodeIKernelSearchService/searchGroup',
|
||||||
|
'NodeIKernelSearchListener/onSearchGroupResult',
|
||||||
|
[{
|
||||||
|
keyWords: groupCode,
|
||||||
|
groupNum: 25,
|
||||||
|
exactSearch: false,
|
||||||
|
penetrate: ''
|
||||||
|
}],
|
||||||
|
(ret) => ret.result === 0,
|
||||||
|
(params) => !!params.groupInfos.find(g => g.groupCode === groupCode),
|
||||||
|
1,
|
||||||
|
5000
|
||||||
|
);
|
||||||
|
return ret.groupInfos.find(g => g.groupCode === groupCode);
|
||||||
|
}
|
||||||
async getGroupMemberEx(GroupCode: string, uid: string, forced = false, retry = 2) {
|
async getGroupMemberEx(GroupCode: string, uid: string, forced = false, retry = 2) {
|
||||||
const data = await solveAsyncProblem((eventWrapper: NTEventWrapper, GroupCode: string, uid: string, forced = false) => {
|
const data = await solveAsyncProblem((eventWrapper: NTEventWrapper, GroupCode: string, uid: string, forced = false) => {
|
||||||
return eventWrapper.callNormalEventV2(
|
return eventWrapper.callNormalEventV2(
|
||||||
|
@@ -5,5 +5,4 @@ export * from './msg';
|
|||||||
export * from './user';
|
export * from './user';
|
||||||
export * from './webapi';
|
export * from './webapi';
|
||||||
export * from './sign';
|
export * from './sign';
|
||||||
export * from './system';
|
export * from './system';
|
||||||
export * from './cache';
|
|
@@ -94,6 +94,7 @@ export class NTQQMsgApi {
|
|||||||
pageLimit: 1,
|
pageLimit: 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
//@deprecated
|
||||||
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
|
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
|
||||||
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
|
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,13 @@ export class NTQQUserApi {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
this.core = core;
|
this.core = core;
|
||||||
}
|
}
|
||||||
|
//self_tind格式
|
||||||
|
async createUidFromTinyId(tinyId: string) {
|
||||||
|
return this.context.session.getMsgService().createUidFromTinyId(this.core.selfInfo.uin, tinyId);
|
||||||
|
}
|
||||||
|
async getStatusByUid(uid: string) {
|
||||||
|
return this.context.session.getProfileService().getStatus(uid);
|
||||||
|
}
|
||||||
async getProfileLike(uid: string) {
|
async getProfileLike(uid: string) {
|
||||||
return this.context.session.getProfileLikeService().getBuddyProfileLike({
|
return this.context.session.getProfileLikeService().getBuddyProfileLike({
|
||||||
friendUids: [uid],
|
friendUids: [uid],
|
||||||
@@ -24,7 +30,18 @@ export class NTQQUserApi {
|
|||||||
limit: 20,
|
limit: 20,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
async fetchOtherProfileLike(uid: string) {
|
||||||
|
return this.context.session.getProfileLikeService().getBuddyProfileLike({
|
||||||
|
friendUids: [uid],
|
||||||
|
basic: 1,
|
||||||
|
vote: 1,
|
||||||
|
favorite: 0,
|
||||||
|
userProfile: 0,
|
||||||
|
type: 1,
|
||||||
|
start: 0,
|
||||||
|
limit: 20,
|
||||||
|
});
|
||||||
|
}
|
||||||
async setLongNick(longNick: string) {
|
async setLongNick(longNick: string) {
|
||||||
return this.context.session.getProfileService().setLongNick(longNick);
|
return this.context.session.getProfileService().setLongNick(longNick);
|
||||||
}
|
}
|
||||||
@@ -159,7 +176,7 @@ export class NTQQUserApi {
|
|||||||
if (uid) return uid;
|
if (uid) return uid;
|
||||||
uid = (await this.context.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin);
|
uid = (await this.context.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin);
|
||||||
if (uid) return uid;
|
if (uid) return uid;
|
||||||
const unverifiedUid = (await this.getUserDetailInfoByUinV2(Uin)).detail.uid;//从QQ Native 特殊转换
|
const unverifiedUid = (await this.getUserDetailInfoByUin(Uin)).detail.uid;//从QQ Native 特殊转换
|
||||||
if (unverifiedUid.indexOf('*') == -1) uid = unverifiedUid;
|
if (unverifiedUid.indexOf('*') == -1) uid = unverifiedUid;
|
||||||
//if (uid) return uid;
|
//if (uid) return uid;
|
||||||
return uid;
|
return uid;
|
||||||
@@ -195,7 +212,7 @@ export class NTQQUserApi {
|
|||||||
return await this.context.session.getRecentContactService().getRecentContactList();
|
return await this.context.session.getRecentContactService().getRecentContactList();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUserDetailInfoByUinV2(Uin: string) {
|
async getUserDetailInfoByUin(Uin: string) {
|
||||||
return await this.core.eventWrapper.callNoListenerEvent(
|
return await this.core.eventWrapper.callNoListenerEvent(
|
||||||
'NodeIKernelProfileService/getUserDetailInfoByUin',
|
'NodeIKernelProfileService/getUserDetailInfoByUin',
|
||||||
Uin
|
Uin
|
||||||
|
@@ -264,7 +264,7 @@ export class NTQQWebApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logError('获取龙王信息失败');
|
this.context.logger.logError.bind(this.context.logger)('获取龙王信息失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
||||||
@@ -280,7 +280,7 @@ export class NTQQWebApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logError('获取群聊之火失败');
|
this.context.logger.logError.bind(this.context.logger)('获取群聊之火失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
||||||
@@ -296,7 +296,7 @@ export class NTQQWebApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logError('获取群聊炽焰失败');
|
this.context.logger.logError.bind(this.context.logger)('获取群聊炽焰失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
||||||
@@ -312,7 +312,7 @@ export class NTQQWebApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logError('获取快乐源泉失败');
|
this.context.logger.logError.bind(this.context.logger)('获取快乐源泉失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { GroupMemberRole, Peer } from '@/core';
|
import { GroupMemberRole } from '@/core';
|
||||||
|
|
||||||
export interface Peer {
|
export interface Peer {
|
||||||
chatType: ChatType;
|
chatType: ChatType;
|
||||||
@@ -959,3 +959,18 @@ export interface TmpChatInfo {
|
|||||||
sessionType: number;
|
sessionType: number;
|
||||||
sig: string;
|
sig: string;
|
||||||
}
|
}
|
||||||
|
export interface MsgReqType {
|
||||||
|
peer: Peer,
|
||||||
|
byType: number,
|
||||||
|
msgId: string,
|
||||||
|
msgSeq: string,
|
||||||
|
msgTime: string,
|
||||||
|
clientSeq: string,
|
||||||
|
cnt: number,
|
||||||
|
queryOrder: boolean,
|
||||||
|
includeSelf: boolean,
|
||||||
|
includeDeleteMsg: boolean,
|
||||||
|
extraCnt: number
|
||||||
|
}
|
||||||
|
//getMsgsIncludeSelf Peer必须 byType 1
|
||||||
|
//getMsgsWithMsgTimeAndClientSeqForC2C Peer必须 byType 3
|
@@ -1,14 +1,15 @@
|
|||||||
export interface IdMusicSignPostData {
|
export interface IdMusicSignPostData {
|
||||||
type: 'qq' | '163',
|
type: 'qq' | '163' | 'kugou' | 'migu' | 'kuwo',
|
||||||
id: string | number,
|
id: string | number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CustomMusicSignPostData {
|
export interface CustomMusicSignPostData {
|
||||||
type: 'custom',
|
type: 'qq' | '163' | 'kugou' | 'migu' | 'kuwo' | 'custom',
|
||||||
|
id: undefined,
|
||||||
url: string,
|
url: string,
|
||||||
audio: string,
|
audio?: string,
|
||||||
title: string,
|
title?: string,
|
||||||
image?: string,
|
image: string,
|
||||||
singer?: string
|
singer?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -153,7 +153,10 @@ interface CommonExt {
|
|||||||
labels: any[];
|
labels: any[];
|
||||||
qqLevel: QQLevel;
|
qqLevel: QQLevel;
|
||||||
}
|
}
|
||||||
|
export enum BuddyListReqType {
|
||||||
|
KNOMAL,
|
||||||
|
KLETTER
|
||||||
|
}
|
||||||
interface Pic {
|
interface Pic {
|
||||||
picId: string;
|
picId: string;
|
||||||
picTime: number;
|
picTime: number;
|
||||||
@@ -213,7 +216,7 @@ export interface BuddyProfileLikeReq {
|
|||||||
userProfile: number;
|
userProfile: number;
|
||||||
type: number;
|
type: number;
|
||||||
start: number;
|
start: number;
|
||||||
limit: number;
|
limit?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QQLevel {
|
export interface QQLevel {
|
||||||
@@ -294,7 +297,7 @@ export enum BizKey {
|
|||||||
KPHOTOWALL
|
KPHOTOWALL
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserDetailInfoByUinV2 {
|
export interface UserDetailInfoByUin {
|
||||||
result: number,
|
result: number,
|
||||||
errMsg: string,
|
errMsg: string,
|
||||||
detail: {
|
detail: {
|
||||||
@@ -305,65 +308,6 @@ export interface UserDetailInfoByUinV2 {
|
|||||||
photoWall: null
|
photoWall: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserDetailInfoByUin {
|
|
||||||
result: number,
|
|
||||||
errMsg: string,
|
|
||||||
info: {
|
|
||||||
uid: string,//这个没办法用
|
|
||||||
qid: string,
|
|
||||||
uin: string,
|
|
||||||
nick: string,
|
|
||||||
remark: string,
|
|
||||||
longNick: string,
|
|
||||||
avatarUrl: string,
|
|
||||||
birthday_year: number,
|
|
||||||
birthday_month: number,
|
|
||||||
birthday_day: number,
|
|
||||||
sex: number,//0
|
|
||||||
topTime: string,
|
|
||||||
constellation: number,
|
|
||||||
shengXiao: number,
|
|
||||||
kBloodType: number,
|
|
||||||
homeTown: string,
|
|
||||||
makeFriendCareer: number,
|
|
||||||
pos: string,
|
|
||||||
eMail: string,
|
|
||||||
phoneNum: string,
|
|
||||||
college: string,
|
|
||||||
country: string,
|
|
||||||
province: string,
|
|
||||||
city: string,
|
|
||||||
postCode: string,
|
|
||||||
address: string,
|
|
||||||
isBlock: boolean,
|
|
||||||
isSpecialCareOpen: boolean,
|
|
||||||
isSpecialCareZone: boolean,
|
|
||||||
ringId: string,
|
|
||||||
regTime: number,
|
|
||||||
interest: string,
|
|
||||||
termType: number,
|
|
||||||
labels: any[],
|
|
||||||
qqLevel: { crownNum: number, sunNum: number, moonNum: number, starNum: number },
|
|
||||||
isHideQQLevel: number,
|
|
||||||
privilegeIcon: { jumpUrl: string, openIconList: any[], closeIconList: any[] },
|
|
||||||
isHidePrivilegeIcon: number,
|
|
||||||
photoWall: { picList: any[] },
|
|
||||||
vipFlag: boolean,
|
|
||||||
yearVipFlag: boolean,
|
|
||||||
svipFlag: boolean,
|
|
||||||
vipLevel: number,
|
|
||||||
status: number,
|
|
||||||
qidianMasterFlag: number,
|
|
||||||
qidianCrewFlag: number,
|
|
||||||
qidianCrewFlag2: number,
|
|
||||||
extStatus: number,
|
|
||||||
recommendImgFlag: number,
|
|
||||||
disableEmojiShortCuts: number,
|
|
||||||
pendantId: string,
|
|
||||||
vipNameColorId: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export enum UserDetailSource {
|
export enum UserDetailSource {
|
||||||
KDB,
|
KDB,
|
||||||
KSERVER
|
KSERVER
|
||||||
@@ -375,8 +319,4 @@ export enum ProfileBizType {
|
|||||||
KVAS,
|
KVAS,
|
||||||
KQZONE,
|
KQZONE,
|
||||||
KOTHER
|
KOTHER
|
||||||
}export enum BuddyListReqType {
|
}
|
||||||
KNOMAL,
|
|
||||||
KLETTER
|
|
||||||
}
|
|
||||||
|
|
24
src/core/external/appid.json
vendored
24
src/core/external/appid.json
vendored
@@ -1,14 +1,18 @@
|
|||||||
{
|
{
|
||||||
"3.2.12-27597": {
|
"9.9.15-28060": {
|
||||||
"appid": 537243600,
|
"appid": 537246092,
|
||||||
"qua": "V1_LNX_NQ_3.2.12_27597_GW_B"
|
"qua": "V1_WIN_NQ_9.9.15_28060_GW_B"
|
||||||
},
|
},
|
||||||
"9.9.15-27597": {
|
"9.9.15-28131": {
|
||||||
"appid": 537243441,
|
"appid": 537246092,
|
||||||
"qua": "V1_WIN_NQ_9.9.15_27597_GW_B"
|
"qua": "V1_WIN_NQ_9.9.15_28131_GW_B"
|
||||||
},
|
},
|
||||||
"6.9.53-27597": {
|
"3.2.12-28060": {
|
||||||
"appid": 537243538,
|
"appid": 537246140,
|
||||||
"qua": "V1_MAC_NQ_6.9.53_27597_GW_B"
|
"qua": "V1_LNX_NQ_3.2.12_28060_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.12-28131": {
|
||||||
|
"appid": 537246140,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.12_28131_GW_B"
|
||||||
}
|
}
|
||||||
}
|
}
|
18
src/core/external/proto/ProfileLikeTip.proto
vendored
Normal file
18
src/core/external/proto/ProfileLikeTip.proto
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package SysMessage;
|
||||||
|
|
||||||
|
message likeDetail {
|
||||||
|
string txt = 1;
|
||||||
|
int64 uin = 3;
|
||||||
|
string nickname = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message likeMsg {
|
||||||
|
int32 times = 1;
|
||||||
|
int32 time = 2;
|
||||||
|
likeDetail detail = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message profileLikeTip {
|
||||||
|
likeMsg msg = 14;
|
||||||
|
}
|
@@ -8,7 +8,7 @@ interface ServerRkeyData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RkeyManager {
|
export class RkeyManager {
|
||||||
serverUrl: string = '';
|
serverUrl: string[] = [];
|
||||||
logger: LogWrapper;
|
logger: LogWrapper;
|
||||||
private rkeyData: ServerRkeyData = {
|
private rkeyData: ServerRkeyData = {
|
||||||
group_rkey: '',
|
group_rkey: '',
|
||||||
@@ -16,7 +16,7 @@ export class RkeyManager {
|
|||||||
expired_time: 0,
|
expired_time: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(serverUrl: string, logger: LogWrapper) {
|
constructor(serverUrl: string[], logger: LogWrapper) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.serverUrl = serverUrl;
|
this.serverUrl = serverUrl;
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ export class RkeyManager {
|
|||||||
try {
|
try {
|
||||||
await this.refreshRkey();
|
await this.refreshRkey();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError('获取rkey失败', e);
|
this.logger.logError.bind(this.logger)('获取rkey失败', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.rkeyData;
|
return this.rkeyData;
|
||||||
@@ -40,6 +40,13 @@ export class RkeyManager {
|
|||||||
|
|
||||||
async refreshRkey(): Promise<any> {
|
async refreshRkey(): Promise<any> {
|
||||||
//刷新rkey
|
//刷新rkey
|
||||||
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(this.serverUrl, 'GET');
|
for (const url of this.serverUrl) {
|
||||||
|
try {
|
||||||
|
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET');
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.logError.bind(this.logger)(`[Rkey] Get Rkey ${url} Error `, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ import { QQBasicInfoWrapper } from '@/common/qq-basic-info';
|
|||||||
import { NapCatPathWrapper } from '@/common/path';
|
import { NapCatPathWrapper } from '@/common/path';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import { getMachineId, hostname, systemName, systemVersion } from '@/common/system';
|
import { hostname, systemName, systemVersion } from '@/common/system';
|
||||||
import { NTEventWrapper } from '@/common/event';
|
import { NTEventWrapper } from '@/common/event';
|
||||||
import { DataSource, GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/entities';
|
import { DataSource, GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/entities';
|
||||||
import { NapCatConfigLoader } from '@/core/helper/config';
|
import { NapCatConfigLoader } from '@/core/helper/config';
|
||||||
@@ -45,12 +45,18 @@ export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
|
|||||||
let appPath;
|
let appPath;
|
||||||
if (os.platform() === 'darwin') {
|
if (os.platform() === 'darwin') {
|
||||||
appPath = path.resolve(path.dirname(process.execPath), '../Resources/app');
|
appPath = path.resolve(path.dirname(process.execPath), '../Resources/app');
|
||||||
} else {
|
} else if (os.platform() === 'linux') {
|
||||||
appPath = path.resolve(path.dirname(process.execPath), './resources/app');
|
appPath = path.resolve(path.dirname(process.execPath), './resources/app');
|
||||||
|
} else {
|
||||||
|
appPath = path.resolve(path.dirname(process.execPath), `./versions/${QQVersion}/`);
|
||||||
}
|
}
|
||||||
let wrapperNodePath = path.resolve(appPath, 'wrapper.node');
|
let wrapperNodePath = path.resolve(appPath, 'wrapper.node');
|
||||||
if (!fs.existsSync(wrapperNodePath)) {
|
if (!fs.existsSync(wrapperNodePath)) {
|
||||||
wrapperNodePath = path.join(appPath, `versions/${QQVersion}/wrapper.node`);
|
wrapperNodePath = path.join(appPath, `./resources/app/wrapper.node`);
|
||||||
|
}
|
||||||
|
//老版本兼容 未来去掉
|
||||||
|
if (!fs.existsSync(wrapperNodePath)) {
|
||||||
|
wrapperNodePath = path.join(path.dirname(process.execPath), `./resources/app/versions/${QQVersion}/wrapper.node`);
|
||||||
}
|
}
|
||||||
const nativemodule: any = { exports: {} };
|
const nativemodule: any = { exports: {} };
|
||||||
process.dlopen(nativemodule, wrapperNodePath);
|
process.dlopen(nativemodule, wrapperNodePath);
|
||||||
@@ -93,7 +99,7 @@ export class NapCatCore {
|
|||||||
if (!fs.existsSync(this.NapCatTempPath)) {
|
if (!fs.existsSync(this.NapCatTempPath)) {
|
||||||
fs.mkdirSync(this.NapCatTempPath, { recursive: true });
|
fs.mkdirSync(this.NapCatTempPath, { recursive: true });
|
||||||
}
|
}
|
||||||
this.initNapCatCoreListeners().then().catch(this.context.logger.logError);
|
this.initNapCatCoreListeners().then().catch(this.context.logger.logError.bind(this.context.logger));
|
||||||
|
|
||||||
this.context.logger.setFileLogEnabled(
|
this.context.logger.setFileLogEnabled(
|
||||||
this.configLoader.configData.fileLog,
|
this.configLoader.configData.fileLog,
|
||||||
@@ -121,7 +127,7 @@ export class NapCatCore {
|
|||||||
const msgListener = new NodeIKernelMsgListener();
|
const msgListener = new NodeIKernelMsgListener();
|
||||||
msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => {
|
msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => {
|
||||||
// 下线通知
|
// 下线通知
|
||||||
this.context.logger.logError('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc);
|
this.context.logger.logError.bind(this.context.logger)('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc);
|
||||||
this.selfInfo.online = false;
|
this.selfInfo.online = false;
|
||||||
};
|
};
|
||||||
msgListener.onRecvMsg = (msgs) => {
|
msgListener.onRecvMsg = (msgs) => {
|
||||||
@@ -145,7 +151,6 @@ export class NapCatCore {
|
|||||||
if (Info.status == 20) {
|
if (Info.status == 20) {
|
||||||
this.selfInfo.online = false;
|
this.selfInfo.online = false;
|
||||||
this.context.logger.log("账号状态变更为离线");
|
this.context.logger.log("账号状态变更为离线");
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
this.selfInfo.online = true;
|
this.selfInfo.online = true;
|
||||||
}
|
}
|
||||||
@@ -242,22 +247,41 @@ export class NapCatCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function genSessionConfig(QQVersionAppid: string, QQVersion: string, selfUin: string, selfUid: string, account_path: string): Promise<WrapperSessionInitConfig> {
|
export async function genSessionConfig(
|
||||||
|
guid:string,
|
||||||
|
QQVersionAppid: string,
|
||||||
|
QQVersion: string,
|
||||||
|
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 });
|
||||||
const guid: string = await getMachineId();//26702 支持JS获取guid值 在LoginService中获取 TODO mlikiow a
|
//os.platform()
|
||||||
|
let systemPlatform = PlatformType.KWINDOWS;
|
||||||
|
switch (os.platform()) {
|
||||||
|
case 'win32':
|
||||||
|
systemPlatform = PlatformType.KWINDOWS;
|
||||||
|
break;
|
||||||
|
case 'darwin':
|
||||||
|
systemPlatform = PlatformType.KMAC;
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
systemPlatform = PlatformType.KLINUX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
selfUin,
|
selfUin,
|
||||||
selfUid,
|
selfUid,
|
||||||
desktopPathConfig: {
|
desktopPathConfig: {
|
||||||
account_path, // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
account_path, // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
||||||
},
|
},
|
||||||
clientVer: QQVersion, // 9.9.8-22355
|
clientVer: QQVersion,
|
||||||
a2: '',
|
a2: '',
|
||||||
d2: '',
|
d2: '',
|
||||||
d2Key: '',
|
d2Key: '',
|
||||||
machineId: '',
|
machineId: '',
|
||||||
platform: PlatformType.KWINDOWS, // 3是Windows?
|
platform: systemPlatform, // 3是Windows?
|
||||||
platVer: systemVersion, // 系统版本号, 应该可以固定
|
platVer: systemVersion, // 系统版本号, 应该可以固定
|
||||||
appid: QQVersionAppid,
|
appid: QQVersionAppid,
|
||||||
rdeliveryConfig: {
|
rdeliveryConfig: {
|
||||||
@@ -265,7 +289,7 @@ export async function genSessionConfig(QQVersionAppid: string, QQVersion: string
|
|||||||
systemId: 0,
|
systemId: 0,
|
||||||
appId: '',
|
appId: '',
|
||||||
logicEnvironment: '',
|
logicEnvironment: '',
|
||||||
platform: PlatformType.KWINDOWS,
|
platform: systemPlatform,
|
||||||
language: '',
|
language: '',
|
||||||
sdkVersion: '',
|
sdkVersion: '',
|
||||||
userId: '',
|
userId: '',
|
||||||
|
97
src/core/listeners/NodeIKernelSearchListener.ts
Normal file
97
src/core/listeners/NodeIKernelSearchListener.ts
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import { ChatType } from '@/core';
|
||||||
|
export interface SearchGroupInfo {
|
||||||
|
groupCode: string;
|
||||||
|
ownerUid: string;
|
||||||
|
groupFlag: number;
|
||||||
|
groupFlagExt: number;
|
||||||
|
maxMemberNum: number;
|
||||||
|
memberNum: number;
|
||||||
|
groupOption: number;
|
||||||
|
classExt: number;
|
||||||
|
groupName: string;
|
||||||
|
fingerMemo: string;
|
||||||
|
groupQuestion: string;
|
||||||
|
certType: number;
|
||||||
|
shutUpAllTimestamp: number;
|
||||||
|
shutUpMeTimestamp: number;
|
||||||
|
groupTypeFlag: number;
|
||||||
|
privilegeFlag: number;
|
||||||
|
groupSecLevel: number;
|
||||||
|
groupFlagExt3: number;
|
||||||
|
isConfGroup: number;
|
||||||
|
isModifyConfGroupFace: number;
|
||||||
|
isModifyConfGroupName: number;
|
||||||
|
noFigerOpenFlag: number;
|
||||||
|
noCodeFingerOpenFlag: number;
|
||||||
|
groupFlagExt4: number;
|
||||||
|
groupMemo: string;
|
||||||
|
cmdUinMsgSeq: number;
|
||||||
|
cmdUinJoinTime: number;
|
||||||
|
cmdUinUinFlag: number;
|
||||||
|
cmdUinMsgMask: number;
|
||||||
|
groupSecLevelInfo: number;
|
||||||
|
cmdUinPrivilege: number;
|
||||||
|
cmdUinFlagEx2: number;
|
||||||
|
appealDeadline: number;
|
||||||
|
remarkName: string;
|
||||||
|
isTop: boolean;
|
||||||
|
richFingerMemo: string;
|
||||||
|
groupAnswer: string;
|
||||||
|
joinGroupAuth: string;
|
||||||
|
isAllowModifyConfGroupName: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GroupInfo {
|
||||||
|
groupCode: string;
|
||||||
|
searchGroupInfo: SearchGroupInfo;
|
||||||
|
privilege: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GroupSearchResult {
|
||||||
|
keyWord: string;
|
||||||
|
errorCode: number;
|
||||||
|
groupInfos: GroupInfo[];
|
||||||
|
penetrate: string;
|
||||||
|
isEnd: boolean;
|
||||||
|
nextPos: number;
|
||||||
|
}
|
||||||
|
export interface NodeIKernelSearchListener {
|
||||||
|
|
||||||
|
onSearchGroupResult(params: GroupSearchResult): void;
|
||||||
|
|
||||||
|
onSearchFileKeywordsResult(params: {
|
||||||
|
searchId: string,
|
||||||
|
hasMore: boolean,
|
||||||
|
resultItems: {
|
||||||
|
chatType: ChatType,
|
||||||
|
buddyChatInfo: any[],
|
||||||
|
discussChatInfo: any[],
|
||||||
|
groupChatInfo: {
|
||||||
|
groupCode: string,
|
||||||
|
isConf: boolean,
|
||||||
|
hasModifyConfGroupFace: boolean,
|
||||||
|
hasModifyConfGroupName: boolean,
|
||||||
|
groupName: string,
|
||||||
|
remark: string
|
||||||
|
}[],
|
||||||
|
dataLineChatInfo: any[],
|
||||||
|
tmpChatInfo: any[],
|
||||||
|
msgId: string,
|
||||||
|
msgSeq: string,
|
||||||
|
msgTime: string,
|
||||||
|
senderUid: string,
|
||||||
|
senderNick: string,
|
||||||
|
senderRemark: string,
|
||||||
|
senderCard: string,
|
||||||
|
elemId: string,
|
||||||
|
elemType: number,
|
||||||
|
fileSize: string,
|
||||||
|
filePath: string,
|
||||||
|
fileName: string,
|
||||||
|
hits: {
|
||||||
|
start: number,
|
||||||
|
end: number
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}): void;
|
||||||
|
}
|
@@ -1,39 +0,0 @@
|
|||||||
import { ChatType } from '@/core';
|
|
||||||
|
|
||||||
export interface NodeIKernelSearchListener_Polyfill {
|
|
||||||
onSearchFileKeywordsResult(params: {
|
|
||||||
searchId: string,
|
|
||||||
hasMore: boolean,
|
|
||||||
resultItems: {
|
|
||||||
chatType: ChatType,
|
|
||||||
buddyChatInfo: any[],
|
|
||||||
discussChatInfo: any[],
|
|
||||||
groupChatInfo: {
|
|
||||||
groupCode: string,
|
|
||||||
isConf: boolean,
|
|
||||||
hasModifyConfGroupFace: boolean,
|
|
||||||
hasModifyConfGroupName: boolean,
|
|
||||||
groupName: string,
|
|
||||||
remark: string
|
|
||||||
}[],
|
|
||||||
dataLineChatInfo: any[],
|
|
||||||
tmpChatInfo: any[],
|
|
||||||
msgId: string,
|
|
||||||
msgSeq: string,
|
|
||||||
msgTime: string,
|
|
||||||
senderUid: string,
|
|
||||||
senderNick: string,
|
|
||||||
senderRemark: string,
|
|
||||||
senderCard: string,
|
|
||||||
elemId: string,
|
|
||||||
elemType: number,
|
|
||||||
fileSize: string,
|
|
||||||
filePath: string,
|
|
||||||
fileName: string,
|
|
||||||
hits: {
|
|
||||||
start: number,
|
|
||||||
end: number
|
|
||||||
}[]
|
|
||||||
}[]
|
|
||||||
}): void;
|
|
||||||
}
|
|
5
src/core/listeners/NodeIO3MiscListener.ts
Normal file
5
src/core/listeners/NodeIO3MiscListener.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export class NodeIO3MiscListener {
|
||||||
|
getOnAmgomDataPiece(...arg: unknown[]) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -9,7 +9,7 @@ export * from './NodeIKernelProfileListener';
|
|||||||
export * from './NodeIKernelTicketListener';
|
export * from './NodeIKernelTicketListener';
|
||||||
export * from './NodeIKernelStorageCleanListener';
|
export * from './NodeIKernelStorageCleanListener';
|
||||||
export * from './NodeIKernelFileAssistantListener';
|
export * from './NodeIKernelFileAssistantListener';
|
||||||
export * from './NodeIKernelSearchListener_Polyfill';
|
export * from './NodeIKernelSearchListener';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
NodeIKernelBuddyListener,
|
NodeIKernelBuddyListener,
|
||||||
@@ -19,11 +19,11 @@ import type {
|
|||||||
NodeIKernelMsgListener,
|
NodeIKernelMsgListener,
|
||||||
NodeIKernelProfileListener,
|
NodeIKernelProfileListener,
|
||||||
NodeIKernelRobotListener,
|
NodeIKernelRobotListener,
|
||||||
NodeIKernelSearchListener_Polyfill,
|
|
||||||
NodeIKernelSessionListener,
|
NodeIKernelSessionListener,
|
||||||
NodeIKernelStorageCleanListener,
|
NodeIKernelStorageCleanListener,
|
||||||
NodeIKernelTicketListener,
|
NodeIKernelTicketListener,
|
||||||
} from '.';
|
} from '.';
|
||||||
|
import { NodeIKernelSearchListener } from './NodeIKernelSearchListener';
|
||||||
|
|
||||||
export type ListenerNamingMapping = {
|
export type ListenerNamingMapping = {
|
||||||
NodeIKernelSessionListener: NodeIKernelSessionListener;
|
NodeIKernelSessionListener: NodeIKernelSessionListener;
|
||||||
@@ -36,5 +36,5 @@ export type ListenerNamingMapping = {
|
|||||||
NodeIKernelTicketListener: NodeIKernelTicketListener;
|
NodeIKernelTicketListener: NodeIKernelTicketListener;
|
||||||
NodeIKernelStorageCleanListener: NodeIKernelStorageCleanListener;
|
NodeIKernelStorageCleanListener: NodeIKernelStorageCleanListener;
|
||||||
NodeIKernelFileAssistantListener: NodeIKernelFileAssistantListener;
|
NodeIKernelFileAssistantListener: NodeIKernelFileAssistantListener;
|
||||||
NodeIKernelSearchListener: NodeIKernelSearchListener_Polyfill;
|
NodeIKernelSearchListener: NodeIKernelSearchListener;
|
||||||
};
|
};
|
||||||
|
@@ -1,341 +0,0 @@
|
|||||||
// @generated by protobuf-ts 2.9.4
|
|
||||||
// @generated from protobuf file "EmojiLikeToOthers.proto" (package "SysMessage", syntax proto3)
|
|
||||||
// tslint:disable
|
|
||||||
import type {
|
|
||||||
BinaryReadOptions,
|
|
||||||
BinaryWriteOptions,
|
|
||||||
IBinaryReader,
|
|
||||||
IBinaryWriter,
|
|
||||||
PartialMessage,
|
|
||||||
} from '@protobuf-ts/runtime';
|
|
||||||
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper1
|
|
||||||
*/
|
|
||||||
export interface EmojiLikeToOthersWrapper1 {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersWrapper2 wrapper = 1;
|
|
||||||
*/
|
|
||||||
wrapper?: EmojiLikeToOthersWrapper2;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper2
|
|
||||||
*/
|
|
||||||
export interface EmojiLikeToOthersWrapper2 {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersWrapper3 body = 1;
|
|
||||||
*/
|
|
||||||
body?: EmojiLikeToOthersWrapper3;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper3
|
|
||||||
*/
|
|
||||||
export interface EmojiLikeToOthersWrapper3 {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersMsgSpec msgSpec = 2;
|
|
||||||
*/
|
|
||||||
msgSpec?: EmojiLikeToOthersMsgSpec;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersAttributes attributes = 3;
|
|
||||||
*/
|
|
||||||
attributes?: EmojiLikeToOthersAttributes;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersMsgSpec
|
|
||||||
*/
|
|
||||||
export interface EmojiLikeToOthersMsgSpec {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 msgSeq = 1;
|
|
||||||
*/
|
|
||||||
msgSeq: number;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersAttributes
|
|
||||||
*/
|
|
||||||
export interface EmojiLikeToOthersAttributes {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: string emojiId = 1;
|
|
||||||
*/
|
|
||||||
emojiId: string;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: string senderUid = 4;
|
|
||||||
*/
|
|
||||||
senderUid: string;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersAttributes.Operation operation = 5;
|
|
||||||
*/
|
|
||||||
operation: EmojiLikeToOthersAttributes_Operation;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated from protobuf enum SysMessage.EmojiLikeToOthersAttributes.Operation
|
|
||||||
*/
|
|
||||||
export enum EmojiLikeToOthersAttributes_Operation {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf enum value: FALLBACK = 0;
|
|
||||||
*/
|
|
||||||
FALLBACK = 0,
|
|
||||||
/**
|
|
||||||
* @generated from protobuf enum value: LIKE = 1;
|
|
||||||
*/
|
|
||||||
LIKE = 1,
|
|
||||||
/**
|
|
||||||
* @generated from protobuf enum value: UNLIKE = 2;
|
|
||||||
*/
|
|
||||||
UNLIKE = 2
|
|
||||||
}
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class EmojiLikeToOthersWrapper1$Type extends MessageType<EmojiLikeToOthersWrapper1> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.EmojiLikeToOthersWrapper1", [
|
|
||||||
{ no: 1, name: "wrapper", kind: "message", T: () => EmojiLikeToOthersWrapper2 }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<EmojiLikeToOthersWrapper1>): EmojiLikeToOthersWrapper1 {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<EmojiLikeToOthersWrapper1>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersWrapper1): EmojiLikeToOthersWrapper1 {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* SysMessage.EmojiLikeToOthersWrapper2 wrapper */ 1:
|
|
||||||
message.wrapper = EmojiLikeToOthersWrapper2.internalBinaryRead(reader, reader.uint32(), options, message.wrapper);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: EmojiLikeToOthersWrapper1, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* SysMessage.EmojiLikeToOthersWrapper2 wrapper = 1; */
|
|
||||||
if (message.wrapper)
|
|
||||||
EmojiLikeToOthersWrapper2.internalBinaryWrite(message.wrapper, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersWrapper1
|
|
||||||
*/
|
|
||||||
export const EmojiLikeToOthersWrapper1 = new EmojiLikeToOthersWrapper1$Type();
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class EmojiLikeToOthersWrapper2$Type extends MessageType<EmojiLikeToOthersWrapper2> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.EmojiLikeToOthersWrapper2", [
|
|
||||||
{ no: 1, name: "body", kind: "message", T: () => EmojiLikeToOthersWrapper3 }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<EmojiLikeToOthersWrapper2>): EmojiLikeToOthersWrapper2 {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<EmojiLikeToOthersWrapper2>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersWrapper2): EmojiLikeToOthersWrapper2 {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* SysMessage.EmojiLikeToOthersWrapper3 body */ 1:
|
|
||||||
message.body = EmojiLikeToOthersWrapper3.internalBinaryRead(reader, reader.uint32(), options, message.body);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: EmojiLikeToOthersWrapper2, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* SysMessage.EmojiLikeToOthersWrapper3 body = 1; */
|
|
||||||
if (message.body)
|
|
||||||
EmojiLikeToOthersWrapper3.internalBinaryWrite(message.body, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersWrapper2
|
|
||||||
*/
|
|
||||||
export const EmojiLikeToOthersWrapper2 = new EmojiLikeToOthersWrapper2$Type();
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class EmojiLikeToOthersWrapper3$Type extends MessageType<EmojiLikeToOthersWrapper3> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.EmojiLikeToOthersWrapper3", [
|
|
||||||
{ no: 2, name: "msgSpec", kind: "message", T: () => EmojiLikeToOthersMsgSpec },
|
|
||||||
{ no: 3, name: "attributes", kind: "message", T: () => EmojiLikeToOthersAttributes }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<EmojiLikeToOthersWrapper3>): EmojiLikeToOthersWrapper3 {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<EmojiLikeToOthersWrapper3>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersWrapper3): EmojiLikeToOthersWrapper3 {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* SysMessage.EmojiLikeToOthersMsgSpec msgSpec */ 2:
|
|
||||||
message.msgSpec = EmojiLikeToOthersMsgSpec.internalBinaryRead(reader, reader.uint32(), options, message.msgSpec);
|
|
||||||
break;
|
|
||||||
case /* SysMessage.EmojiLikeToOthersAttributes attributes */ 3:
|
|
||||||
message.attributes = EmojiLikeToOthersAttributes.internalBinaryRead(reader, reader.uint32(), options, message.attributes);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: EmojiLikeToOthersWrapper3, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* SysMessage.EmojiLikeToOthersMsgSpec msgSpec = 2; */
|
|
||||||
if (message.msgSpec)
|
|
||||||
EmojiLikeToOthersMsgSpec.internalBinaryWrite(message.msgSpec, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
|
|
||||||
/* SysMessage.EmojiLikeToOthersAttributes attributes = 3; */
|
|
||||||
if (message.attributes)
|
|
||||||
EmojiLikeToOthersAttributes.internalBinaryWrite(message.attributes, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersWrapper3
|
|
||||||
*/
|
|
||||||
export const EmojiLikeToOthersWrapper3 = new EmojiLikeToOthersWrapper3$Type();
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class EmojiLikeToOthersMsgSpec$Type extends MessageType<EmojiLikeToOthersMsgSpec> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.EmojiLikeToOthersMsgSpec", [
|
|
||||||
{ no: 1, name: "msgSeq", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<EmojiLikeToOthersMsgSpec>): EmojiLikeToOthersMsgSpec {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
message.msgSeq = 0;
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<EmojiLikeToOthersMsgSpec>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersMsgSpec): EmojiLikeToOthersMsgSpec {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* uint32 msgSeq */ 1:
|
|
||||||
message.msgSeq = reader.uint32();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: EmojiLikeToOthersMsgSpec, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* uint32 msgSeq = 1; */
|
|
||||||
if (message.msgSeq !== 0)
|
|
||||||
writer.tag(1, WireType.Varint).uint32(message.msgSeq);
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersMsgSpec
|
|
||||||
*/
|
|
||||||
export const EmojiLikeToOthersMsgSpec = new EmojiLikeToOthersMsgSpec$Type();
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class EmojiLikeToOthersAttributes$Type extends MessageType<EmojiLikeToOthersAttributes> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.EmojiLikeToOthersAttributes", [
|
|
||||||
{ no: 1, name: "emojiId", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
|
||||||
{ no: 4, name: "senderUid", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
|
||||||
{ no: 5, name: "operation", kind: "enum", T: () => ["SysMessage.EmojiLikeToOthersAttributes.Operation", EmojiLikeToOthersAttributes_Operation] }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<EmojiLikeToOthersAttributes>): EmojiLikeToOthersAttributes {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
message.emojiId = "";
|
|
||||||
message.senderUid = "";
|
|
||||||
message.operation = 0;
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<EmojiLikeToOthersAttributes>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersAttributes): EmojiLikeToOthersAttributes {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* string emojiId */ 1:
|
|
||||||
message.emojiId = reader.string();
|
|
||||||
break;
|
|
||||||
case /* string senderUid */ 4:
|
|
||||||
message.senderUid = reader.string();
|
|
||||||
break;
|
|
||||||
case /* SysMessage.EmojiLikeToOthersAttributes.Operation operation */ 5:
|
|
||||||
message.operation = reader.int32();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: EmojiLikeToOthersAttributes, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* string emojiId = 1; */
|
|
||||||
if (message.emojiId !== "")
|
|
||||||
writer.tag(1, WireType.LengthDelimited).string(message.emojiId);
|
|
||||||
/* string senderUid = 4; */
|
|
||||||
if (message.senderUid !== "")
|
|
||||||
writer.tag(4, WireType.LengthDelimited).string(message.senderUid);
|
|
||||||
/* SysMessage.EmojiLikeToOthersAttributes.Operation operation = 5; */
|
|
||||||
if (message.operation !== 0)
|
|
||||||
writer.tag(5, WireType.Varint).int32(message.operation);
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersAttributes
|
|
||||||
*/
|
|
||||||
export const EmojiLikeToOthersAttributes = new EmojiLikeToOthersAttributes$Type();
|
|
@@ -1,104 +0,0 @@
|
|||||||
// @generated by protobuf-ts 2.9.4
|
|
||||||
// @generated from protobuf file "GreyTipWrapper.proto" (package "SysMessage", syntax proto3)
|
|
||||||
// tslint:disable
|
|
||||||
import type {
|
|
||||||
BinaryReadOptions,
|
|
||||||
BinaryWriteOptions,
|
|
||||||
IBinaryReader,
|
|
||||||
IBinaryWriter,
|
|
||||||
PartialMessage,
|
|
||||||
} from '@protobuf-ts/runtime';
|
|
||||||
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.GreyTipWrapper
|
|
||||||
*/
|
|
||||||
export interface GreyTipWrapper {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 subTypeId = 1;
|
|
||||||
*/
|
|
||||||
subTypeId: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 groupCode = 4;
|
|
||||||
*/
|
|
||||||
groupCode: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 subTypeIdMinusOne = 13;
|
|
||||||
*/
|
|
||||||
subTypeIdMinusOne: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: bytes rest = 44;
|
|
||||||
*/
|
|
||||||
rest: Uint8Array;
|
|
||||||
}
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class GreyTipWrapper$Type extends MessageType<GreyTipWrapper> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.GreyTipWrapper", [
|
|
||||||
{ no: 1, name: "subTypeId", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 4, name: "groupCode", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 13, name: "subTypeIdMinusOne", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 44, name: "rest", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<GreyTipWrapper>): GreyTipWrapper {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
message.subTypeId = 0;
|
|
||||||
message.groupCode = 0;
|
|
||||||
message.subTypeIdMinusOne = 0;
|
|
||||||
message.rest = new Uint8Array(0);
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<GreyTipWrapper>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GreyTipWrapper): GreyTipWrapper {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* uint32 subTypeId */ 1:
|
|
||||||
message.subTypeId = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* uint32 groupCode */ 4:
|
|
||||||
message.groupCode = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* uint32 subTypeIdMinusOne */ 13:
|
|
||||||
message.subTypeIdMinusOne = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* bytes rest */ 44:
|
|
||||||
message.rest = reader.bytes();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: GreyTipWrapper, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* uint32 subTypeId = 1; */
|
|
||||||
if (message.subTypeId !== 0)
|
|
||||||
writer.tag(1, WireType.Varint).uint32(message.subTypeId);
|
|
||||||
/* uint32 groupCode = 4; */
|
|
||||||
if (message.groupCode !== 0)
|
|
||||||
writer.tag(4, WireType.Varint).uint32(message.groupCode);
|
|
||||||
/* uint32 subTypeIdMinusOne = 13; */
|
|
||||||
if (message.subTypeIdMinusOne !== 0)
|
|
||||||
writer.tag(13, WireType.Varint).uint32(message.subTypeIdMinusOne);
|
|
||||||
/* bytes rest = 44; */
|
|
||||||
if (message.rest.length)
|
|
||||||
writer.tag(44, WireType.LengthDelimited).bytes(message.rest);
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.GreyTipWrapper
|
|
||||||
*/
|
|
||||||
export const GreyTipWrapper = new GreyTipWrapper$Type();
|
|
95
src/core/proto/ProfileLike.ts
Normal file
95
src/core/proto/ProfileLike.ts
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import * as pb from 'protobufjs';
|
||||||
|
|
||||||
|
// Proto: from src/core/proto/ProfileLike.proto
|
||||||
|
// Author: Mlikiowa
|
||||||
|
|
||||||
|
export interface LikeDetailType {
|
||||||
|
txt: string;
|
||||||
|
uin: pb.Long;
|
||||||
|
nickname: string;
|
||||||
|
}
|
||||||
|
export interface LikeMsgType {
|
||||||
|
times: number;
|
||||||
|
time: number;
|
||||||
|
detail: LikeDetailType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface profileLikeSubTipType {
|
||||||
|
msg: LikeMsgType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProfileLikeTipType {
|
||||||
|
msgType: number;
|
||||||
|
subType: number;
|
||||||
|
content: profileLikeSubTipType;
|
||||||
|
}
|
||||||
|
export interface SysMessageHeaderType {
|
||||||
|
id: string;
|
||||||
|
timestamp: number;
|
||||||
|
sender: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SysMessageMsgSpecType {
|
||||||
|
msgType: number;
|
||||||
|
subType: number;
|
||||||
|
subSubType: number;
|
||||||
|
msgSeq: number;
|
||||||
|
time: number;
|
||||||
|
msgId: pb.Long;
|
||||||
|
other: number;
|
||||||
|
}
|
||||||
|
export interface SysMessageBodyWrapperType {
|
||||||
|
wrappedBody: Uint8Array;
|
||||||
|
}
|
||||||
|
export interface SysMessageType {
|
||||||
|
header: SysMessageHeaderType[];
|
||||||
|
msgSpec: SysMessageMsgSpecType[];
|
||||||
|
bodyWrapper: SysMessageBodyWrapperType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SysMessageHeader = new pb.Type("SysMessageHeader")
|
||||||
|
.add(new pb.Field("PeerNumber", 1, "uint32"))
|
||||||
|
.add(new pb.Field("PeerString", 2, "string"))
|
||||||
|
.add(new pb.Field("Uin", 5, "uint32"))
|
||||||
|
.add(new pb.Field("Uid", 6, "string", "optional"));
|
||||||
|
|
||||||
|
export const SysMessageMsgSpec = new pb.Type("SysMessageMsgSpec")
|
||||||
|
.add(new pb.Field("msgType", 1, "uint32"))
|
||||||
|
.add(new pb.Field("subType", 2, "uint32"))
|
||||||
|
.add(new pb.Field("subSubType", 3, "uint32"))
|
||||||
|
.add(new pb.Field("msgSeq", 5, "uint32"))
|
||||||
|
.add(new pb.Field("time", 6, "uint32"))
|
||||||
|
.add(new pb.Field("msgId", 12, "uint64"))
|
||||||
|
.add(new pb.Field("other", 13, "uint32"));
|
||||||
|
|
||||||
|
export const SysMessageBodyWrapper = new pb.Type("SysMessageBodyWrapper")
|
||||||
|
.add(new pb.Field("wrappedBody", 2, "bytes"));
|
||||||
|
|
||||||
|
export const SysMessage = new pb.Type("SysMessage")
|
||||||
|
.add(SysMessageHeader)
|
||||||
|
.add(SysMessageMsgSpec)
|
||||||
|
.add(SysMessageBodyWrapper)
|
||||||
|
.add(new pb.Field("header", 1, "SysMessageHeader", "repeated"))
|
||||||
|
.add(new pb.Field("msgSpec", 2, "SysMessageMsgSpec", "repeated"))
|
||||||
|
.add(new pb.Field("bodyWrapper", 3, "SysMessageBodyWrapper"));
|
||||||
|
|
||||||
|
export const likeDetail = new pb.Type("likeDetail")
|
||||||
|
.add(new pb.Field("txt", 1, "string"))
|
||||||
|
.add(new pb.Field("uin", 3, "int64"))
|
||||||
|
.add(new pb.Field("nickname", 5, "string"));
|
||||||
|
|
||||||
|
export const likeMsg = new pb.Type("likeMsg")
|
||||||
|
.add(likeDetail)
|
||||||
|
.add(new pb.Field("times", 1, "int32"))
|
||||||
|
.add(new pb.Field("time", 2, "int32"))
|
||||||
|
.add(new pb.Field("detail", 3, "likeDetail"));
|
||||||
|
|
||||||
|
export const profileLikeSubTip = new pb.Type("profileLikeSubTip")
|
||||||
|
.add(likeMsg)
|
||||||
|
.add(new pb.Field("msg", 14, "likeMsg"))
|
||||||
|
|
||||||
|
export const profileLikeTip = new pb.Type("profileLikeTip")
|
||||||
|
.add(profileLikeSubTip)
|
||||||
|
.add(new pb.Field("msgType", 1, "int32"))
|
||||||
|
.add(new pb.Field("subType", 2, "int32"))
|
||||||
|
.add(new pb.Field("content", 203, "profileLikeSubTip"));
|
@@ -1,435 +0,0 @@
|
|||||||
// @generated by protobuf-ts 2.9.4
|
|
||||||
// @generated from protobuf file "SysMessage.proto" (package "SysMessage", syntax proto3)
|
|
||||||
// tslint:disable
|
|
||||||
import type {
|
|
||||||
BinaryReadOptions,
|
|
||||||
BinaryWriteOptions,
|
|
||||||
IBinaryReader,
|
|
||||||
IBinaryWriter,
|
|
||||||
PartialMessage,
|
|
||||||
} from '@protobuf-ts/runtime';
|
|
||||||
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.SysMessage
|
|
||||||
*/
|
|
||||||
export interface SysMessage {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: repeated SysMessage.SysMessageHeader header = 1;
|
|
||||||
*/
|
|
||||||
header: SysMessageHeader[];
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: repeated SysMessage.SysMessageMsgSpec msgSpec = 2;
|
|
||||||
*/
|
|
||||||
msgSpec: SysMessageMsgSpec[];
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: SysMessage.SysMessageBodyWrapper bodyWrapper = 3;
|
|
||||||
*/
|
|
||||||
bodyWrapper?: SysMessageBodyWrapper;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.SysMessageHeader
|
|
||||||
*/
|
|
||||||
export interface SysMessageHeader {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 PeerNumber = 1 [json_name = "PeerNumber"];
|
|
||||||
*/
|
|
||||||
peerNumber: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: string PeerString = 2 [json_name = "PeerString"];
|
|
||||||
*/
|
|
||||||
peerString: string;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 Uin = 5 [json_name = "Uin"];
|
|
||||||
*/
|
|
||||||
uin: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: optional string Uid = 6 [json_name = "Uid"];
|
|
||||||
*/
|
|
||||||
uid?: string;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.SysMessageMsgSpec
|
|
||||||
*/
|
|
||||||
export interface SysMessageMsgSpec {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 msgType = 1;
|
|
||||||
*/
|
|
||||||
msgType: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 subType = 2;
|
|
||||||
*/
|
|
||||||
subType: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 subSubType = 3;
|
|
||||||
*/
|
|
||||||
subSubType: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 msgSeq = 5;
|
|
||||||
*/
|
|
||||||
msgSeq: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 time = 6;
|
|
||||||
*/
|
|
||||||
time: number;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint64 msgId = 12;
|
|
||||||
*/
|
|
||||||
msgId: bigint;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: uint32 other = 13;
|
|
||||||
*/
|
|
||||||
other: number;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.SysMessageBodyWrapper
|
|
||||||
*/
|
|
||||||
export interface SysMessageBodyWrapper {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: bytes wrappedBody = 2;
|
|
||||||
*/
|
|
||||||
wrappedBody: Uint8Array; // Find the first [08], or ignore the first 7 bytes?
|
|
||||||
// And it becomes another ProtoBuf message.
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated from protobuf message SysMessage.KeyValuePair
|
|
||||||
*/
|
|
||||||
export interface KeyValuePair {
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: string key = 1;
|
|
||||||
*/
|
|
||||||
key: string;
|
|
||||||
/**
|
|
||||||
* @generated from protobuf field: string value = 2;
|
|
||||||
*/
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class SysMessage$Type extends MessageType<SysMessage> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.SysMessage", [
|
|
||||||
{ no: 1, name: "header", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => SysMessageHeader },
|
|
||||||
{ no: 2, name: "msgSpec", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => SysMessageMsgSpec },
|
|
||||||
{ no: 3, name: "bodyWrapper", kind: "message", T: () => SysMessageBodyWrapper }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<SysMessage>): SysMessage {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
message.header = [];
|
|
||||||
message.msgSpec = [];
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<SysMessage>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessage): SysMessage {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* repeated SysMessage.SysMessageHeader header */ 1:
|
|
||||||
message.header.push(SysMessageHeader.internalBinaryRead(reader, reader.uint32(), options));
|
|
||||||
break;
|
|
||||||
case /* repeated SysMessage.SysMessageMsgSpec msgSpec */ 2:
|
|
||||||
message.msgSpec.push(SysMessageMsgSpec.internalBinaryRead(reader, reader.uint32(), options));
|
|
||||||
break;
|
|
||||||
case /* SysMessage.SysMessageBodyWrapper bodyWrapper */ 3:
|
|
||||||
message.bodyWrapper = SysMessageBodyWrapper.internalBinaryRead(reader, reader.uint32(), options, message.bodyWrapper);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: SysMessage, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* repeated SysMessage.SysMessageHeader header = 1; */
|
|
||||||
for (let i = 0; i < message.header.length; i++)
|
|
||||||
SysMessageHeader.internalBinaryWrite(message.header[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
|
||||||
/* repeated SysMessage.SysMessageMsgSpec msgSpec = 2; */
|
|
||||||
for (let i = 0; i < message.msgSpec.length; i++)
|
|
||||||
SysMessageMsgSpec.internalBinaryWrite(message.msgSpec[i], writer.tag(2, WireType.LengthDelimited).fork(), options).join();
|
|
||||||
/* SysMessage.SysMessageBodyWrapper bodyWrapper = 3; */
|
|
||||||
if (message.bodyWrapper)
|
|
||||||
SysMessageBodyWrapper.internalBinaryWrite(message.bodyWrapper, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.SysMessage
|
|
||||||
*/
|
|
||||||
export const SysMessage = new SysMessage$Type();
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class SysMessageHeader$Type extends MessageType<SysMessageHeader> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.SysMessageHeader", [
|
|
||||||
{ no: 1, name: "PeerNumber", kind: "scalar", jsonName: "PeerNumber", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 2, name: "PeerString", kind: "scalar", jsonName: "PeerString", T: 9 /*ScalarType.STRING*/ },
|
|
||||||
{ no: 5, name: "Uin", kind: "scalar", jsonName: "Uin", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 6, name: "Uid", kind: "scalar", jsonName: "Uid", opt: true, T: 9 /*ScalarType.STRING*/ }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<SysMessageHeader>): SysMessageHeader {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
message.peerNumber = 0;
|
|
||||||
message.peerString = "";
|
|
||||||
message.uin = 0;
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<SysMessageHeader>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessageHeader): SysMessageHeader {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* uint32 PeerNumber = 1 [json_name = "PeerNumber"];*/ 1:
|
|
||||||
message.peerNumber = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* string PeerString = 2 [json_name = "PeerString"];*/ 2:
|
|
||||||
message.peerString = reader.string();
|
|
||||||
break;
|
|
||||||
case /* uint32 Uin = 5 [json_name = "Uin"];*/ 5:
|
|
||||||
message.uin = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* optional string Uid = 6 [json_name = "Uid"];*/ 6:
|
|
||||||
message.uid = reader.string();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: SysMessageHeader, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* uint32 PeerNumber = 1 [json_name = "PeerNumber"]; */
|
|
||||||
if (message.peerNumber !== 0)
|
|
||||||
writer.tag(1, WireType.Varint).uint32(message.peerNumber);
|
|
||||||
/* string PeerString = 2 [json_name = "PeerString"]; */
|
|
||||||
if (message.peerString !== "")
|
|
||||||
writer.tag(2, WireType.LengthDelimited).string(message.peerString);
|
|
||||||
/* uint32 Uin = 5 [json_name = "Uin"]; */
|
|
||||||
if (message.uin !== 0)
|
|
||||||
writer.tag(5, WireType.Varint).uint32(message.uin);
|
|
||||||
/* optional string Uid = 6 [json_name = "Uid"]; */
|
|
||||||
if (message.uid !== undefined)
|
|
||||||
writer.tag(6, WireType.LengthDelimited).string(message.uid);
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.SysMessageHeader
|
|
||||||
*/
|
|
||||||
export const SysMessageHeader = new SysMessageHeader$Type();
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class SysMessageMsgSpec$Type extends MessageType<SysMessageMsgSpec> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.SysMessageMsgSpec", [
|
|
||||||
{ no: 1, name: "msgType", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 2, name: "subType", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 3, name: "subSubType", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 5, name: "msgSeq", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 6, name: "time", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
|
||||||
{ no: 12, name: "msgId", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
|
||||||
{ no: 13, name: "other", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<SysMessageMsgSpec>): SysMessageMsgSpec {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
message.msgType = 0;
|
|
||||||
message.subType = 0;
|
|
||||||
message.subSubType = 0;
|
|
||||||
message.msgSeq = 0;
|
|
||||||
message.time = 0;
|
|
||||||
message.msgId = 0n;
|
|
||||||
message.other = 0;
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<SysMessageMsgSpec>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessageMsgSpec): SysMessageMsgSpec {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* uint32 msgType */ 1:
|
|
||||||
message.msgType = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* uint32 subType */ 2:
|
|
||||||
message.subType = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* uint32 subSubType */ 3:
|
|
||||||
message.subSubType = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* uint32 msgSeq */ 5:
|
|
||||||
message.msgSeq = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* uint32 time */ 6:
|
|
||||||
message.time = reader.uint32();
|
|
||||||
break;
|
|
||||||
case /* uint64 msgId */ 12:
|
|
||||||
message.msgId = reader.uint64().toBigInt();
|
|
||||||
break;
|
|
||||||
case /* uint32 other */ 13:
|
|
||||||
message.other = reader.uint32();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: SysMessageMsgSpec, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* uint32 msgType = 1; */
|
|
||||||
if (message.msgType !== 0)
|
|
||||||
writer.tag(1, WireType.Varint).uint32(message.msgType);
|
|
||||||
/* uint32 subType = 2; */
|
|
||||||
if (message.subType !== 0)
|
|
||||||
writer.tag(2, WireType.Varint).uint32(message.subType);
|
|
||||||
/* uint32 subSubType = 3; */
|
|
||||||
if (message.subSubType !== 0)
|
|
||||||
writer.tag(3, WireType.Varint).uint32(message.subSubType);
|
|
||||||
/* uint32 msgSeq = 5; */
|
|
||||||
if (message.msgSeq !== 0)
|
|
||||||
writer.tag(5, WireType.Varint).uint32(message.msgSeq);
|
|
||||||
/* uint32 time = 6; */
|
|
||||||
if (message.time !== 0)
|
|
||||||
writer.tag(6, WireType.Varint).uint32(message.time);
|
|
||||||
/* uint64 msgId = 12; */
|
|
||||||
if (message.msgId !== 0n)
|
|
||||||
writer.tag(12, WireType.Varint).uint64(message.msgId);
|
|
||||||
/* uint32 other = 13; */
|
|
||||||
if (message.other !== 0)
|
|
||||||
writer.tag(13, WireType.Varint).uint32(message.other);
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.SysMessageMsgSpec
|
|
||||||
*/
|
|
||||||
export const SysMessageMsgSpec = new SysMessageMsgSpec$Type();
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class SysMessageBodyWrapper$Type extends MessageType<SysMessageBodyWrapper> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.SysMessageBodyWrapper", [
|
|
||||||
{ no: 2, name: "wrappedBody", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<SysMessageBodyWrapper>): SysMessageBodyWrapper {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
message.wrappedBody = new Uint8Array(0);
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<SysMessageBodyWrapper>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessageBodyWrapper): SysMessageBodyWrapper {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* bytes wrappedBody */ 2:
|
|
||||||
message.wrappedBody = reader.bytes();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: SysMessageBodyWrapper, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* bytes wrappedBody = 2; */
|
|
||||||
if (message.wrappedBody.length)
|
|
||||||
writer.tag(2, WireType.LengthDelimited).bytes(message.wrappedBody);
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.SysMessageBodyWrapper
|
|
||||||
*/
|
|
||||||
export const SysMessageBodyWrapper = new SysMessageBodyWrapper$Type();
|
|
||||||
// @generated message type with reflection information, may provide speed optimized methods
|
|
||||||
class KeyValuePair$Type extends MessageType<KeyValuePair> {
|
|
||||||
constructor() {
|
|
||||||
super("SysMessage.KeyValuePair", [
|
|
||||||
{ no: 1, name: "key", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
|
||||||
{ no: 2, name: "value", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
create(value?: PartialMessage<KeyValuePair>): KeyValuePair {
|
|
||||||
const message = globalThis.Object.create((this.messagePrototype!));
|
|
||||||
message.key = "";
|
|
||||||
message.value = "";
|
|
||||||
if (value !== undefined)
|
|
||||||
reflectionMergePartial<KeyValuePair>(this, message, value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: KeyValuePair): KeyValuePair {
|
|
||||||
let message = target ?? this.create(), end = reader.pos + length;
|
|
||||||
while (reader.pos < end) {
|
|
||||||
let [fieldNo, wireType] = reader.tag();
|
|
||||||
switch (fieldNo) {
|
|
||||||
case /* string key */ 1:
|
|
||||||
message.key = reader.string();
|
|
||||||
break;
|
|
||||||
case /* string value */ 2:
|
|
||||||
message.value = reader.string();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let u = options.readUnknownField;
|
|
||||||
if (u === "throw")
|
|
||||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
||||||
let d = reader.skip(wireType);
|
|
||||||
if (u !== false)
|
|
||||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
internalBinaryWrite(message: KeyValuePair, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
|
||||||
/* string key = 1; */
|
|
||||||
if (message.key !== "")
|
|
||||||
writer.tag(1, WireType.LengthDelimited).string(message.key);
|
|
||||||
/* string value = 2; */
|
|
||||||
if (message.value !== "")
|
|
||||||
writer.tag(2, WireType.LengthDelimited).string(message.value);
|
|
||||||
let u = options.writeUnknownFields;
|
|
||||||
if (u !== false)
|
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @generated MessageType for protobuf message SysMessage.KeyValuePair
|
|
||||||
*/
|
|
||||||
export const KeyValuePair = new KeyValuePair$Type();
|
|
@@ -14,7 +14,7 @@ export interface NodeIKernelBuddyService {
|
|||||||
}>
|
}>
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
getBuddyListFromCache(callFrom: string): Promise<Array<
|
getBuddyListFromCache(reqType: BuddyListReqType): Promise<Array<
|
||||||
{
|
{
|
||||||
categoryId: number,//9999应该跳过 那是兜底数据吧
|
categoryId: number,//9999应该跳过 那是兜底数据吧
|
||||||
categorySortId: number,//排序方式
|
categorySortId: number,//排序方式
|
||||||
@@ -23,7 +23,7 @@ export interface NodeIKernelBuddyService {
|
|||||||
onlineCount: number,//在线数目
|
onlineCount: number,//在线数目
|
||||||
buddyUids: Array<string>//Uids
|
buddyUids: Array<string>//Uids
|
||||||
}>>;
|
}>>;
|
||||||
|
|
||||||
addKernelBuddyListener(listener: NodeIKernelBuddyListener): number;
|
addKernelBuddyListener(listener: NodeIKernelBuddyListener): number;
|
||||||
|
|
||||||
getAllBuddyCount(): number;
|
getAllBuddyCount(): number;
|
||||||
@@ -114,7 +114,7 @@ export interface NodeIKernelBuddyService {
|
|||||||
|
|
||||||
reportDoubtBuddyReqUnread(): void;
|
reportDoubtBuddyReqUnread(): void;
|
||||||
|
|
||||||
getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise<unknown>;
|
getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise<GeneralCallResult & { arkMsg: string }>;
|
||||||
|
|
||||||
isNull(): boolean;
|
isNull(): boolean;
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { NodeIKernelLoginListener } from '@/core/listeners/NodeIKernelLoginListener';
|
import { NodeIKernelLoginListener } from '@/core/listeners/NodeIKernelLoginListener';
|
||||||
|
import { GeneralCallResult } from './common';
|
||||||
|
|
||||||
export interface LoginInitConfig {
|
export interface LoginInitConfig {
|
||||||
machineId: '';
|
machineId: '';
|
||||||
@@ -59,8 +60,12 @@ export interface QuickLoginResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeIKernelLoginService {
|
export interface NodeIKernelLoginService {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
setLoginMiscData(arg0: string, value: string): unknown;
|
||||||
new(): NodeIKernelLoginService;
|
getMachineGuid(): string;
|
||||||
|
|
||||||
|
get(): NodeIKernelLoginService;
|
||||||
|
|
||||||
|
connect(): boolean;
|
||||||
|
|
||||||
addKernelLoginListener(listener: NodeIKernelLoginListener): number;
|
addKernelLoginListener(listener: NodeIKernelLoginListener): number;
|
||||||
|
|
||||||
@@ -68,7 +73,7 @@ export interface NodeIKernelLoginService {
|
|||||||
|
|
||||||
initConfig(config: LoginInitConfig): void;
|
initConfig(config: LoginInitConfig): void;
|
||||||
|
|
||||||
getLoginMiscData(cb: (r: unknown) => void): void;
|
getLoginMiscData(data: string): Promise<GeneralCallResult & { value: string }>;
|
||||||
|
|
||||||
getLoginList(): Promise<{
|
getLoginList(): Promise<{
|
||||||
result: number, // 0是ok
|
result: number, // 0是ok
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { ElementType, MessageElement, Peer, RawMessage, SendMessageElement } from '@/core/entities';
|
import { ElementType, MessageElement, Peer, RawMessage, SendMessageElement } from '@/core/entities';
|
||||||
import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener';
|
import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener';
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
import { QueryMsgsParams, TmpChatInfoApi } from '../entities/msg';
|
import { MsgReqType, QueryMsgsParams, TmpChatInfoApi } from '../entities/msg';
|
||||||
|
|
||||||
export interface NodeIKernelMsgService {
|
export interface NodeIKernelMsgService {
|
||||||
|
|
||||||
@@ -147,12 +147,15 @@ export interface NodeIKernelMsgService {
|
|||||||
msgList: RawMessage[]
|
msgList: RawMessage[]
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
//@deprecated
|
||||||
getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise<unknown>;
|
getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise<unknown>;
|
||||||
|
|
||||||
|
//@deprecated
|
||||||
getMsgsIncludeSelf(peer: Peer, msgId: string, count: number, queryOrder: boolean): Promise<GeneralCallResult & {
|
getMsgsIncludeSelf(peer: Peer, msgId: string, count: number, queryOrder: boolean): Promise<GeneralCallResult & {
|
||||||
msgList: RawMessage[]
|
msgList: RawMessage[]
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
//@deprecated
|
||||||
getMsgsWithMsgTimeAndClientSeqForC2C(...args: unknown[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
getMsgsWithMsgTimeAndClientSeqForC2C(...args: unknown[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||||
|
|
||||||
getMsgsWithStatus(params: {
|
getMsgsWithStatus(params: {
|
||||||
@@ -168,7 +171,7 @@ export interface NodeIKernelMsgService {
|
|||||||
getMsgsBySeqRange(peer: Peer, startSeq: string, endSeq: string): Promise<GeneralCallResult & {
|
getMsgsBySeqRange(peer: Peer, startSeq: string, endSeq: string): Promise<GeneralCallResult & {
|
||||||
msgList: RawMessage[]
|
msgList: RawMessage[]
|
||||||
}>;
|
}>;
|
||||||
|
//@deprecated
|
||||||
getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, unknownArg: boolean): Promise<GeneralCallResult & {
|
getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, unknownArg: boolean): Promise<GeneralCallResult & {
|
||||||
msgList: RawMessage[]
|
msgList: RawMessage[]
|
||||||
}>;
|
}>;
|
||||||
@@ -179,6 +182,8 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
getMsgsBySeqList(peer: Peer, seqList: string[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
getMsgsBySeqList(peer: Peer, seqList: string[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||||
|
|
||||||
|
getMsgsExt(msgReq: MsgReqType): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||||
|
|
||||||
getSingleMsg(Peer: Peer, msgSeq: string): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
getSingleMsg(Peer: Peer, msgSeq: string): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||||
|
|
||||||
getSourceOfReplyMsg(peer: Peer, MsgId: string, SourceSeq: string): unknown;
|
getSourceOfReplyMsg(peer: Peer, MsgId: string, SourceSeq: string): unknown;
|
||||||
@@ -318,7 +323,7 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
getFileThumbSavePath(...args: unknown[]): unknown;
|
getFileThumbSavePath(...args: unknown[]): unknown;
|
||||||
|
|
||||||
translatePtt2Text(msgId: string, peer: Peer, msgElement: unknown): unknown;
|
translatePtt2Text(msgId: string, peer: Peer, msgElement: MessageElement): unknown;
|
||||||
|
|
||||||
setPttPlayedState(...args: unknown[]): unknown;
|
setPttPlayedState(...args: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -391,7 +396,12 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
getEmojiResourcePath(...args: unknown[]): unknown;
|
getEmojiResourcePath(...args: unknown[]): unknown;
|
||||||
|
|
||||||
JoinDragonGroupEmoji(JoinDragonGroupEmojiReq: any/*joinDragonGroupEmojiReq*/): unknown;
|
JoinDragonGroupEmoji(JoinDragonGroupEmojiReq: {
|
||||||
|
latestMsgSeq: string,
|
||||||
|
manageEmojiId: number,
|
||||||
|
manageMsgSeq: string,
|
||||||
|
peerContact: Peer
|
||||||
|
}): Promise<unknown>;
|
||||||
|
|
||||||
getMsgAbstracts(...args: unknown[]): unknown;
|
getMsgAbstracts(...args: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -518,7 +528,7 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
canImportOldDbMsg(...args: unknown[]): unknown;
|
canImportOldDbMsg(...args: unknown[]): unknown;
|
||||||
|
|
||||||
setPowerStatus(z: boolean): unknown;
|
setPowerStatus(isPowerOn: boolean): unknown;
|
||||||
|
|
||||||
canProcessDataMigration(...args: unknown[]): unknown;
|
canProcessDataMigration(...args: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -607,7 +617,7 @@ export interface NodeIKernelMsgService {
|
|||||||
setIKernelPublicAccountAdapter(...args: unknown[]): unknown;
|
setIKernelPublicAccountAdapter(...args: unknown[]): unknown;
|
||||||
|
|
||||||
//tempChatGameSession有关
|
//tempChatGameSession有关
|
||||||
createUidFromTinyId(fromTinyId: string, toTinyId: string): unknown;
|
createUidFromTinyId(fromTinyId: string, toTinyId: string): string;
|
||||||
|
|
||||||
dataMigrationGetDataAvaiableContactList(...args: unknown[]): unknown;
|
dataMigrationGetDataAvaiableContactList(...args: unknown[]): unknown;
|
||||||
|
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
import { GeneralCallResult } from './common';
|
import { GeneralCallResult } from './common';
|
||||||
|
|
||||||
export interface NodeIKernelNodeMiscService {
|
export interface NodeIKernelNodeMiscService {
|
||||||
|
writeVersionToRegistry(version: string): void;
|
||||||
|
|
||||||
getMiniAppPath(): unknown;
|
getMiniAppPath(): unknown;
|
||||||
|
|
||||||
setMiniAppVersion(version: string): unknown;
|
setMiniAppVersion(version: string): unknown;
|
||||||
|
@@ -1,8 +1,13 @@
|
|||||||
import { AnyCnameRecord } from 'node:dns';
|
import { AnyCnameRecord } from 'node:dns';
|
||||||
import { BizKey, ModifyProfileParams, NodeIKernelProfileListener, ProfileBizType, SimpleInfo, UserDetailInfoByUinV2, UserDetailSource } from '@/core';
|
import { BizKey, ModifyProfileParams, NodeIKernelProfileListener, ProfileBizType, SimpleInfo, UserDetailInfoByUin, UserDetailSource } from '@/core';
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
|
|
||||||
export interface NodeIKernelProfileService {
|
export interface NodeIKernelProfileService {
|
||||||
|
getOtherFlag(callfrom: string, uids: string[]): Promise<Map<string, any>>;
|
||||||
|
|
||||||
|
getVasInfo(callfrom: string, uids: string[]): Promise<Map<string, any>>;
|
||||||
|
|
||||||
|
getRelationFlag(callfrom: string, uids: string[]): Promise<Map<string, any>>;
|
||||||
|
|
||||||
getUidByUin(callfrom: string, uin: Array<string>): Promise<Map<string, string>>;
|
getUidByUin(callfrom: string, uin: Array<string>): Promise<Map<string, string>>;
|
||||||
|
|
||||||
@@ -50,7 +55,7 @@ export interface NodeIKernelProfileService {
|
|||||||
|
|
||||||
getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise<GeneralCallResult>;
|
getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUinV2>;
|
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUin>;
|
||||||
|
|
||||||
getZplanAvatarInfos(args: string[]): Promise<unknown>;
|
getZplanAvatarInfos(args: string[]): Promise<unknown>;
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { ChatType } from '../entities';
|
import { ChatType } from '../entities';
|
||||||
|
import { GeneralCallResult } from './common';
|
||||||
|
|
||||||
export interface NodeIKernelSearchService {
|
export interface NodeIKernelSearchService {
|
||||||
|
|
||||||
@@ -8,7 +9,12 @@ export interface NodeIKernelSearchService {
|
|||||||
|
|
||||||
searchStranger(unknown: string, searchStranger: unknown, searchParams: unknown): Promise<unknown>;
|
searchStranger(unknown: string, searchStranger: unknown, searchParams: unknown): Promise<unknown>;
|
||||||
|
|
||||||
searchGroup(...args: any[]): unknown;// needs 1 arguments
|
searchGroup(param: {
|
||||||
|
keyWords: string,
|
||||||
|
groupNum: number,
|
||||||
|
exactSearch: boolean,
|
||||||
|
penetrate: string
|
||||||
|
}): Promise<GeneralCallResult>;// needs 1 arguments
|
||||||
|
|
||||||
searchLocalInfo(keywords: string, unknown: number/*4*/): unknown;
|
searchLocalInfo(keywords: string, unknown: number/*4*/): unknown;
|
||||||
|
|
||||||
|
@@ -4,14 +4,14 @@ export interface NodeIKernelUnitedConfigService {
|
|||||||
|
|
||||||
removeKernelUnitedConfigListener(listenerId:number): void;
|
removeKernelUnitedConfigListener(listenerId:number): void;
|
||||||
|
|
||||||
fetchUnitedCommendConfig(...args: any[]): unknown;// needs 1 arguments
|
|
||||||
|
|
||||||
fetchUnitedSwitchConfig(...args: any[]): unknown;// needs 1 arguments
|
fetchUnitedSwitchConfig(...args: any[]): unknown;// needs 1 arguments
|
||||||
|
|
||||||
loadUnitedConfig(...args: any[]): unknown;// needs 1 arguments
|
|
||||||
|
|
||||||
isUnitedConfigSwitchOn(...args: any[]): unknown;// needs 1 arguments
|
isUnitedConfigSwitchOn(...args: any[]): unknown;// needs 1 arguments
|
||||||
|
|
||||||
registerUnitedConfigPushGroupList(...args: any[]): unknown;// needs 1 arguments
|
registerUnitedConfigPushGroupList(...args: any[]): unknown;// needs 1 arguments
|
||||||
|
|
||||||
|
fetchUnitedCommendConfig(ids: `${string}`[]): void
|
||||||
|
|
||||||
|
loadUnitedConfig(id: string): Promise<unknown>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
11
src/core/services/NodeIO3MiscService.ts
Normal file
11
src/core/services/NodeIO3MiscService.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { NodeIO3MiscListener } from "../listeners/NodeIO3MiscListener";
|
||||||
|
|
||||||
|
export interface NodeIO3MiscService {
|
||||||
|
get(): NodeIO3MiscService;
|
||||||
|
|
||||||
|
addO3MiscListener(listeners: NodeIO3MiscListener): number;
|
||||||
|
|
||||||
|
setAmgomDataPiece(appid: string, dataPiece: Uint8Array): void;
|
||||||
|
|
||||||
|
reportAmgomWeather(type: string, uk2: string, arg: Array<string>): void;
|
||||||
|
}
|
@@ -26,6 +26,7 @@ import { NodeIKernelRecentContactService } from './services/NodeIKernelRecentCon
|
|||||||
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 { NodeIKernelECDHService } from './services/NodeIKernelECDHService';
|
||||||
|
import { NodeIO3MiscService } from './services/NodeIO3MiscService';
|
||||||
|
|
||||||
export interface NodeQQNTWrapperUtil {
|
export interface NodeQQNTWrapperUtil {
|
||||||
get(): unknown;
|
get(): unknown;
|
||||||
@@ -143,8 +144,7 @@ export interface NodeQQNTWrapperUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeIQQNTWrapperSession {
|
export interface NodeIQQNTWrapperSession {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
create(): NodeIQQNTWrapperSession;
|
||||||
new(): NodeIQQNTWrapperSession;
|
|
||||||
|
|
||||||
init(
|
init(
|
||||||
wrapperSessionInitConfig: WrapperSessionInitConfig,
|
wrapperSessionInitConfig: WrapperSessionInitConfig,
|
||||||
@@ -250,11 +250,11 @@ export interface NodeIQQNTWrapperSession {
|
|||||||
|
|
||||||
export interface EnginInitDesktopConfig {
|
export interface EnginInitDesktopConfig {
|
||||||
base_path_prefix: string;
|
base_path_prefix: string;
|
||||||
platform_type: 3;
|
platform_type: PlatformType;
|
||||||
app_type: 4;
|
app_type: 4;
|
||||||
app_version: string;
|
app_version: string;
|
||||||
os_version: string;
|
os_version: string;
|
||||||
use_xlog: true;
|
use_xlog: boolean;
|
||||||
qua: string;
|
qua: string;
|
||||||
global_path_config: {
|
global_path_config: {
|
||||||
desktopGlobalPath: string;
|
desktopGlobalPath: string;
|
||||||
@@ -263,28 +263,26 @@ export interface EnginInitDesktopConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeIQQNTWrapperEngine {
|
export interface NodeIQQNTWrapperEngine {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
get(): NodeIQQNTWrapperEngine;
|
||||||
new(): NodeIQQNTWrapperEngine;
|
|
||||||
|
|
||||||
initWithDeskTopConfig(config: EnginInitDesktopConfig, nodeIGlobalAdapter: NodeIGlobalAdapter): void;
|
initWithDeskTopConfig(config: EnginInitDesktopConfig, nodeIGlobalAdapter: NodeIGlobalAdapter): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WrapperNodeApi {
|
export interface WrapperNodeApi {
|
||||||
[key: string]: any;
|
NodeIO3MiscService: NodeIO3MiscService;
|
||||||
|
|
||||||
NodeQQNTWrapperUtil: NodeQQNTWrapperUtil;
|
NodeQQNTWrapperUtil: NodeQQNTWrapperUtil;
|
||||||
NodeIQQNTWrapperSession: NodeIQQNTWrapperSession;
|
NodeIQQNTWrapperSession: NodeIQQNTWrapperSession;
|
||||||
NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine;
|
NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine;
|
||||||
NodeIKernelLoginService: NodeIKernelLoginService;
|
NodeIKernelLoginService: NodeIKernelLoginService;
|
||||||
NodeIKernelProfileService: NodeIKernelProfileService;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
export enum PlatformType {
|
export enum PlatformType {
|
||||||
KUNKNOWN,
|
KUNKNOWN,
|
||||||
KANDROID,
|
KANDROID,
|
||||||
KIOS,
|
KIOS,
|
||||||
KWINDOWS,
|
KWINDOWS,
|
||||||
KMAC,
|
KMAC,
|
||||||
|
KLINUX
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DeviceType {
|
export enum DeviceType {
|
||||||
|
@@ -49,7 +49,7 @@ export async function NCoreInitFramework(
|
|||||||
const loaderObject = new NapCatFramework(wrapper, session, logger, loginService, selfInfo, basicInfoWrapper, pathWrapper);
|
const loaderObject = new NapCatFramework(wrapper, session, logger, loginService, selfInfo, basicInfoWrapper, pathWrapper);
|
||||||
|
|
||||||
//启动WebUi
|
//启动WebUi
|
||||||
InitWebUi(logger, pathWrapper).then().catch(logger.logError);
|
InitWebUi(logger, pathWrapper).then().catch(logger.logError.bind(logger));
|
||||||
//初始化LLNC的Onebot实现
|
//初始化LLNC的Onebot实现
|
||||||
new NapCatOneBot11Adapter(loaderObject.core, loaderObject.context, pathWrapper);
|
new NapCatOneBot11Adapter(loaderObject.core, loaderObject.context, pathWrapper);
|
||||||
}
|
}
|
||||||
|
@@ -46,7 +46,7 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
|
|||||||
const resData = await this._handle(payload);
|
const resData = await this._handle(payload);
|
||||||
return OB11Response.ok(resData);
|
return OB11Response.ok(resData);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.core.context.logger.logError('发生错误', e);
|
this.core.context.logger.logError.bind(this.core.context.logger)('发生错误', e);
|
||||||
return OB11Response.error(e?.toString() || e?.stack?.toString() || '未知错误,可能操作超时', 200);
|
return OB11Response.error(e?.toString() || e?.stack?.toString() || '未知错误,可能操作超时', 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
|
|||||||
const resData = await this._handle(payload);
|
const resData = await this._handle(payload);
|
||||||
return OB11Response.ok(resData, echo);
|
return OB11Response.ok(resData, echo);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.core.context.logger.logError('发生错误', e);
|
this.core.context.logger.logError.bind(this.core.context.logger)('发生错误', e);
|
||||||
return OB11Response.error(e.stack?.toString() || e.toString(), 1200, echo);
|
return OB11Response.error(e.stack?.toString() || e.toString(), 1200, echo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
src/onebot/action/extends/FetchUserProfileLike.ts
Normal file
11
src/onebot/action/extends/FetchUserProfileLike.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName } from '../types';
|
||||||
|
|
||||||
|
export class FetchUserProfileLike extends BaseAction<{ qq: number }, any> {
|
||||||
|
actionName = ActionName.FetchUserProfileLike;
|
||||||
|
|
||||||
|
async _handle(payload: { qq: number }) {
|
||||||
|
if (!payload.qq) throw new Error('qq is required');
|
||||||
|
return await this.core.apis.UserApi.getUidByUinV2(payload.qq.toString());
|
||||||
|
}
|
||||||
|
}
|
@@ -19,26 +19,21 @@ export class OCRImage extends BaseAction<Payload, any> {
|
|||||||
payloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.image));
|
const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.image));
|
||||||
if (!success) {
|
if (!success) {
|
||||||
throw `OCR ${payload.image}失败,image字段可能格式不正确`;
|
throw `OCR ${payload.image}失败,image字段可能格式不正确`;
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
||||||
const ret = await this.core.apis.SystemApi.ocrImage(path);
|
const ret = await this.core.apis.SystemApi.ocrImage(path);
|
||||||
if (!isLocal) {
|
fs.unlink(path, () => { });
|
||||||
fs.unlink(path, () => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
throw `OCR ${payload.file}失败`;
|
throw `OCR ${payload.file}失败`;
|
||||||
}
|
}
|
||||||
return ret.result;
|
return ret.result;
|
||||||
}
|
}
|
||||||
if (!isLocal) {
|
fs.unlink(path, () => { });
|
||||||
fs.unlink(path, () => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
throw `OCR ${payload.file}失败,文件可能不存在`;
|
throw `OCR ${payload.file}失败,文件可能不存在`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,17 +24,16 @@ export default class SetAvatar extends BaseAction<Payload, null> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<null> {
|
async _handle(payload: Payload): Promise<null> {
|
||||||
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
|
const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
|
||||||
if (!success) {
|
if (!success) {
|
||||||
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
||||||
const ret = await this.core.apis.UserApi.setQQAvatar(path);
|
const ret = await this.core.apis.UserApi.setQQAvatar(path);
|
||||||
if (!isLocal) {
|
fs.unlink(path, () => {
|
||||||
fs.unlink(path, () => {
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
throw `头像${payload.file}设置失败,api无返回`;
|
throw `头像${payload.file}设置失败,api无返回`;
|
||||||
}
|
}
|
||||||
@@ -45,10 +44,8 @@ export default class SetAvatar extends BaseAction<Payload, null> {
|
|||||||
throw `头像${payload.file}设置失败,未知的错误,${ret['result']}:${ret['errMsg']}`;
|
throw `头像${payload.file}设置失败,未知的错误,${ret['result']}:${ret['errMsg']}`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!isLocal) {
|
fs.unlink(path, () => { });
|
||||||
fs.unlink(path, () => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`;
|
throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@@ -7,17 +7,18 @@ const SchemaData = {
|
|||||||
properties: {
|
properties: {
|
||||||
group_id: { type: ['string', 'number'] },
|
group_id: { type: ['string', 'number'] },
|
||||||
folder_id: { type: 'string' },
|
folder_id: { type: 'string' },
|
||||||
|
folder: { type: 'string' }
|
||||||
},
|
},
|
||||||
required: ['group_id', 'folder_id'],
|
required: ['group_id'],
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
type Payload = FromSchema<typeof SchemaData>;
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
export class DeleteGroupFileFolder extends BaseAction<Payload, any> {
|
export class DeleteGroupFileFolder extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder;
|
actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder;
|
||||||
payloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
return (await this.core.apis.GroupApi.DelGroupFileFolder(
|
return (await this.core.apis.GroupApi.DelGroupFileFolder(
|
||||||
payload.group_id.toString(), payload.folder_id)).groupFileCommonResult;
|
payload.group_id.toString(), payload.folder ?? payload.folder_id ?? '')).groupFileCommonResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -73,7 +73,7 @@ export default class GoCQHTTPDownloadFile extends BaseAction<Payload, FileRespon
|
|||||||
headers[headerItem] = '';
|
headers[headerItem] = '';
|
||||||
} else {
|
} else {
|
||||||
const key = headerItem.substring(0, spilt);
|
const key = headerItem.substring(0, spilt);
|
||||||
headers[key] = headerItem.substring(0, spilt + 1);
|
headers[key] = headerItem.substring(spilt + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,9 +8,10 @@ const SchemaData = {
|
|||||||
properties: {
|
properties: {
|
||||||
group_id: { type: ['string', 'number'] },
|
group_id: { type: ['string', 'number'] },
|
||||||
folder_id: { type: 'string' },
|
folder_id: { type: 'string' },
|
||||||
|
folder: { type: 'string' },
|
||||||
file_count: { type: ['string', 'number'] },
|
file_count: { type: ['string', 'number'] },
|
||||||
},
|
},
|
||||||
required: ['group_id', 'folder_id'],
|
required: ['group_id'],
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
type Payload = FromSchema<typeof SchemaData>;
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
@@ -26,7 +27,7 @@ export class GetGroupFilesByFolder extends BaseAction<any, any> {
|
|||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
sortOrder: 2,
|
sortOrder: 2,
|
||||||
showOnlinedocFolder: 0,
|
showOnlinedocFolder: 0,
|
||||||
folderId: payload.folder_id,
|
folderId: payload.folder ?? payload.folder_id ?? '',
|
||||||
}).catch(() => []);
|
}).catch(() => []);
|
||||||
return {
|
return {
|
||||||
files: ret.filter(item => item.fileInfo)
|
files: ret.filter(item => item.fileInfo)
|
||||||
|
@@ -20,25 +20,26 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
|
|||||||
|
|
||||||
async _handle(payload: Payload): Promise<OB11User> {
|
async _handle(payload: Payload): Promise<OB11User> {
|
||||||
const user_id = payload.user_id.toString();
|
const user_id = payload.user_id.toString();
|
||||||
const extendData = await this.core.apis.UserApi.getUserDetailInfoByUinV2(user_id);
|
const extendData = await this.core.apis.UserApi.getUserDetailInfoByUin(user_id);
|
||||||
const uid = (await this.core.apis.UserApi.getUidByUinV2(user_id))!;
|
let uid = (await this.core.apis.UserApi.getUidByUinV2(user_id));
|
||||||
if (!uid || uid.indexOf('*') != -1) {
|
if (!uid) uid = extendData.detail.uid;
|
||||||
return {
|
const info = (await this.core.apis.UserApi.getUserDetailInfo(uid));
|
||||||
...extendData.detail.simpleInfo.coreInfo,
|
return {
|
||||||
...extendData.detail.commonExt,
|
user_id: parseInt(extendData.detail.uin) ?? 0,
|
||||||
...extendData.detail.simpleInfo.baseInfo,
|
uid: info.uid ?? uid,
|
||||||
...extendData.detail.simpleInfo.relationFlags,
|
nickname: extendData.detail.simpleInfo.coreInfo.nick,
|
||||||
...extendData.detail.simpleInfo.status,
|
age: extendData.detail.simpleInfo.baseInfo.age ?? info.age,
|
||||||
user_id: parseInt(extendData.detail.uin) || 0,
|
qid: extendData.detail.simpleInfo.baseInfo.qid,
|
||||||
nickname: extendData.detail.simpleInfo.coreInfo.nick,
|
qqLevel: calcQQLevel(extendData.detail.commonExt?.qqLevel ?? info.qqLevel),
|
||||||
sex: OB11UserSex.unknown,
|
sex: OB11Entities.sex(extendData.detail.simpleInfo.baseInfo.sex) ?? OB11UserSex.unknown,
|
||||||
age: extendData.detail.simpleInfo.baseInfo.age || 0,
|
long_nick: extendData.detail.simpleInfo.baseInfo.longNick ?? info.longNick,
|
||||||
qid: extendData.detail.simpleInfo.baseInfo.qid,
|
reg_time: extendData.detail.commonExt.regTime ?? info.regTime,
|
||||||
level: calcQQLevel(extendData.detail.commonExt?.qqLevel ?? 0) || 0,
|
is_vip: extendData.detail.simpleInfo.vasInfo?.svipFlag,
|
||||||
login_days: 0,
|
is_years_vip: extendData.detail.simpleInfo.vasInfo?.yearVipFlag,
|
||||||
};
|
vip_level: extendData.detail.simpleInfo.vasInfo?.vipLevel,
|
||||||
}
|
remark: extendData.detail.simpleInfo.coreInfo.remark ?? info.remark,
|
||||||
const data = { ...extendData, ...(await this.core.apis.UserApi.getUserDetailInfo(uid)) };
|
status: extendData.detail.simpleInfo.status?.status ?? info.status,
|
||||||
return OB11Entities.stranger(data);
|
login_days: 0,//失效
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,6 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
|||||||
//公告图逻辑
|
//公告图逻辑
|
||||||
const {
|
const {
|
||||||
path,
|
path,
|
||||||
isLocal,
|
|
||||||
success,
|
success,
|
||||||
} = (await uri2local(this.core.NapCatTempPath, payload.image));
|
} = (await uri2local(this.core.NapCatTempPath, payload.image));
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@@ -45,10 +44,10 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
|||||||
if (ImageUploadResult.errCode != 0) {
|
if (ImageUploadResult.errCode != 0) {
|
||||||
throw `群公告${payload.image}设置失败,图片上传失败`;
|
throw `群公告${payload.image}设置失败,图片上传失败`;
|
||||||
}
|
}
|
||||||
if (!isLocal) {
|
|
||||||
unlink(path, () => {
|
unlink(path, () => {
|
||||||
});
|
});
|
||||||
}
|
|
||||||
UploadImage = ImageUploadResult.picInfo;
|
UploadImage = ImageUploadResult.picInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +57,6 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
|||||||
const noticeShowEditCard = +(payload.is_show_edit_card ?? 0);
|
const noticeShowEditCard = +(payload.is_show_edit_card ?? 0);
|
||||||
const noticeTipWindowType = +(payload.tip_window_type ?? 0);
|
const noticeTipWindowType = +(payload.tip_window_type ?? 0);
|
||||||
const noticeConfirmRequired = +(payload.confirm_required ?? 1);
|
const noticeConfirmRequired = +(payload.confirm_required ?? 1);
|
||||||
//const publishGroupBulletinResult = await this.core.apis.GroupApi.publishGroupBulletin(payload.group_id.toString(), payload.content, UploadImage, noticePinned, noticeConfirmRequired);
|
|
||||||
const publishGroupBulletinResult = await this.core.apis.WebApi.setGroupNotice(
|
const publishGroupBulletinResult = await this.core.apis.WebApi.setGroupNotice(
|
||||||
payload.group_id.toString(),
|
payload.group_id.toString(),
|
||||||
payload.content,
|
payload.content,
|
||||||
@@ -72,7 +70,7 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
|||||||
UploadImage?.height
|
UploadImage?.height
|
||||||
);
|
);
|
||||||
if (!publishGroupBulletinResult || publishGroupBulletinResult.ec != 0) {
|
if (!publishGroupBulletinResult || publishGroupBulletinResult.ec != 0) {
|
||||||
throw `设置群公告失败,错误信息:${publishGroupBulletinResult?.em}`;
|
throw new Error(`设置群公告失败,错误信息:${publishGroupBulletinResult?.em}`);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -25,17 +25,14 @@ export default class SetGroupPortrait extends BaseAction<Payload, any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<any> {
|
async _handle(payload: Payload): Promise<any> {
|
||||||
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
|
const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
|
||||||
if (!success) {
|
if (!success) {
|
||||||
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
||||||
const ret = await this.core.apis.GroupApi.setGroupAvatar(payload.group_id.toString(), path) as any;
|
const ret = await this.core.apis.GroupApi.setGroupAvatar(payload.group_id.toString(), path) as any;
|
||||||
if (!isLocal) {
|
fs.unlink(path, () => { });
|
||||||
fs.unlink(path, () => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
throw `头像${payload.file}设置失败,api无返回`;
|
throw `头像${payload.file}设置失败,api无返回`;
|
||||||
}
|
}
|
||||||
@@ -46,10 +43,7 @@ export default class SetGroupPortrait extends BaseAction<Payload, any> {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
if (!isLocal) {
|
fs.unlink(path, () => {});
|
||||||
fs.unlink(path, () => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`;
|
throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { ChatType } from '@/core/entities';
|
import { ChatType, Peer } from '@/core/entities';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { uri2local } from '@/common/file';
|
import { uri2local } from '@/common/file';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { MessageContext } from '@/onebot/api';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -29,14 +30,19 @@ export default class GoCQHTTPUploadGroupFile extends BaseAction<Payload, null> {
|
|||||||
file = `file://${file}`;
|
file = `file://${file}`;
|
||||||
}
|
}
|
||||||
const downloadResult = await uri2local(this.core.NapCatTempPath, file);
|
const downloadResult = await uri2local(this.core.NapCatTempPath, file);
|
||||||
|
const peer: Peer = {
|
||||||
|
chatType: ChatType.KCHATTYPEGROUP,
|
||||||
|
peerUid: payload.group_id.toString(),
|
||||||
|
};
|
||||||
if (!downloadResult.success) {
|
if (!downloadResult.success) {
|
||||||
throw new Error(downloadResult.errMsg);
|
throw new Error(downloadResult.errMsg);
|
||||||
}
|
}
|
||||||
const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name, payload.folder_id);
|
const msgContext: MessageContext = {
|
||||||
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId({
|
peer: peer,
|
||||||
chatType: ChatType.KCHATTYPEGROUP,
|
deleteAfterSentFiles: []
|
||||||
peerUid: payload.group_id.toString(),
|
};
|
||||||
}, [sendFileEle], [], true);
|
const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name, payload.folder ?? payload.folder_id);
|
||||||
|
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, [sendFileEle], [], true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,8 @@ import { ChatType, Peer, SendFileElement } from '@/core/entities';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { uri2local } from '@/common/file';
|
import { uri2local } from '@/common/file';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { MessageContext } from '@/onebot/api';
|
||||||
|
import { ContextMode, createContext } from '../msg/SendMsg';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -42,7 +44,15 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
|
|||||||
if (!downloadResult.success) {
|
if (!downloadResult.success) {
|
||||||
throw new Error(downloadResult.errMsg);
|
throw new Error(downloadResult.errMsg);
|
||||||
}
|
}
|
||||||
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name);
|
|
||||||
|
const msgContext: MessageContext = {
|
||||||
|
peer: await createContext(this.core, {
|
||||||
|
user_id: payload.user_id.toString(),
|
||||||
|
group_id: undefined,
|
||||||
|
}, ContextMode.Private),
|
||||||
|
deleteAfterSentFiles: []
|
||||||
|
};
|
||||||
|
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name);
|
||||||
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(await this.getPeer(payload), [sendFileEle], [], true);
|
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(await this.getPeer(payload), [sendFileEle], [], true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -51,7 +51,7 @@ export class GetGroupEssence extends BaseAction<Payload, any> {
|
|||||||
operator_nick: msg.add_digest_nick,
|
operator_nick: msg.add_digest_nick,
|
||||||
message_id: message_id,
|
message_id: message_id,
|
||||||
operator_time: msg.add_digest_time,
|
operator_time: msg.add_digest_time,
|
||||||
content: (await this.obContext.apis.MsgApi.parseMessage(rawMessage, 'array'))?.message
|
content: (await this.obContext.apis.MsgApi.parseMessage(rawMessage))?.message
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const msgTempData = JSON.stringify({
|
const msgTempData = JSON.stringify({
|
||||||
|
@@ -20,7 +20,17 @@ class GetGroupInfo extends BaseAction<Payload, OB11Group> {
|
|||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const group = (await this.core.apis.GroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString());
|
const group = (await this.core.apis.GroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString());
|
||||||
if (!group) throw `群${payload.group_id}不存在`;
|
if (!group) {
|
||||||
|
const data = await this.core.apis.GroupApi.searchGroup(payload.group_id.toString());
|
||||||
|
if (!data) throw new Error('Group not found');
|
||||||
|
return {
|
||||||
|
...data.searchGroupInfo,
|
||||||
|
group_id: +payload.group_id,
|
||||||
|
group_name: data.searchGroupInfo.groupName,
|
||||||
|
member_count: data.searchGroupInfo.memberNum,
|
||||||
|
max_member_count: data.searchGroupInfo.maxMemberNum,
|
||||||
|
};
|
||||||
|
}
|
||||||
return OB11Entities.group(group);
|
return OB11Entities.group(group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ import { OB11Entities } from '@/onebot/entities';
|
|||||||
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 { calcQQLevel } from '@/common/helper';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -22,7 +23,8 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
|
|||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const groupMembers = await this.core.apis.GroupApi.getGroupMembersV2(payload.group_id.toString());
|
const groupMembers = await this.core.apis.GroupApi.getGroupMembersV2(payload.group_id.toString());
|
||||||
const groupMembersArr = Array.from(groupMembers.values());
|
const groupMembersArr = Array.from(groupMembers.values());
|
||||||
|
const uids = groupMembersArr.map(item => item.uid);
|
||||||
|
//let CoreAndBase = await this.core.apis.GroupApi.getCoreAndBaseInfo(uids)
|
||||||
let _groupMembers = groupMembersArr.map(item => {
|
let _groupMembers = groupMembersArr.map(item => {
|
||||||
return OB11Entities.groupMember(payload.group_id.toString(), item);
|
return OB11Entities.groupMember(payload.group_id.toString(), item);
|
||||||
});
|
});
|
||||||
@@ -32,34 +34,38 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
|
|||||||
|
|
||||||
for (let i = 0, len = _groupMembers.length; i < len; i++) {
|
for (let i = 0, len = _groupMembers.length; i < len; i++) {
|
||||||
// 保证基础数据有这个 同时避免群管插件过于依赖这个杀了
|
// 保证基础数据有这个 同时避免群管插件过于依赖这个杀了
|
||||||
_groupMembers[i].join_time = date;
|
const Member = await this.core.apis.GroupApi.getGroupMember(payload.group_id.toString(), _groupMembers[i].user_id);
|
||||||
_groupMembers[i].last_sent_time = date;
|
_groupMembers[i].join_time = +(Member?.joinTime ?? date);
|
||||||
|
_groupMembers[i].last_sent_time = +(Member?.lastSpeakTime ?? date);
|
||||||
MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]);
|
MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const selfRole = groupMembers.get(this.core.selfInfo.uid)?.role;
|
const selfRole = groupMembers.get(this.core.selfInfo.uid)?.role;
|
||||||
const isPrivilege = selfRole === 3 || selfRole === 4;
|
const isPrivilege = selfRole === 3 || selfRole === 4;
|
||||||
|
|
||||||
_groupMembers.forEach(item => {
|
|
||||||
item.last_sent_time = date;
|
|
||||||
item.join_time = date;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isPrivilege) {
|
if (isPrivilege) {
|
||||||
const webGroupMembers = await this.core.apis.WebApi.getGroupMembers(payload.group_id.toString());
|
try {
|
||||||
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
const webGroupMembers = await this.core.apis.WebApi.getGroupMembers(payload.group_id.toString());
|
||||||
if (!webGroupMembers[i]?.uin) {
|
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
||||||
continue;
|
if (!webGroupMembers[i]?.uin) {
|
||||||
}
|
continue;
|
||||||
const MemberData = MemberMap.get(webGroupMembers[i]?.uin);
|
}
|
||||||
if (MemberData) {
|
const MemberData = MemberMap.get(webGroupMembers[i]?.uin);
|
||||||
MemberData.join_time = webGroupMembers[i]?.join_time;
|
if (MemberData) {
|
||||||
MemberData.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
MemberData.join_time = webGroupMembers[i]?.join_time;
|
||||||
MemberData.qage = webGroupMembers[i]?.qage;
|
MemberData.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
||||||
MemberData.level = webGroupMembers[i]?.lv.level.toString();
|
MemberData.qage = webGroupMembers[i]?.qage;
|
||||||
MemberMap.set(webGroupMembers[i]?.uin, MemberData);
|
MemberData.level = webGroupMembers[i]?.lv.level.toString();
|
||||||
|
MemberMap.set(webGroupMembers[i]?.uin, MemberData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
const logger = this.core.context.logger;
|
||||||
|
logger.logError.bind(logger)('GetGroupMemberList', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_groupMembers = Array.from(MemberMap.values());
|
_groupMembers = Array.from(MemberMap.values());
|
||||||
|
@@ -68,8 +68,8 @@ import SetGroupPortrait from './go-cqhttp/SetGroupPortrait';
|
|||||||
import { FetchCustomFace } from './extends/FetchCustomFace';
|
import { FetchCustomFace } from './extends/FetchCustomFace';
|
||||||
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivateFile';
|
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivateFile';
|
||||||
import { FetchEmojiLike } from './extends/FetchEmojiLike';
|
import { FetchEmojiLike } from './extends/FetchEmojiLike';
|
||||||
|
import { FetchUserProfileLike } from './extends/FetchUserProfileLike';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
|
|
||||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||||
import GetGuildProfile from './guild/GetGuildProfile';
|
import GetGuildProfile from './guild/GetGuildProfile';
|
||||||
import SetModelShow from './go-cqhttp/SetModelShow';
|
import SetModelShow from './go-cqhttp/SetModelShow';
|
||||||
@@ -83,6 +83,8 @@ import { DeleteGroupFileFolder } from '@/onebot/action/go-cqhttp/DeleteGroupFile
|
|||||||
import { GetGroupFileSystemInfo } from '@/onebot/action/go-cqhttp/GetGroupFileSystemInfo';
|
import { GetGroupFileSystemInfo } from '@/onebot/action/go-cqhttp/GetGroupFileSystemInfo';
|
||||||
import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
|
import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
|
||||||
import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesByFolder';
|
import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesByFolder';
|
||||||
|
import { GetGroupSystemMsg } from './system/GetSystemMsg';
|
||||||
|
|
||||||
|
|
||||||
export type ActionMap = Map<string, BaseAction<any, any>>;
|
export type ActionMap = Map<string, BaseAction<any, any>>;
|
||||||
|
|
||||||
@@ -176,6 +178,8 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
|
|||||||
new DeleteGroupFileFolder(obContext, core),
|
new DeleteGroupFileFolder(obContext, core),
|
||||||
new GetGroupFileSystemInfo(obContext, core),
|
new GetGroupFileSystemInfo(obContext, core),
|
||||||
new GetGroupFilesByFolder(obContext, core),
|
new GetGroupFilesByFolder(obContext, core),
|
||||||
|
new GetGroupSystemMsg(obContext, core),
|
||||||
|
new FetchUserProfileLike(obContext, core),
|
||||||
];
|
];
|
||||||
const actionMap = new Map();
|
const actionMap = new Map();
|
||||||
for (const action of actionHandlers) {
|
for (const action of actionHandlers) {
|
||||||
|
@@ -35,7 +35,7 @@ class GetMsg extends BaseAction<Payload, OB11Message> {
|
|||||||
const msg = await this.core.apis.MsgApi.getMsgsByMsgId(
|
const msg = await this.core.apis.MsgApi.getMsgsByMsgId(
|
||||||
peer,
|
peer,
|
||||||
[msgIdWithPeer?.MsgId || payload.message_id.toString()]);
|
[msgIdWithPeer?.MsgId || payload.message_id.toString()]);
|
||||||
const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg.msgList[0], 'array');
|
const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg.msgList[0]);
|
||||||
if (!retMsg) throw Error('消息为空');
|
if (!retMsg) throw Error('消息为空');
|
||||||
try {
|
try {
|
||||||
retMsg.message_id = MessageUnique.createUniqueMsgId(peer, msg.msgList[0].msgId)!;
|
retMsg.message_id = MessageUnique.createUniqueMsgId(peer, msg.msgList[0].msgId)!;
|
||||||
|
@@ -3,6 +3,7 @@ import {
|
|||||||
OB11MessageDataType,
|
OB11MessageDataType,
|
||||||
OB11MessageMixType,
|
OB11MessageMixType,
|
||||||
OB11MessageNode,
|
OB11MessageNode,
|
||||||
|
OB11PostContext,
|
||||||
OB11PostSendMsg,
|
OB11PostSendMsg,
|
||||||
} from '@/onebot/types';
|
} from '@/onebot/types';
|
||||||
import { ActionName, BaseCheckResult } from '@/onebot/action/types';
|
import { ActionName, BaseCheckResult } from '@/onebot/action/types';
|
||||||
@@ -30,7 +31,7 @@ export function normalize(message: OB11MessageMixType, autoEscape = false): OB11
|
|||||||
) : Array.isArray(message) ? message : [message];
|
) : Array.isArray(message) ? message : [message];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createContext(core: NapCatCore, payload: OB11PostSendMsg, contextMode: ContextMode): Promise<Peer> {
|
export async function createContext(core: NapCatCore, payload: OB11PostContext, contextMode: ContextMode): Promise<Peer> {
|
||||||
// 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.
|
||||||
@@ -148,7 +149,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
//对Mgsid和OB11ID混用情况兜底
|
//对Mgsid和OB11ID混用情况兜底
|
||||||
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
|
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
|
||||||
if (!nodeMsg) {
|
if (!nodeMsg) {
|
||||||
logger.logError('转发消息失败,未找到消息', nodeId);
|
logger.logError.bind(this.core.context.logger)('转发消息失败,未找到消息', nodeId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nodeMsgIds.push(nodeMsg.MsgId);
|
nodeMsgIds.push(nodeMsg.MsgId);
|
||||||
@@ -160,7 +161,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
const isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息
|
const isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息
|
||||||
if (isNodeMsg !== 0) {
|
if (isNodeMsg !== 0) {
|
||||||
if (isNodeMsg !== OB11Data.length) {
|
if (isNodeMsg !== OB11Data.length) {
|
||||||
logger.logError('子消息中包含非node消息 跳过不合法部分');
|
logger.logError.bind(this.core.context.logger)('子消息中包含非node消息 跳过不合法部分');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
||||||
@@ -208,7 +209,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
for (const msgId of nodeMsgIds) {
|
for (const msgId of nodeMsgIds) {
|
||||||
const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId);
|
const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId);
|
||||||
if (!nodeMsgPeer) {
|
if (!nodeMsgPeer) {
|
||||||
logger.logError('转发消息失败,未找到消息', msgId);
|
logger.logError.bind(this.core.context.logger)('转发消息失败,未找到消息', msgId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const nodeMsg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
|
const nodeMsg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
|
||||||
@@ -237,7 +238,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
|
logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
|
||||||
return await this.core.apis.MsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds);
|
return await this.core.apis.MsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.logError('forward failed', e);
|
logger.logError.bind(this.core.context.logger)('forward failed', e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,7 +262,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
try {
|
try {
|
||||||
return await this.core.apis.MsgApi.sendMsg(selfPeer, sendElements, true);
|
return await this.core.apis.MsgApi.sendMsg(selfPeer, sendElements, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.logError(e, '克隆转发消息失败,将忽略本条消息', msg);
|
logger.logError.bind(this.core.context.logger)(e, '克隆转发消息失败,将忽略本条消息', msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
50
src/onebot/action/system/GetSystemMsg.ts
Normal file
50
src/onebot/action/system/GetSystemMsg.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { GroupNotifyMsgStatus } from '@/core';
|
||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName } from '../types';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
group_id: { type: ['number', 'string'] },
|
||||||
|
},
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export class GetGroupSystemMsg extends BaseAction<void, any> {
|
||||||
|
actionName = ActionName.GetGroupSystemMsg;
|
||||||
|
|
||||||
|
async _handle(payload: void) {
|
||||||
|
const NTQQUserApi = this.core.apis.UserApi;
|
||||||
|
const NTQQGroupApi = this.core.apis.GroupApi;
|
||||||
|
// 默认10条 该api未完整实现 包括响应数据规范化 类型规范化
|
||||||
|
const SingleScreenNotifies = await NTQQGroupApi.getSingleScreenNotifies(false,10);
|
||||||
|
const retData: any = { InvitedRequest: [], join_requests: [] };
|
||||||
|
for (const SSNotify of SingleScreenNotifies) {
|
||||||
|
if (SSNotify.type == 1) {
|
||||||
|
retData.InvitedRequest.push({
|
||||||
|
request_id: SSNotify.seq,
|
||||||
|
invitor_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid),
|
||||||
|
invitor_nick: SSNotify.user1?.nickName,
|
||||||
|
group_id: SSNotify.group?.groupCode,
|
||||||
|
group_name: SSNotify.group?.groupName,
|
||||||
|
checked: SSNotify.status === GroupNotifyMsgStatus.KUNHANDLE ? false : true,
|
||||||
|
actor: await NTQQUserApi.getUinByUidV2(SSNotify.user2?.uid) || 0,
|
||||||
|
});
|
||||||
|
} else if (SSNotify.type == 7) {
|
||||||
|
retData.join_requests.push({
|
||||||
|
request_id: SSNotify.seq,
|
||||||
|
requester_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid),
|
||||||
|
requester_nick: SSNotify.user1?.nickName,
|
||||||
|
group_id: SSNotify.group?.groupCode,
|
||||||
|
group_name: SSNotify.group?.groupName,
|
||||||
|
checked: SSNotify.status === GroupNotifyMsgStatus.KUNHANDLE ? false : true,
|
||||||
|
actor: await NTQQUserApi.getUinByUidV2(SSNotify.user2?.uid) || 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retData;
|
||||||
|
}
|
||||||
|
}
|
@@ -16,8 +16,8 @@ export interface InvalidCheckResult {
|
|||||||
export enum ActionName {
|
export enum ActionName {
|
||||||
// 以下为扩展napcat扩展
|
// 以下为扩展napcat扩展
|
||||||
Unknown = 'unknown',
|
Unknown = 'unknown',
|
||||||
SharePeer = 'ArkShareGroup',
|
SharePeer = 'ArkSharePeer',
|
||||||
ShareGroupEx = 'ArkSharePeer',
|
ShareGroupEx = 'ArkShareGroup',
|
||||||
RebootNormal = 'reboot_normal',//无快速登录重新启动
|
RebootNormal = 'reboot_normal',//无快速登录重新启动
|
||||||
GetRobotUinRange = 'get_robot_uin_range',
|
GetRobotUinRange = 'get_robot_uin_range',
|
||||||
SetOnlineStatus = 'set_online_status',
|
SetOnlineStatus = 'set_online_status',
|
||||||
@@ -116,5 +116,7 @@ export enum ActionName {
|
|||||||
SetInputStatus = 'set_input_status',
|
SetInputStatus = 'set_input_status',
|
||||||
GetCSRF = 'get_csrf_token',
|
GetCSRF = 'get_csrf_token',
|
||||||
DelGroupNotice = '_del_group_notice',
|
DelGroupNotice = '_del_group_notice',
|
||||||
GetGroupInfoEx = "get_group_info_ex"
|
GetGroupInfoEx = "get_group_info_ex",
|
||||||
|
GetGroupSystemMsg = 'get_group_system_msg',
|
||||||
|
FetchUserProfileLike = "fetch_user_profile_like",
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ export default class GetRecentContact extends BaseAction<Payload, any> {
|
|||||||
const FastMsg = await this.core.apis.MsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]);
|
const FastMsg = await this.core.apis.MsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]);
|
||||||
if (FastMsg.msgList.length > 0) {
|
if (FastMsg.msgList.length > 0) {
|
||||||
//扩展ret.info.changedList
|
//扩展ret.info.changedList
|
||||||
const lastestMsg = await this.obContext.apis.MsgApi.parseMessage(FastMsg.msgList[0], 'array');
|
const lastestMsg = await this.obContext.apis.MsgApi.parseMessage(FastMsg.msgList[0]);
|
||||||
return {
|
return {
|
||||||
lastestMsg: lastestMsg,
|
lastestMsg: lastestMsg,
|
||||||
peerUin: t.peerUin,
|
peerUin: t.peerUin,
|
||||||
|
@@ -19,6 +19,7 @@ import { OB11GroupPokeEvent } from '@/onebot/event/notice/OB11PokeEvent';
|
|||||||
import { OB11GroupEssenceEvent } from '@/onebot/event/notice/OB11GroupEssenceEvent';
|
import { OB11GroupEssenceEvent } from '@/onebot/event/notice/OB11GroupEssenceEvent';
|
||||||
import { OB11GroupTitleEvent } from '@/onebot/event/notice/OB11GroupTitleEvent';
|
import { OB11GroupTitleEvent } from '@/onebot/event/notice/OB11GroupTitleEvent';
|
||||||
import { FileNapCatOneBotUUID } from '@/common/helper';
|
import { FileNapCatOneBotUUID } from '@/common/helper';
|
||||||
|
import { pathToFileURL } from 'node:url';
|
||||||
|
|
||||||
export class OneBotGroupApi {
|
export class OneBotGroupApi {
|
||||||
obContext: NapCatOneBot11Adapter;
|
obContext: NapCatOneBot11Adapter;
|
||||||
@@ -77,7 +78,8 @@ export class OneBotGroupApi {
|
|||||||
id: FileNapCatOneBotUUID.encode({
|
id: FileNapCatOneBotUUID.encode({
|
||||||
chatType: ChatType.KCHATTYPEGROUP,
|
chatType: ChatType.KCHATTYPEGROUP,
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
}, msg.msgId, element.elementId, element.fileElement.fileName),
|
}, msg.msgId, element.elementId, "." + element.fileElement.fileName),
|
||||||
|
url: pathToFileURL(element.fileElement.filePath).href,
|
||||||
name: element.fileElement.fileName,
|
name: element.fileElement.fileName,
|
||||||
size: parseInt(element.fileElement.fileSize),
|
size: parseInt(element.fileElement.fileSize),
|
||||||
busid: element.fileElement.fileBizId || 0,
|
busid: element.fileElement.fileBizId || 0,
|
||||||
@@ -138,15 +140,25 @@ export class OneBotGroupApi {
|
|||||||
}
|
}
|
||||||
if (element.grayTipElement.jsonGrayTipElement.busiId == 2407) {
|
if (element.grayTipElement.jsonGrayTipElement.busiId == 2407) {
|
||||||
//下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE
|
//下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE
|
||||||
const memberUin = json.items[1].param[0];
|
const type = json.items[json.items.length - 1]?.txt;
|
||||||
const title = json.items[3].txt;
|
switch (type) {
|
||||||
logger.logDebug('收到群成员新头衔消息', json);
|
case "头衔": {
|
||||||
return new OB11GroupTitleEvent(
|
const memberUin = json.items[1].param[0];
|
||||||
this.core,
|
const title = json.items[3].txt;
|
||||||
parseInt(msg.peerUid),
|
logger.logDebug('收到群成员新头衔消息', json);
|
||||||
parseInt(memberUin),
|
return new OB11GroupTitleEvent(
|
||||||
title,
|
this.core,
|
||||||
);
|
parseInt(msg.peerUid),
|
||||||
|
parseInt(memberUin),
|
||||||
|
title,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case "移出":
|
||||||
|
logger.logDebug('收到机器人被踢消息', json);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
logger.logWarn('收到未知的灰条消息', json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,7 +289,7 @@ export class OneBotGroupApi {
|
|||||||
}
|
}
|
||||||
const replyMsg = replyMsgList[0];
|
const replyMsg = replyMsgList[0];
|
||||||
if (!replyMsg) {
|
if (!replyMsg) {
|
||||||
this.core.context.logger.logError('解析表情回应消息失败: 未找到回应消息');
|
this.core.context.logger.logError.bind(this.core.context.logger)('解析表情回应消息失败: 未找到回应消息');
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return new OB11GroupMsgEmojiLikeEvent(
|
return new OB11GroupMsgEmojiLikeEvent(
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { FileNapCatOneBotUUID } from '@/common/helper';
|
import { FileNapCatOneBotUUID } from '@/common/helper';
|
||||||
import { MessageUnique } from '@/common/message-unique';
|
import { MessageUnique } from '@/common/message-unique';
|
||||||
|
import { pathToFileURL } from 'node:url';
|
||||||
import {
|
import {
|
||||||
AtType,
|
AtType,
|
||||||
ChatType,
|
ChatType,
|
||||||
@@ -33,6 +34,7 @@ import { RequestUtil } from '@/common/request';
|
|||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import fsPromise from 'node:fs/promises';
|
import fsPromise from 'node:fs/promises';
|
||||||
import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent';
|
import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent';
|
||||||
|
import { SysMessage, SysMessageType } from '@/core/proto/ProfileLike';
|
||||||
|
|
||||||
type RawToOb11Converters = {
|
type RawToOb11Converters = {
|
||||||
[Key in keyof MessageElement as Key extends `${string}Element` ? Key : never]: (
|
[Key in keyof MessageElement as Key extends `${string}Element` ? Key : never]: (
|
||||||
@@ -106,7 +108,7 @@ export class OneBotMsgApi {
|
|||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
guildId: '',
|
guildId: '',
|
||||||
};
|
};
|
||||||
const encodedFileId = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, element.fileName);
|
const encodedFileId = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + element.fileName);
|
||||||
return {
|
return {
|
||||||
type: OB11MessageDataType.image,
|
type: OB11MessageDataType.image,
|
||||||
data: {
|
data: {
|
||||||
@@ -114,12 +116,13 @@ export class OneBotMsgApi {
|
|||||||
sub_type: element.picSubType,
|
sub_type: element.picSubType,
|
||||||
file_id: encodedFileId,
|
file_id: encodedFileId,
|
||||||
url: await this.core.apis.FileApi.getImageUrl(element),
|
url: await this.core.apis.FileApi.getImageUrl(element),
|
||||||
|
path: element.filePath,
|
||||||
file_size: element.fileSize,
|
file_size: element.fileSize,
|
||||||
file_unique: element.fileName
|
file_unique: element.fileName
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.core.context.logger.logError('获取图片url失败', e.stack);
|
this.core.context.logger.logError.bind(this.core.context.logger)('获取图片url失败', e.stack);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -135,8 +138,8 @@ export class OneBotMsgApi {
|
|||||||
data: {
|
data: {
|
||||||
file: element.fileName,
|
file: element.fileName,
|
||||||
path: element.filePath,
|
path: element.filePath,
|
||||||
url: element.filePath,
|
url: pathToFileURL(element.filePath).href,
|
||||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, element.fileName),
|
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + element.fileName),
|
||||||
file_size: element.fileSize,
|
file_size: element.fileSize,
|
||||||
file_unique: element.fileName,
|
file_unique: element.fileName,
|
||||||
},
|
},
|
||||||
@@ -175,13 +178,16 @@ export class OneBotMsgApi {
|
|||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
guildId: '',
|
guildId: '',
|
||||||
};
|
};
|
||||||
|
const { emojiId } = _;
|
||||||
|
const dir = emojiId.substring(0, 2);
|
||||||
|
const url = `https://gxh.vip.qq.com/club/item/parcel/item/${dir}/${emojiId}/raw300.gif`;
|
||||||
return {
|
return {
|
||||||
type: OB11MessageDataType.image,
|
type: OB11MessageDataType.image,
|
||||||
data: {
|
data: {
|
||||||
file: 'marketface',
|
file: 'marketface',
|
||||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, ".jpg"),
|
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + _.key + ".jpg"),
|
||||||
path: elementWrapper.elementId,
|
path: url,
|
||||||
url: elementWrapper.elementId,
|
url: url,
|
||||||
file_unique: _.key
|
file_unique: _.key
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -195,7 +201,7 @@ export class OneBotMsgApi {
|
|||||||
guildId: '',
|
guildId: '',
|
||||||
};
|
};
|
||||||
if (!records || !element.replyMsgTime || !element.senderUidStr) {
|
if (!records || !element.replyMsgTime || !element.senderUidStr) {
|
||||||
this.core.context.logger.logError('获取不到引用的消息', element.replayMsgSeq);
|
this.core.context.logger.logError.bind(this.core.context.logger)('获取不到引用的消息', element.replayMsgSeq);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +219,7 @@ export class OneBotMsgApi {
|
|||||||
.msgList.find(msg => msg.msgRandom === records.msgRandom);
|
.msgList.find(msg => msg.msgRandom === records.msgRandom);
|
||||||
|
|
||||||
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
|
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
|
||||||
this.core.context.logger.logError('获取不到引用的消息', element.replayMsgSeq);
|
this.core.context.logger.logError.bind(this.core.context.logger)('获取不到引用的消息', element.replayMsgSeq);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return createReplyData(replyMsg.msgId);
|
return createReplyData(replyMsg.msgId);
|
||||||
@@ -257,14 +263,14 @@ export class OneBotMsgApi {
|
|||||||
if (!videoDownUrl) {
|
if (!videoDownUrl) {
|
||||||
videoDownUrl = element.filePath;
|
videoDownUrl = element.filePath;
|
||||||
}
|
}
|
||||||
|
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + element.fileName);
|
||||||
return {
|
return {
|
||||||
type: OB11MessageDataType.video,
|
type: OB11MessageDataType.video,
|
||||||
data: {
|
data: {
|
||||||
file: element.fileName,
|
file: fileCode,
|
||||||
path: videoDownUrl,
|
path: videoDownUrl,
|
||||||
url: videoDownUrl,
|
url: videoDownUrl ?? pathToFileURL(element.filePath).href,
|
||||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, element.fileName),
|
file_id: fileCode,
|
||||||
file_size: element.fileSize,
|
file_size: element.fileSize,
|
||||||
file_unique: element.fileName,
|
file_unique: element.fileName,
|
||||||
},
|
},
|
||||||
@@ -277,14 +283,16 @@ export class OneBotMsgApi {
|
|||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
guildId: '',
|
guildId: '',
|
||||||
};
|
};
|
||||||
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, element.fileName);
|
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + element.fileName);
|
||||||
return {
|
return {
|
||||||
type: OB11MessageDataType.voice,
|
type: OB11MessageDataType.voice,
|
||||||
data: {
|
data: {
|
||||||
file: fileCode,
|
file: fileCode,
|
||||||
path: element.filePath,
|
path: element.filePath,
|
||||||
|
url: pathToFileURL(element.filePath).href,
|
||||||
file_id: fileCode,
|
file_id: fileCode,
|
||||||
file_size: element.fileSize,
|
file_size: element.fileSize,
|
||||||
|
file_unique: element.fileName
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -413,6 +421,10 @@ export class OneBotMsgApi {
|
|||||||
// 从face_config.json中获取表情名称
|
// 从face_config.json中获取表情名称
|
||||||
const sysFaces = faceConfig.sysface;
|
const sysFaces = faceConfig.sysface;
|
||||||
const face: any = sysFaces.find((systemFace) => systemFace.QSid === parsedFaceId.toString());
|
const face: any = sysFaces.find((systemFace) => systemFace.QSid === parsedFaceId.toString());
|
||||||
|
if (!face) {
|
||||||
|
this.core.context.logger.logError.bind(this.core.context.logger)('不支持的ID', id);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
parsedFaceId = parseInt(parsedFaceId.toString());
|
parsedFaceId = parseInt(parsedFaceId.toString());
|
||||||
let faceType = 1;
|
let faceType = 1;
|
||||||
if (parsedFaceId >= 222) {
|
if (parsedFaceId >= 222) {
|
||||||
@@ -453,17 +465,17 @@ export class OneBotMsgApi {
|
|||||||
// File service
|
// File service
|
||||||
[OB11MessageDataType.image]: async (sendMsg, context) => {
|
[OB11MessageDataType.image]: async (sendMsg, context) => {
|
||||||
const sendPicElement = await this.core.apis.FileApi.createValidSendPicElement(
|
const sendPicElement = await this.core.apis.FileApi.createValidSendPicElement(
|
||||||
|
context,
|
||||||
(await this.handleOb11FileLikeMessage(sendMsg, context)).path,
|
(await this.handleOb11FileLikeMessage(sendMsg, context)).path,
|
||||||
sendMsg.data.summary,
|
sendMsg.data.summary,
|
||||||
sendMsg.data.sub_type,
|
sendMsg.data.sub_type,
|
||||||
);
|
);
|
||||||
context.deleteAfterSentFiles.push(sendPicElement.picElement.sourcePath);
|
|
||||||
return sendPicElement;
|
return sendPicElement;
|
||||||
},
|
},
|
||||||
|
|
||||||
[OB11MessageDataType.file]: async (sendMsg, context) => {
|
[OB11MessageDataType.file]: async (sendMsg, context) => {
|
||||||
const { path, fileName } = await this.handleOb11FileLikeMessage(sendMsg, context);
|
const { path, fileName } = await this.handleOb11FileLikeMessage(sendMsg, context);
|
||||||
return await this.core.apis.FileApi.createValidSendFileElement(path, fileName);
|
return await this.core.apis.FileApi.createValidSendFileElement(context, path, fileName);
|
||||||
},
|
},
|
||||||
|
|
||||||
[OB11MessageDataType.video]: async (sendMsg, context) => {
|
[OB11MessageDataType.video]: async (sendMsg, context) => {
|
||||||
@@ -474,9 +486,7 @@ export class OneBotMsgApi {
|
|||||||
const uri2LocalRes = await uri2local(this.core.NapCatTempPath, thumb);
|
const uri2LocalRes = await uri2local(this.core.NapCatTempPath, thumb);
|
||||||
if (uri2LocalRes.success) thumb = uri2LocalRes.path;
|
if (uri2LocalRes.success) thumb = uri2LocalRes.path;
|
||||||
}
|
}
|
||||||
const videoEle = await this.core.apis.FileApi.createValidSendVideoElement(path, fileName, thumb);
|
const videoEle = await this.core.apis.FileApi.createValidSendVideoElement(context, path, fileName, thumb);
|
||||||
|
|
||||||
context.deleteAfterSentFiles.push(videoEle.videoElement.filePath);
|
|
||||||
return videoEle;
|
return videoEle;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -537,40 +547,37 @@ export class OneBotMsgApi {
|
|||||||
|
|
||||||
[OB11MessageDataType.music]: async ({ data }, context) => {
|
[OB11MessageDataType.music]: async ({ data }, context) => {
|
||||||
// 保留, 直到...找到更好的解决方案
|
// 保留, 直到...找到更好的解决方案
|
||||||
if (data.type === 'custom') {
|
if (data.id !== undefined) {
|
||||||
if (!data.url) {
|
if (!['qq', '163', 'kugou', 'kuwo', 'migu'].includes(data.type)) {
|
||||||
this.core.context.logger.logError('自定义音卡缺少参数url');
|
this.core.context.logger.logError.bind(this.core.context.logger)('音乐卡片type错误, 只支持qq、163、kugou、kuwo、migu,当前type:', data.type);
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (!data.audio) {
|
|
||||||
this.core.context.logger.logError('自定义音卡缺少参数audio');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (!data.title) {
|
|
||||||
this.core.context.logger.logError('自定义音卡缺少参数title');
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!['qq', '163'].includes(data.type)) {
|
if (!['qq', '163', 'kugou', 'kuwo', 'migu', 'custom'].includes(data.type)) {
|
||||||
this.core.context.logger.logError('音乐卡片type错误, 只支持qq、163、custom,当前type:', data.type);
|
this.core.context.logger.logError.bind(this.core.context.logger)('音乐卡片type错误, 只支持qq、163、kugou、kuwo、migu、custom,当前type:', data.type);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (!data.id) {
|
if (!data.url) {
|
||||||
this.core.context.logger.logError('音乐卡片缺少参数id');
|
this.core.context.logger.logError.bind(this.core.context.logger)('自定义音卡缺少参数url');
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (!data.image) {
|
||||||
|
this.core.context.logger.logError.bind(this.core.context.logger)('自定义音卡缺少参数image');
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let postData: IdMusicSignPostData | CustomMusicSignPostData;
|
let postData: IdMusicSignPostData | CustomMusicSignPostData;
|
||||||
if (data.type === 'custom' && data.content) {
|
if (data.id === undefined && data.content) {
|
||||||
const { content, ...others } = data;
|
const { content, ...others } = data;
|
||||||
postData = { singer: content, ...others };
|
postData = { singer: content, ...others };
|
||||||
} else {
|
} else {
|
||||||
postData = data;
|
postData = data;
|
||||||
}
|
}
|
||||||
const signUrl = this.obContext.configLoader.configData.musicSignUrl;
|
let signUrl = this.obContext.configLoader.configData.musicSignUrl;
|
||||||
if (!signUrl) {
|
if (!signUrl) {
|
||||||
throw Error('音乐消息签名地址未配置');
|
signUrl = 'https://ss.xingzhige.com/music_card/card';//感谢思思!已获思思许可 其余地方使用请自行询问
|
||||||
|
//throw Error('音乐消息签名地址未配置');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const musicJson = await RequestUtil.HttpGetJson<any>(signUrl, 'POST', postData);
|
const musicJson = await RequestUtil.HttpGetJson<any>(signUrl, 'POST', postData);
|
||||||
@@ -579,7 +586,7 @@ export class OneBotMsgApi {
|
|||||||
type: OB11MessageDataType.json
|
type: OB11MessageDataType.json
|
||||||
}, context);
|
}, context);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.core.context.logger.logError('生成音乐消息失败', e);
|
this.core.context.logger.logError.bind(this.core.context.logger)('生成音乐消息失败', e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -601,6 +608,14 @@ export class OneBotMsgApi {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
[OB11MessageDataType.miniapp]: async () => undefined,
|
[OB11MessageDataType.miniapp]: async () => undefined,
|
||||||
|
|
||||||
|
[OB11MessageDataType.contact]: async ({ data }, context) => {
|
||||||
|
const arkJson = await this.core.apis.UserApi.getBuddyRecommendContactArkJson(data.id.toString(), '');
|
||||||
|
return this.ob11ToRawConverters.json({
|
||||||
|
data: { data: arkJson.arkMsg },
|
||||||
|
type: OB11MessageDataType.json
|
||||||
|
}, context);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
||||||
@@ -613,18 +628,14 @@ export class OneBotMsgApi {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const element of msg.elements) {
|
for (const element of msg.elements) {
|
||||||
if (element.grayTipElement) {
|
if (element.grayTipElement && element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_JSON) {
|
||||||
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_JSON) {
|
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
||||||
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
const PokeEvent = await this.obContext.apis.FriendApi.parsePrivatePokeEvent(element.grayTipElement);
|
||||||
const PokeEvent = await this.obContext.apis.FriendApi.parsePrivatePokeEvent(element.grayTipElement);
|
if (PokeEvent) return PokeEvent;
|
||||||
if (PokeEvent) return PokeEvent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_XMLMSG) {
|
//好友添加成功事件
|
||||||
//好友添加成功事件
|
if (element.grayTipElement.jsonGrayTipElement.busiId == 19324 && msg.peerUid !== '') {
|
||||||
if (element.grayTipElement.xmlElement.templId === '10229' && msg.peerUin !== '') {
|
return new OB11FriendAddNoticeEvent(this.core, Number(await this.core.apis.UserApi.getUinByUidV2(msg.peerUid)));
|
||||||
return new OB11FriendAddNoticeEvent(this.core, parseInt(msg.peerUin));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -686,36 +697,46 @@ export class OneBotMsgApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const msgSegments = (await Promise.allSettled(msg.elements.map(
|
// 处理消息段
|
||||||
|
const msgSegments = await Promise.allSettled(msg.elements.map(
|
||||||
async (element) => {
|
async (element) => {
|
||||||
for (const key in element) {
|
for (const key in element) {
|
||||||
if (keyCanBeParsed(key, this.rawToOb11Converters) && element[key]) {
|
if (keyCanBeParsed(key, this.rawToOb11Converters) && element[key]) {
|
||||||
return await this.rawToOb11Converters[key]?.(
|
const parsedElement = await this.rawToOb11Converters[key]?.(
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
element[key],
|
element[key],
|
||||||
msg,
|
msg,
|
||||||
element,
|
element,
|
||||||
);
|
);
|
||||||
|
// 对于 face 类型的消息,检查是否存在
|
||||||
|
if (key === 'faceElement' && !parsedElement) {
|
||||||
|
return null; // 如果没有找到对应的表情,返回 null
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
))).filter(entry => {
|
));
|
||||||
|
|
||||||
|
// 过滤掉无效的消息段
|
||||||
|
const validSegments = msgSegments.filter(entry => {
|
||||||
if (entry.status === 'fulfilled') {
|
if (entry.status === 'fulfilled') {
|
||||||
return !!entry.value;
|
return !!entry.value;
|
||||||
} else {
|
} else {
|
||||||
this.core.context.logger.logError('消息段解析失败', entry.reason);
|
this.core.context.logger.logError.bind(this.core.context.logger)('消息段解析失败', entry.reason);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}).map((entry) => (<PromiseFulfilledResult<OB11MessageData>>entry).value);
|
}).map((entry) => (<PromiseFulfilledResult<OB11MessageData>>entry).value).filter(value => value != null);
|
||||||
|
|
||||||
const msgAsCQCode = msgSegments.map(msg => encodeCQCode(msg)).join('').trim();
|
const msgAsCQCode = validSegments.map(msg => encodeCQCode(msg)).join('').trim();
|
||||||
|
|
||||||
if (messagePostFormat === 'string') {
|
if (messagePostFormat === 'string') {
|
||||||
resMsg.message = msgAsCQCode;
|
resMsg.message = msgAsCQCode;
|
||||||
resMsg.raw_message = msgAsCQCode;
|
resMsg.raw_message = msgAsCQCode;
|
||||||
} else {
|
} else {
|
||||||
resMsg.message = msgSegments;
|
resMsg.message = validSegments;
|
||||||
resMsg.raw_message = msgAsCQCode;
|
resMsg.raw_message = msgAsCQCode;
|
||||||
}
|
}
|
||||||
return resMsg;
|
return resMsg;
|
||||||
@@ -772,7 +793,7 @@ export class OneBotMsgApi {
|
|||||||
timeout += PredictTime;// 10S Basic Timeout + PredictTime( For File 512kb/s )
|
timeout += PredictTime;// 10S Basic Timeout + PredictTime( For File 512kb/s )
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.core.context.logger.logError('发送消息计算预计时间异常', e);
|
this.core.context.logger.logError.bind(this.core.context.logger)('发送消息计算预计时间异常', e);
|
||||||
}
|
}
|
||||||
const returnMsg = await this.core.apis.MsgApi.sendMsg(peer, sendElements, waitComplete, timeout);
|
const returnMsg = await this.core.apis.MsgApi.sendMsg(peer, sendElements, waitComplete, timeout);
|
||||||
if (!returnMsg) throw new Error('发送消息失败');
|
if (!returnMsg) throw new Error('发送消息失败');
|
||||||
@@ -782,7 +803,7 @@ export class OneBotMsgApi {
|
|||||||
peerUid: peer.peerUid,
|
peerUid: peer.peerUid,
|
||||||
}, returnMsg.msgId);
|
}, returnMsg.msgId);
|
||||||
deleteAfterSentFiles.forEach(file => {
|
deleteAfterSentFiles.forEach(file => {
|
||||||
fsPromise.unlink(file).then().catch(e => this.core.context.logger.logError('发送消息删除文件失败', e));
|
fsPromise.unlink(file).then().catch(e => this.core.context.logger.logError.bind(this.core.context.logger)('发送消息删除文件失败', e));
|
||||||
});
|
});
|
||||||
return returnMsg;
|
return returnMsg;
|
||||||
}
|
}
|
||||||
@@ -791,30 +812,59 @@ export class OneBotMsgApi {
|
|||||||
{ data: inputdata }: OB11MessageFileBase,
|
{ data: inputdata }: OB11MessageFileBase,
|
||||||
{ deleteAfterSentFiles }: MessageContext,
|
{ deleteAfterSentFiles }: MessageContext,
|
||||||
) {
|
) {
|
||||||
const isBlankUrl = !inputdata.url || inputdata.url === '';
|
const realUri = inputdata.url || inputdata.file || inputdata.path || '';
|
||||||
const isBlankFile = !inputdata.file || inputdata.file === '';
|
if (realUri.length === 0) {
|
||||||
if (isBlankUrl && isBlankFile) {
|
this.core.context.logger.logError.bind(this.core.context.logger)('文件消息缺少参数', inputdata);
|
||||||
this.core.context.logger.logError('文件消息缺少参数', inputdata);
|
|
||||||
throw Error('文件消息缺少参数');
|
throw Error('文件消息缺少参数');
|
||||||
}
|
}
|
||||||
const fileOrUrl = (isBlankUrl ? inputdata.file : inputdata.url) ?? '';
|
|
||||||
const {
|
const {
|
||||||
path,
|
path,
|
||||||
isLocal,
|
|
||||||
fileName,
|
fileName,
|
||||||
errMsg,
|
errMsg,
|
||||||
success,
|
success,
|
||||||
} = (await uri2local(this.core.NapCatTempPath, fileOrUrl));
|
} = (await uri2local(this.core.NapCatTempPath, realUri));
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
this.core.context.logger.logError('文件下载失败', errMsg);
|
this.core.context.logger.logError.bind(this.core.context.logger)('文件下载失败', errMsg);
|
||||||
throw Error('文件下载失败' + errMsg);
|
throw Error('文件下载失败' + errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isLocal) { // 只删除http和base64转过来的文件
|
deleteAfterSentFiles.push(path);
|
||||||
deleteAfterSentFiles.push(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { path, fileName: inputdata.name ?? fileName };
|
return { path, fileName: inputdata.name ?? fileName };
|
||||||
}
|
}
|
||||||
|
async parseSysMessage(msg: number[]) {
|
||||||
|
const sysMsg = SysMessage.decode(Uint8Array.from(msg)) as unknown as SysMessageType;
|
||||||
|
if (sysMsg.msgSpec.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { msgType, subType, subSubType } = sysMsg.msgSpec[0];
|
||||||
|
if (msgType === 528 && subType === 39 && subSubType === 39) {
|
||||||
|
if (!sysMsg.bodyWrapper) return;
|
||||||
|
const event = await this.obContext.apis.UserApi.parseLikeEvent(sysMsg.bodyWrapper.wrappedBody);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (msgType === 732 && subType === 16 && subSubType === 16) {
|
||||||
|
const greyTip = GreyTipWrapper.fromBinary(Uint8Array.from(sysMsg.bodyWrapper!.wrappedBody.slice(7)));
|
||||||
|
if (greyTip.subTypeId === 36) {
|
||||||
|
const emojiLikeToOthers = EmojiLikeToOthersWrapper1
|
||||||
|
.fromBinary(greyTip.rest)
|
||||||
|
.wrapper!
|
||||||
|
.body!;
|
||||||
|
if (emojiLikeToOthers.attributes?.operation !== 1) { // Un-like
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const eventOrEmpty = await this.apis.GroupApi.createGroupEmojiLikeEvent(
|
||||||
|
greyTip.groupCode.toString(),
|
||||||
|
await this.core.apis.UserApi.getUinByUidV2(emojiLikeToOthers.attributes!.senderUid),
|
||||||
|
emojiLikeToOthers.msgSpec!.msgSeq.toString(),
|
||||||
|
emojiLikeToOthers.attributes!.emojiId,
|
||||||
|
);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||||
|
eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,7 @@ export class OneBotQuickActionApi {
|
|||||||
const peerContextMode = msg.message_type == 'private' ? ContextMode.Private : ContextMode.Group;
|
const peerContextMode = msg.message_type == 'private' ? ContextMode.Private : ContextMode.Group;
|
||||||
|
|
||||||
const peer: Peer = await createContext(this.core, {
|
const peer: Peer = await createContext(this.core, {
|
||||||
message: "",
|
message_type: undefined,
|
||||||
group_id: msg.group_id?.toString(),
|
group_id: msg.group_id?.toString(),
|
||||||
user_id: msg.user_id?.toString(),
|
user_id: msg.user_id?.toString(),
|
||||||
}, peerContextMode);
|
}, peerContextMode);
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
|
import { profileLikeTip, ProfileLikeTipType } from '@/core/proto/ProfileLike';
|
||||||
|
|
||||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||||
|
import { OB11ProfileLikeEvent } from '../event/notice/OB11ProfileLikeEvent';
|
||||||
|
|
||||||
export class OneBotUserApi {
|
export class OneBotUserApi {
|
||||||
obContext: NapCatOneBot11Adapter;
|
obContext: NapCatOneBot11Adapter;
|
||||||
@@ -10,4 +12,21 @@ export class OneBotUserApi {
|
|||||||
this.obContext = obContext;
|
this.obContext = obContext;
|
||||||
this.core = core;
|
this.core = core;
|
||||||
}
|
}
|
||||||
|
async parseLikeEvent(wrappedBody: Uint8Array): Promise<OB11ProfileLikeEvent | undefined> {
|
||||||
|
const likeTip = profileLikeTip.decode(Uint8Array.from(wrappedBody)) as unknown as ProfileLikeTipType;
|
||||||
|
if (likeTip?.msgType !== 0 || likeTip?.subType !== 203) return;
|
||||||
|
this.core.context.logger.logDebug("收到点赞通知消息");
|
||||||
|
const likeMsg = likeTip.content.msg;
|
||||||
|
if (!likeMsg) return;
|
||||||
|
const detail = likeMsg.detail;
|
||||||
|
if (!detail) return;
|
||||||
|
const times = detail.txt.match(/\d+/) ?? "0";
|
||||||
|
return new OB11ProfileLikeEvent(
|
||||||
|
this.core,
|
||||||
|
Number(detail.uin),
|
||||||
|
detail.nickname,
|
||||||
|
parseInt(times[0], 10),
|
||||||
|
likeMsg.time,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -48,7 +48,8 @@ export class OB11Entities {
|
|||||||
}[role];
|
}[role];
|
||||||
}
|
}
|
||||||
|
|
||||||
static sex(sex: Sex): OB11UserSex {
|
static sex(sex?: Sex): OB11UserSex {
|
||||||
|
if (!sex) return OB11UserSex.unknown;
|
||||||
return {
|
return {
|
||||||
[Sex.male]: OB11UserSex.male,
|
[Sex.male]: OB11UserSex.male,
|
||||||
[Sex.female]: OB11UserSex.female,
|
[Sex.female]: OB11UserSex.female,
|
||||||
@@ -126,6 +127,7 @@ export class OB11Entities {
|
|||||||
return {
|
return {
|
||||||
group_id: parseInt(peerId),
|
group_id: parseInt(peerId),
|
||||||
folder_id: folder.folderId,
|
folder_id: folder.folderId,
|
||||||
|
folder: folder.folderId,
|
||||||
folder_name: folder.folderName,
|
folder_name: folder.folderName,
|
||||||
create_time: folder.createTime,
|
create_time: folder.createTime,
|
||||||
creator: parseInt(folder.createUin),
|
creator: parseInt(folder.createUin),
|
||||||
|
@@ -6,6 +6,7 @@ export interface GroupUploadFile {
|
|||||||
name: string,
|
name: string,
|
||||||
size: number,
|
size: number,
|
||||||
busid: number,
|
busid: number,
|
||||||
|
url:string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OB11GroupUploadNoticeEvent extends OB11GroupNoticeEvent {
|
export class OB11GroupUploadNoticeEvent extends OB11GroupNoticeEvent {
|
||||||
|
19
src/onebot/event/notice/OB11ProfileLikeEvent.ts
Normal file
19
src/onebot/event/notice/OB11ProfileLikeEvent.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent';
|
||||||
|
import { NapCatCore } from '@/core';
|
||||||
|
|
||||||
|
export class OB11ProfileLikeEvent extends OB11BaseNoticeEvent {
|
||||||
|
notice_type = 'notify';
|
||||||
|
sub_type = 'profile_like';
|
||||||
|
operator_id: number;
|
||||||
|
operator_nick: string;
|
||||||
|
times: number;
|
||||||
|
time: number;
|
||||||
|
|
||||||
|
constructor(core: NapCatCore, operatorId: number, operatorNick: string, times: number, time: number) {
|
||||||
|
super(core);
|
||||||
|
this.operator_id = operatorId;
|
||||||
|
this.operator_nick = operatorNick;
|
||||||
|
this.times = times;
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
}
|
@@ -43,7 +43,8 @@ import { OB11FriendRecallNoticeEvent } from '@/onebot/event/notice/OB11FriendRec
|
|||||||
import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent';
|
import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent';
|
||||||
import { LRUCache } from '@/common/lru-cache';
|
import { LRUCache } from '@/common/lru-cache';
|
||||||
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
|
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
|
||||||
|
import { OB11ProfileLikeEvent } from './event/notice/OB11ProfileLikeEvent';
|
||||||
|
import { profileLikeTip, ProfileLikeTipType, SysMessage, SysMessageType } from '@/core/proto/ProfileLike';
|
||||||
//OneBot实现类
|
//OneBot实现类
|
||||||
export class NapCatOneBot11Adapter {
|
export class NapCatOneBot11Adapter {
|
||||||
readonly core: NapCatCore;
|
readonly core: NapCatCore;
|
||||||
@@ -70,7 +71,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
this.actions = createActionMap(this, core);
|
this.actions = createActionMap(this, core);
|
||||||
this.networkManager = new OB11NetworkManager();
|
this.networkManager = new OB11NetworkManager();
|
||||||
this.InitOneBot()
|
this.InitOneBot()
|
||||||
.catch(e => this.context.logger.logError('初始化OneBot失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('初始化OneBot失败', e));
|
||||||
}
|
}
|
||||||
|
|
||||||
async InitOneBot() {
|
async InitOneBot() {
|
||||||
@@ -86,7 +87,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
this.core.apis.UserApi.getUserDetailInfo(selfInfo.uid).then(user => {
|
this.core.apis.UserApi.getUserDetailInfo(selfInfo.uid).then(user => {
|
||||||
selfInfo.nick = user.nick;
|
selfInfo.nick = user.nick;
|
||||||
this.context.logger.setLogSelfInfo(selfInfo);
|
this.context.logger.setLogSelfInfo(selfInfo);
|
||||||
}).catch(this.context.logger.logError);
|
}).catch(this.context.logger.logError.bind(this.context.logger));
|
||||||
this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`);
|
this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`);
|
||||||
|
|
||||||
//创建NetWork服务
|
//创建NetWork服务
|
||||||
@@ -237,36 +238,11 @@ export class NapCatOneBot11Adapter {
|
|||||||
|
|
||||||
private initMsgListener() {
|
private initMsgListener() {
|
||||||
const msgListener = new NodeIKernelMsgListener();
|
const msgListener = new NodeIKernelMsgListener();
|
||||||
|
msgListener.onRecvSysMsg = (msg) => {
|
||||||
/*
|
this.apis.MsgApi.parseSysMessage(msg).then((event) => {
|
||||||
msgListener.onRecvSysMsg = async () => {
|
if (event) this.networkManager.emitEvent(event);
|
||||||
const sysMsg = SysMessage.fromBinary(Uint8Array.from(msg));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructSysMessage error: ', e));
|
||||||
if (sysMsg.msgSpec.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { msgType, subType, subSubType } = sysMsg.msgSpec[0];
|
|
||||||
if (msgType === 732 && subType === 16 && subSubType === 16) {
|
|
||||||
const greyTip = GreyTipWrapper.fromBinary(Uint8Array.from(sysMsg.bodyWrapper!.wrappedBody.slice(7)));
|
|
||||||
if (greyTip.subTypeId === 36) {
|
|
||||||
const emojiLikeToOthers = EmojiLikeToOthersWrapper1
|
|
||||||
.fromBinary(greyTip.rest)
|
|
||||||
.wrapper!
|
|
||||||
.body!;
|
|
||||||
if (emojiLikeToOthers.attributes?.operation !== 1) { // Un-like
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const eventOrEmpty = await this.apis.GroupApi.createGroupEmojiLikeEvent(
|
|
||||||
greyTip.groupCode.toString(),
|
|
||||||
await this.core.apis.UserApi.getUinByUidV2(emojiLikeToOthers.attributes!.senderUid),
|
|
||||||
emojiLikeToOthers.msgSpec!.msgSeq.toString(),
|
|
||||||
emojiLikeToOthers.attributes!.emojiId,
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
||||||
eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
|
|
||||||
msgListener.onInputStatusPush = async data => {
|
msgListener.onInputStatusPush = async data => {
|
||||||
const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin);
|
const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin);
|
||||||
@@ -294,7 +270,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
m.msgId,
|
m.msgId,
|
||||||
);
|
);
|
||||||
await this.emitMsg(m)
|
await this.emitMsg(m)
|
||||||
.catch(e => this.context.logger.logError('处理消息失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -302,7 +278,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
const recallMsgs = new LRUCache<string, boolean>(100);
|
const recallMsgs = new LRUCache<string, boolean>(100);
|
||||||
msgListener.onMsgInfoListUpdate = async msgList => {
|
msgListener.onMsgInfoListUpdate = async msgList => {
|
||||||
this.emitRecallMsg(msgList, recallMsgs)
|
this.emitRecallMsg(msgList, recallMsgs)
|
||||||
.catch(e => this.context.logger.logError('处理消息失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e));
|
||||||
|
|
||||||
for (const msg of msgList.filter(e => e.senderUin == this.core.selfInfo.uin)) {
|
for (const msg of msgList.filter(e => e.senderUin == this.core.selfInfo.uin)) {
|
||||||
if (msg.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS && !msgIdSend.get(msg.msgId)) {
|
if (msg.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS && !msgIdSend.get(msg.msgId)) {
|
||||||
@@ -404,7 +380,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
].includes(notify.type) ? 'unset' : 'set',
|
].includes(notify.type) ? 'unset' : 'set',
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
||||||
.catch(e => this.context.logger.logError('处理群管理员变动失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群管理员变动失败', e));
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logDebug('获取群通知的成员信息失败', notify, this.core.apis.GroupApi.getGroup(notify.group.groupCode));
|
this.context.logger.logDebug('获取群通知的成员信息失败', notify, this.core.apis.GroupApi.getGroup(notify.group.groupCode));
|
||||||
}
|
}
|
||||||
@@ -429,7 +405,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
subType,
|
subType,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupDecreaseEvent)
|
this.networkManager.emitEvent(groupDecreaseEvent)
|
||||||
.catch(e => this.context.logger.logError('处理群成员退出失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群成员退出失败', e));
|
||||||
// notify.status == 1 表示未处理 2表示处理完成
|
// notify.status == 1 表示未处理 2表示处理完成
|
||||||
} else if ([
|
} else if ([
|
||||||
GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS,
|
GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS,
|
||||||
@@ -449,9 +425,9 @@ export class NapCatOneBot11Adapter {
|
|||||||
flag,
|
flag,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupRequestEvent)
|
this.networkManager.emitEvent(groupRequestEvent)
|
||||||
.catch(e => this.context.logger.logError('处理加群请求失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理加群请求失败', e));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.context.logger.logError('获取加群人QQ号失败 Uid:', notify.user1.uid, e);
|
this.context.logger.logError.bind(this.context.logger)('获取加群人QQ号失败 Uid:', notify.user1.uid, e);
|
||||||
}
|
}
|
||||||
} else if (notify.type == GroupNotifyMsgType.INVITED_BY_MEMBER && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
|
} else if (notify.type == GroupNotifyMsgType.INVITED_BY_MEMBER && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
|
||||||
this.context.logger.logDebug(`收到邀请我加群通知:${notify}`);
|
this.context.logger.logDebug(`收到邀请我加群通知:${notify}`);
|
||||||
@@ -464,7 +440,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
flag,
|
flag,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupInviteEvent)
|
this.networkManager.emitEvent(groupInviteEvent)
|
||||||
.catch(e => this.context.logger.logError('处理邀请本人加群失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理邀请本人加群失败', e));
|
||||||
} else if (notify.type == GroupNotifyMsgType.INVITED_NEED_ADMINI_STRATOR_PASS && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
|
} else if (notify.type == GroupNotifyMsgType.INVITED_NEED_ADMINI_STRATOR_PASS && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
|
||||||
this.context.logger.logDebug(`收到群员邀请加群通知:${notify}`);
|
this.context.logger.logDebug(`收到群员邀请加群通知:${notify}`);
|
||||||
const groupInviteEvent = new OB11GroupRequestEvent(
|
const groupInviteEvent = new OB11GroupRequestEvent(
|
||||||
@@ -476,7 +452,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
flag,
|
flag,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupInviteEvent)
|
this.networkManager.emitEvent(groupInviteEvent)
|
||||||
.catch(e => this.context.logger.logError('处理邀请本人加群失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理邀请本人加群失败', e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,9 +474,9 @@ export class NapCatOneBot11Adapter {
|
|||||||
member.role === GroupMemberRole.admin ? 'set' : 'unset',
|
member.role === GroupMemberRole.admin ? 'set' : 'unset',
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
||||||
.catch(e => this.context.logger.logError('处理群管理员变动失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群管理员变动失败', e));
|
||||||
existMember.isChangeRole = false;
|
existMember.isChangeRole = false;
|
||||||
this.context.logger.logDebug('群管理员变动处理完毕');
|
this.context.logger.logDebug.bind(this.context.logger)('群管理员变动处理完毕');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -523,8 +499,6 @@ export class NapCatOneBot11Adapter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// logOB11Message(this.core, ob11Msg)
|
|
||||||
// .catch(e => this.context.logger.logError('logMessage error: ', e));
|
|
||||||
const isSelfMsg = ob11Msg.user_id.toString() == this.core.selfInfo.uin;
|
const isSelfMsg = ob11Msg.user_id.toString() == this.core.selfInfo.uin;
|
||||||
if (isSelfMsg && !reportSelfMessage) {
|
if (isSelfMsg && !reportSelfMessage) {
|
||||||
return;
|
return;
|
||||||
@@ -533,21 +507,21 @@ export class NapCatOneBot11Adapter {
|
|||||||
ob11Msg.target_id = parseInt(message.peerUin);
|
ob11Msg.target_id = parseInt(message.peerUin);
|
||||||
}
|
}
|
||||||
this.networkManager.emitEvent(ob11Msg);
|
this.networkManager.emitEvent(ob11Msg);
|
||||||
}).catch(e => this.context.logger.logError('constructMessage error: ', e));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructMessage error: ', e));
|
||||||
|
|
||||||
this.apis.GroupApi.parseGroupEvent(message).then(groupEvent => {
|
this.apis.GroupApi.parseGroupEvent(message).then(groupEvent => {
|
||||||
if (groupEvent) {
|
if (groupEvent) {
|
||||||
// log("post group event", groupEvent);
|
// log("post group event", groupEvent);
|
||||||
this.networkManager.emitEvent(groupEvent);
|
this.networkManager.emitEvent(groupEvent);
|
||||||
}
|
}
|
||||||
}).catch(e => this.context.logger.logError('constructGroupEvent error: ', e));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructGroupEvent error: ', e));
|
||||||
|
|
||||||
this.apis.MsgApi.parsePrivateMsgEvent(message).then(privateEvent => {
|
this.apis.MsgApi.parsePrivateMsgEvent(message).then(privateEvent => {
|
||||||
if (privateEvent) {
|
if (privateEvent) {
|
||||||
// log("post private event", privateEvent);
|
// log("post private event", privateEvent);
|
||||||
this.networkManager.emitEvent(privateEvent);
|
this.networkManager.emitEvent(privateEvent);
|
||||||
}
|
}
|
||||||
}).catch(e => this.context.logger.logError('constructPrivateEvent error: ', e));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructPrivateEvent error: ', e));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async emitRecallMsg(msgList: RawMessage[], cache: LRUCache<string, boolean>) {
|
private async emitRecallMsg(msgList: RawMessage[], cache: LRUCache<string, boolean>) {
|
||||||
@@ -567,7 +541,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
oriMessageId,
|
oriMessageId,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(friendRecallEvent)
|
this.networkManager.emitEvent(friendRecallEvent)
|
||||||
.catch(e => this.context.logger.logError('处理好友消息撤回失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理好友消息撤回失败', e));
|
||||||
} else if (message.chatType == ChatType.KCHATTYPEGROUP) {
|
} else if (message.chatType == ChatType.KCHATTYPEGROUP) {
|
||||||
let operatorId = message.senderUin;
|
let operatorId = message.senderUin;
|
||||||
for (const element of message.elements) {
|
for (const element of message.elements) {
|
||||||
@@ -584,7 +558,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
oriMessageId,
|
oriMessageId,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupRecallEvent)
|
this.networkManager.emitEvent(groupRecallEvent)
|
||||||
.catch(e => this.context.logger.logError('处理群消息撤回失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群消息撤回失败', e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -49,12 +49,12 @@ export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter {
|
|||||||
try {
|
try {
|
||||||
this.obContext.apis.QuickActionApi
|
this.obContext.apis.QuickActionApi
|
||||||
.handleQuickOperation(event as QuickActionEvent, resJson)
|
.handleQuickOperation(event as QuickActionEvent, resJson)
|
||||||
.catch(this.logger.logError);
|
.catch(this.logger.logError.bind(this.logger));
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.logger.logError('[OneBot] [Http Client] 新消息事件HTTP上报返回快速操作失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [Http Client] 新消息事件HTTP上报返回快速操作失败', e);
|
||||||
}
|
}
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
this.logger.logError('[OneBot] [Http Client] 新消息事件HTTP上报失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [Http Client] 新消息事件HTTP上报失败', e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -91,7 +91,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
try {
|
try {
|
||||||
this.connectEvent(this.core);
|
this.connectEvent(this.core);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发送连接生命周期失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Client] 发送连接生命周期失败', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -100,8 +100,8 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
});
|
});
|
||||||
this.connection.once('close', () => {
|
this.connection.once('close', () => {
|
||||||
if (!isClosedByError) {
|
if (!isClosedByError) {
|
||||||
this.logger.logError(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接意外关闭`);
|
this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接意外关闭`);
|
||||||
this.logger.logError(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
||||||
if (!this.isClosed) {
|
if (!this.isClosed) {
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
||||||
@@ -110,8 +110,8 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
});
|
});
|
||||||
this.connection.on('error', (err) => {
|
this.connection.on('error', (err) => {
|
||||||
isClosedByError = true;
|
isClosedByError = true;
|
||||||
this.logger.logError(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接错误`, err);
|
this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接错误`, err);
|
||||||
this.logger.logError(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
||||||
if (!this.isClosed) {
|
if (!this.isClosed) {
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
||||||
@@ -124,7 +124,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
try {
|
try {
|
||||||
this.checkStateAndReply<any>(new OB11LifeCycleEvent(core, LifeCycleSubType.CONNECT));
|
this.checkStateAndReply<any>(new OB11LifeCycleEvent(core, LifeCycleSubType.CONNECT));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发送生命周期失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Client] 发送生命周期失败', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
|
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
|
||||||
const action = this.actions.get(receiveData.action);
|
const action = this.actions.get(receiveData.action);
|
||||||
if (!action) {
|
if (!action) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
|
||||||
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo));
|
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
core: NapCatCore;
|
core: NapCatCore;
|
||||||
logger: LogWrapper;
|
logger: LogWrapper;
|
||||||
private heartbeatIntervalId: NodeJS.Timeout | null = null;
|
private heartbeatIntervalId: NodeJS.Timeout | null = null;
|
||||||
|
wsClientWithEvent: WebSocket[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ip: string,
|
ip: string,
|
||||||
@@ -46,10 +47,15 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
}
|
}
|
||||||
//鉴权
|
//鉴权
|
||||||
this.authorize(token, wsClient, wsReq);
|
this.authorize(token, wsClient, wsReq);
|
||||||
this.connectEvent(core, wsClient);
|
const paramUrl = wsReq.url?.indexOf('?') !== -1 ? wsReq.url?.substring(0, wsReq.url?.indexOf('?')) : wsReq.url;
|
||||||
|
const isApiConnect = paramUrl === '/api' || paramUrl === '/api/';
|
||||||
|
if (!isApiConnect) {
|
||||||
|
this.connectEvent(core, wsClient);
|
||||||
|
}
|
||||||
|
|
||||||
wsClient.on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Client Error:', err.message));
|
wsClient.on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Client Error:', err.message));
|
||||||
wsClient.on('message', (message) => {
|
wsClient.on('message', (message) => {
|
||||||
this.handleMessage(wsClient, message).then().catch(this.logger.logError);
|
this.handleMessage(wsClient, message).then().catch(this.logger.logError.bind(this.logger));
|
||||||
});
|
});
|
||||||
wsClient.on('ping', () => {
|
wsClient.on('ping', () => {
|
||||||
wsClient.pong();
|
wsClient.pong();
|
||||||
@@ -59,13 +65,21 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
});
|
});
|
||||||
wsClient.once('close', () => {
|
wsClient.once('close', () => {
|
||||||
this.wsClientsMutex.runExclusive(async () => {
|
this.wsClientsMutex.runExclusive(async () => {
|
||||||
const index = this.wsClients.indexOf(wsClient);
|
const NormolIndex = this.wsClients.indexOf(wsClient);
|
||||||
if (index !== -1) {
|
if (NormolIndex !== -1) {
|
||||||
this.wsClients.splice(index, 1);
|
this.wsClients.splice(NormolIndex, 1);
|
||||||
}
|
}
|
||||||
|
const EventIndex = this.wsClientWithEvent.indexOf(wsClient);
|
||||||
|
if (EventIndex !== -1) {
|
||||||
|
this.wsClientWithEvent.splice(EventIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
await this.wsClientsMutex.runExclusive(async () => {
|
await this.wsClientsMutex.runExclusive(async () => {
|
||||||
|
if (!isApiConnect) {
|
||||||
|
this.wsClientWithEvent.push(wsClient);
|
||||||
|
}
|
||||||
this.wsClients.push(wsClient);
|
this.wsClients.push(wsClient);
|
||||||
});
|
});
|
||||||
}).on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Server Error:', err.message));
|
}).on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Server Error:', err.message));
|
||||||
@@ -75,13 +89,13 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
try {
|
try {
|
||||||
this.checkStateAndReply<any>(new OB11LifeCycleEvent(core, LifeCycleSubType.CONNECT), wsClient);
|
this.checkStateAndReply<any>(new OB11LifeCycleEvent(core, LifeCycleSubType.CONNECT), wsClient);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Server] 发送生命周期失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Server] 发送生命周期失败', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onEvent<T extends OB11EmitEventContent>(event: T) {
|
onEvent<T extends OB11EmitEventContent>(event: T) {
|
||||||
this.wsClientsMutex.runExclusive(async () => {
|
this.wsClientsMutex.runExclusive(async () => {
|
||||||
this.wsClients.forEach((wsClient) => {
|
this.wsClientWithEvent.forEach((wsClient) => {
|
||||||
wsClient.send(JSON.stringify(event));
|
wsClient.send(JSON.stringify(event));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -89,11 +103,11 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
|
|
||||||
open() {
|
open() {
|
||||||
if (this.isOpen) {
|
if (this.isOpen) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Server] Cannot open a opened WebSocket server');
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Server] Cannot open a opened WebSocket server');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.hasBeenClosed) {
|
if (this.hasBeenClosed) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Server] Cannot open a WebSocket server that has been closed');
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Server] Cannot open a WebSocket server that has been closed');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const addressInfo = this.wsServer.address();
|
const addressInfo = this.wsServer.address();
|
||||||
@@ -156,7 +170,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
|
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
|
||||||
const action = this.actions.get(receiveData.action);
|
const action = this.actions.get(receiveData.action);
|
||||||
if (!action) {
|
if (!action) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
|
||||||
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo), wsClient);
|
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo), wsClient);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
export interface OB11User {
|
export interface OB11User {
|
||||||
|
[key: string]: any;
|
||||||
user_id: number;
|
user_id: number;
|
||||||
nickname: string;
|
nickname: string;
|
||||||
remark?: string;
|
remark?: string;
|
||||||
@@ -81,6 +82,7 @@ export interface OB11GroupFile {
|
|||||||
export interface OB11GroupFileFolder {
|
export interface OB11GroupFileFolder {
|
||||||
group_id: number,
|
group_id: number,
|
||||||
folder_id: string,
|
folder_id: string,
|
||||||
|
folder: string,
|
||||||
folder_name: string,
|
folder_name: string,
|
||||||
create_time: number,
|
create_time: number,
|
||||||
creator: number,
|
creator: number,
|
||||||
|
@@ -62,6 +62,7 @@ export enum OB11MessageDataType {
|
|||||||
dice = 'dice',
|
dice = 'dice',
|
||||||
RPS = 'rps',
|
RPS = 'rps',
|
||||||
miniapp = 'miniapp',//json类
|
miniapp = 'miniapp',//json类
|
||||||
|
contact = 'contact',
|
||||||
Location = 'location'
|
Location = 'location'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,9 +82,16 @@ export interface OB11MessageText {
|
|||||||
text: string, // 纯文本
|
text: string, // 纯文本
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export interface OB11MessageContext {
|
||||||
|
type: OB11MessageDataType.contact,
|
||||||
|
data: {
|
||||||
|
id: string,
|
||||||
|
}
|
||||||
|
}
|
||||||
export interface OB11MessageFileBase {
|
export interface OB11MessageFileBase {
|
||||||
data: {
|
data: {
|
||||||
|
file_unique?: string,
|
||||||
|
path?: string;
|
||||||
thumb?: string;
|
thumb?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
file: string,
|
file: string,
|
||||||
@@ -196,7 +204,7 @@ export type OB11MessageData =
|
|||||||
OB11MessageAt | OB11MessageReply |
|
OB11MessageAt | OB11MessageReply |
|
||||||
OB11MessageImage | OB11MessageRecord | OB11MessageFile | OB11MessageVideo |
|
OB11MessageImage | OB11MessageRecord | OB11MessageFile | OB11MessageVideo |
|
||||||
OB11MessageNode | OB11MessageIdMusic | OB11MessageCustomMusic | OB11MessageJson |
|
OB11MessageNode | OB11MessageIdMusic | OB11MessageCustomMusic | OB11MessageJson |
|
||||||
OB11MessageDice | OB11MessageRPS | OB11MessageMarkdown | OB11MessageForward
|
OB11MessageDice | OB11MessageRPS | OB11MessageMarkdown | OB11MessageForward | OB11MessageContext
|
||||||
|
|
||||||
export interface OB11PostSendMsg {
|
export interface OB11PostSendMsg {
|
||||||
message_type?: 'private' | 'group'
|
message_type?: 'private' | 'group'
|
||||||
@@ -206,3 +214,8 @@ export interface OB11PostSendMsg {
|
|||||||
messages?: OB11MessageMixType; // 兼容 go-cqhttp
|
messages?: OB11MessageMixType; // 兼容 go-cqhttp
|
||||||
auto_escape?: boolean | string
|
auto_escape?: boolean | string
|
||||||
}
|
}
|
||||||
|
export interface OB11PostContext {
|
||||||
|
message_type?: 'private' | 'group'
|
||||||
|
user_id?: string,
|
||||||
|
group_id?: string,
|
||||||
|
}
|
||||||
|
@@ -11,6 +11,7 @@ import {
|
|||||||
NapCatCore,
|
NapCatCore,
|
||||||
NapCatCoreWorkingEnv,
|
NapCatCoreWorkingEnv,
|
||||||
NodeIQQNTWrapperSession,
|
NodeIQQNTWrapperSession,
|
||||||
|
PlatformType,
|
||||||
WrapperNodeApi,
|
WrapperNodeApi,
|
||||||
} from '@/core';
|
} from '@/core';
|
||||||
import { QQBasicInfoWrapper } from '@/common/qq-basic-info';
|
import { QQBasicInfoWrapper } from '@/common/qq-basic-info';
|
||||||
@@ -27,6 +28,7 @@ import { NapCatOneBot11Adapter } from '@/onebot';
|
|||||||
import { InitWebUi } from '@/webui';
|
import { InitWebUi } from '@/webui';
|
||||||
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
|
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
|
||||||
import { napCatVersion } from '@/common/version';
|
import { napCatVersion } from '@/common/version';
|
||||||
|
import { NodeIO3MiscListener } from '@/core/listeners/NodeIO3MiscListener';
|
||||||
|
|
||||||
program.option('-q, --qq [number]', 'QQ号').parse(process.argv);
|
program.option('-q, --qq [number]', 'QQ号').parse(process.argv);
|
||||||
const cmdOptions = program.opts();
|
const cmdOptions = program.opts();
|
||||||
@@ -39,14 +41,19 @@ export async function NCoreInitShell() {
|
|||||||
const logger = new LogWrapper(pathWrapper.logsPath);
|
const logger = new LogWrapper(pathWrapper.logsPath);
|
||||||
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
||||||
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
||||||
|
|
||||||
|
const o3Service = wrapper.NodeIO3MiscService.get();
|
||||||
|
o3Service.addO3MiscListener(new NodeIO3MiscListener());
|
||||||
|
|
||||||
logger.log(`[NapCat] [Core] NapCat.Core Version: ` + napCatVersion);
|
logger.log(`[NapCat] [Core] NapCat.Core Version: ` + napCatVersion);
|
||||||
InitWebUi(logger, pathWrapper).then().catch(logger.logError);
|
InitWebUi(logger, pathWrapper).then().catch(logger.logError.bind(logger));
|
||||||
|
|
||||||
// from constructor
|
// from constructor
|
||||||
const engine = new wrapper.NodeIQQNTWrapperEngine();
|
const engine = wrapper.NodeIQQNTWrapperEngine.get();
|
||||||
//const util = wrapper.NodeQQNTWrapperUtil.get();
|
//const util = wrapper.NodeQQNTWrapperUtil.get();
|
||||||
const loginService = new wrapper.NodeIKernelLoginService();
|
const loginService = wrapper.NodeIKernelLoginService.get();
|
||||||
const session = new wrapper.NodeIQQNTWrapperSession();
|
|
||||||
|
const session = wrapper.NodeIQQNTWrapperSession.create();
|
||||||
|
|
||||||
// from get dataPath
|
// from get dataPath
|
||||||
const [dataPath, dataPathGlobal] = (() => {
|
const [dataPath, dataPathGlobal] = (() => {
|
||||||
@@ -63,17 +70,29 @@ export async function NCoreInitShell() {
|
|||||||
const dataPathGlobal = path.resolve(dataPath, './nt_qq/global');
|
const dataPathGlobal = path.resolve(dataPath, './nt_qq/global');
|
||||||
return [dataPath, dataPathGlobal];
|
return [dataPath, dataPathGlobal];
|
||||||
})();
|
})();
|
||||||
|
let systemPlatform = PlatformType.KWINDOWS;
|
||||||
|
switch (os.platform()) {
|
||||||
|
case 'win32':
|
||||||
|
systemPlatform = PlatformType.KWINDOWS;
|
||||||
|
break;
|
||||||
|
case 'darwin':
|
||||||
|
systemPlatform = PlatformType.KMAC;
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
systemPlatform = PlatformType.KLINUX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!basicInfoWrapper.QQVersionAppid || !basicInfoWrapper.QQVersionQua) throw new Error('QQVersionAppid or QQVersionQua is not defined');
|
||||||
// from initConfig
|
// from initConfig
|
||||||
engine.initWithDeskTopConfig(
|
engine.initWithDeskTopConfig(
|
||||||
{
|
{
|
||||||
base_path_prefix: '',
|
base_path_prefix: '',
|
||||||
platform_type: 3,
|
platform_type: systemPlatform,
|
||||||
app_type: 4,
|
app_type: 4,
|
||||||
app_version: basicInfoWrapper.getFullQQVesion(),
|
app_version: basicInfoWrapper.getFullQQVesion(),
|
||||||
os_version: 'Windows 10 Pro',
|
os_version: systemVersion,
|
||||||
use_xlog: true,
|
use_xlog: false,
|
||||||
qua: basicInfoWrapper.QQVersionQua!,
|
qua: basicInfoWrapper.QQVersionQua,
|
||||||
global_path_config: {
|
global_path_config: {
|
||||||
desktopGlobalPath: dataPathGlobal,
|
desktopGlobalPath: dataPathGlobal,
|
||||||
},
|
},
|
||||||
@@ -83,7 +102,7 @@ export async function NCoreInitShell() {
|
|||||||
);
|
);
|
||||||
loginService.initConfig({
|
loginService.initConfig({
|
||||||
machineId: '',
|
machineId: '',
|
||||||
appid: basicInfoWrapper.QQVersionAppid!,
|
appid: basicInfoWrapper.QQVersionAppid,
|
||||||
platVer: systemVersion,
|
platVer: systemVersion,
|
||||||
commonPath: dataPathGlobal,
|
commonPath: dataPathGlobal,
|
||||||
clientVer: basicInfoWrapper.getFullQQVesion(),
|
clientVer: basicInfoWrapper.getFullQQVesion(),
|
||||||
@@ -100,21 +119,25 @@ export async function NCoreInitShell() {
|
|||||||
quickLoginUin = '';
|
quickLoginUin = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let dataTimestape = new Date().getTime().toString();
|
||||||
|
o3Service.reportAmgomWeather('login', 'a1', [dataTimestape, '0', '0']);
|
||||||
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
||||||
const loginListener = new NodeIKernelLoginListener();
|
const loginListener = new NodeIKernelLoginListener();
|
||||||
|
let isLogined = false;
|
||||||
// from constructor
|
// from constructor
|
||||||
loginListener.onUserLoggedIn = (userid: string) => {
|
loginListener.onUserLoggedIn = (userid: string) => {
|
||||||
logger.logError(`当前账号(${userid})已登录,无法重复登录`);
|
logger.logError.bind(logger)(`当前账号(${userid})已登录,无法重复登录`);
|
||||||
};
|
};
|
||||||
|
|
||||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => resolve({
|
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
||||||
uid: loginResult.uid,
|
isLogined = true;
|
||||||
uin: loginResult.uin,
|
resolve({
|
||||||
nick: '', // 获取不到
|
uid: loginResult.uid,
|
||||||
online: true,
|
uin: loginResult.uin,
|
||||||
});
|
nick: '', // 获取不到
|
||||||
|
online: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
loginListener.onQRCodeGetPicture = ({ pngBase64QrcodeData, qrcodeUrl }) => {
|
loginListener.onQRCodeGetPicture = ({ pngBase64QrcodeData, qrcodeUrl }) => {
|
||||||
//设置WebuiQrcode
|
//设置WebuiQrcode
|
||||||
@@ -137,37 +160,49 @@ export async function NCoreInitShell() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
loginListener.onQRCodeSessionFailed = (errType: number, errCode: number, errMsg: string) => {
|
loginListener.onQRCodeSessionFailed = (errType: number, errCode: number, errMsg: string) => {
|
||||||
//logger.logError('登录失败(onQRCodeSessionFailed)', errCode, errMsg);
|
if (!isLogined) {
|
||||||
logger.logError('[Core] [Login] Login Error,ErrCode: ', errCode, ' ErrMsg:', errMsg);
|
logger.logError.bind(logger)('[Core] [Login] Login Error,ErrCode: ', errCode, ' ErrMsg:', errMsg);
|
||||||
if (errType == 1 && errCode == 3) {
|
if (errType == 1 && errCode == 3) {
|
||||||
// 二维码过期刷新
|
// 二维码过期刷新
|
||||||
|
}
|
||||||
|
loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
loginService.getQRCodePicture();
|
|
||||||
};
|
};
|
||||||
loginListener.onLoginFailed = (args) => {
|
loginListener.onLoginFailed = (args) => {
|
||||||
//logger.logError('登录失败(onLoginFailed)', args);
|
logger.logError.bind(logger)('[Core] [Login] Login Error , ErrInfo: ', args);
|
||||||
logger.logError('[Core] [Login] Login Error , ErrInfo: ', args);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
loginService.addKernelLoginListener(proxiedListenerOf(loginListener, logger) as any);
|
loginService.addKernelLoginListener(proxiedListenerOf(loginListener, logger) as any);
|
||||||
|
const isConnect = loginService.connect();
|
||||||
|
if (!isConnect) {
|
||||||
|
logger.logError.bind(logger)('核心登录服务连接失败!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.log('核心登录服务连接成功!');
|
||||||
// 实现WebUi快速登录
|
// 实现WebUi快速登录
|
||||||
loginService.getLoginList().then((res) => {
|
loginService.getLoginList().then((res) => {
|
||||||
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
|
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
|
||||||
WebUiDataRuntime.setQQQuickLoginList(res.LocalLoginInfoList.filter((item) => item.isQuickLogin).map((item) => item.uin.toString()));
|
WebUiDataRuntime.setQQQuickLoginList(res.LocalLoginInfoList.filter((item) => item.isQuickLogin).map((item) => item.uin.toString()));
|
||||||
});
|
});
|
||||||
|
if (basicInfoWrapper.QQVersionConfig?.curVersion) {
|
||||||
|
loginService.getLoginMiscData('hotUpdateSign').then((res) => {
|
||||||
|
if (res.result === 0) {
|
||||||
|
loginService.setLoginMiscData('hotUpdateSign', res.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
session.getNodeMiscService().writeVersionToRegistry(basicInfoWrapper.QQVersionConfig?.curVersion);
|
||||||
|
}
|
||||||
WebUiDataRuntime.setQuickLoginCall(async (uin: string) => {
|
WebUiDataRuntime.setQuickLoginCall(async (uin: string) => {
|
||||||
return await new Promise((resolve) => {
|
return await new Promise((resolve) => {
|
||||||
if (uin) {
|
if (uin) {
|
||||||
logger.log('正在快速登录 ', uin);
|
logger.log.bind(logger)('正在快速登录 ', uin);
|
||||||
loginService.quickLoginWithUin(uin).then(res => {
|
loginService.quickLoginWithUin(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 });
|
||||||
}
|
}
|
||||||
resolve({ result: true, message: '' });
|
resolve({ result: true, message: '' });
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
logger.logError(e);
|
logger.logError.bind(logger)(e);
|
||||||
resolve({ result: false, message: '快速登录发生错误' });
|
resolve({ result: false, message: '快速登录发生错误' });
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -183,15 +218,15 @@ export async function NCoreInitShell() {
|
|||||||
loginService.quickLoginWithUin(quickLoginUin)
|
loginService.quickLoginWithUin(quickLoginUin)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result.loginErrorInfo.errMsg) {
|
if (result.loginErrorInfo.errMsg) {
|
||||||
logger.logError('快速登录错误:', result.loginErrorInfo.errMsg);
|
logger.logError.bind(logger)('快速登录错误:', result.loginErrorInfo.errMsg);
|
||||||
loginService.getQRCodePicture();
|
if (!isLogined) loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch();
|
.catch();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
logger.logError('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
logger.logError.bind(logger)('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
||||||
loginService.getQRCodePicture();
|
if (!isLogined) loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log('没有 -q 指令指定快速登录,将使用二维码登录方式');
|
logger.log('没有 -q 指令指定快速登录,将使用二维码登录方式');
|
||||||
@@ -199,18 +234,30 @@ export async function NCoreInitShell() {
|
|||||||
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
||||||
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
||||||
.join('\n')
|
.join('\n')
|
||||||
}`);
|
}`);
|
||||||
}
|
}
|
||||||
loginService.getQRCodePicture();
|
loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// BEFORE LOGGING IN
|
// BEFORE LOGGING IN
|
||||||
|
let amgomDataPiece = 'eb1fd6ac257461580dc7438eb099f23aae04ca679f4d88f53072dc56e3bb1129';
|
||||||
|
o3Service.setAmgomDataPiece(basicInfoWrapper.QQVersionAppid, new Uint8Array(Buffer.from(amgomDataPiece, 'hex')));
|
||||||
// AFTER LOGGING IN
|
// AFTER LOGGING IN
|
||||||
|
//99b15bdb4c984fc69d5aa1feb9aa16xx --> 99b15bdb-4c98-4fc6-9d5a-a1feb9aa16xx
|
||||||
|
//把guid从左向右转换为guid格式 loginService.getMachineGuid()
|
||||||
|
|
||||||
|
let guid = loginService.getMachineGuid();
|
||||||
|
guid = guid.slice(0, 8) + '-' + guid.slice(8, 12) + '-' + guid.slice(12, 16) + '-' + guid.slice(16, 20) + '-' + guid.slice(20);
|
||||||
|
//console.log('guid:', guid);
|
||||||
|
//NodeIO3MiscService/reportAmgomWeather login a6 [ '1726748166943', '184', '329' ]
|
||||||
|
o3Service.reportAmgomWeather('login', 'a6', [dataTimestape, '184', '329']);
|
||||||
|
// if(session.getUnitedConfigService()){
|
||||||
|
// session.getUnitedConfigService().fetchUnitedCommendConfig([]);
|
||||||
|
// }
|
||||||
// from initSession
|
// from initSession
|
||||||
await new Promise<void>(async (resolve, reject) => {
|
await new Promise<void>(async (resolve, reject) => {
|
||||||
const sessionConfig = await genSessionConfig(
|
const sessionConfig = await genSessionConfig(
|
||||||
|
guid,
|
||||||
basicInfoWrapper.QQVersionAppid!,
|
basicInfoWrapper.QQVersionAppid!,
|
||||||
basicInfoWrapper.getFullQQVesion(),
|
basicInfoWrapper.getFullQQVesion(),
|
||||||
selfInfo.uin,
|
selfInfo.uin,
|
||||||
|
@@ -54,7 +54,7 @@ export async function InitWebUi(logger: LogWrapper, pathWrapper: NapCatPathWrapp
|
|||||||
).then((data) => {
|
).then((data) => {
|
||||||
log(`[NapCat] [WebUi] WebUi Publish Panel Url: http://${data.IP.IP}:${config.port}${config.prefix}/webui/?token=${config.token}`);
|
log(`[NapCat] [WebUi] WebUi Publish Panel Url: http://${data.IP.IP}:${config.port}${config.prefix}/webui/?token=${config.token}`);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
logger.logError(`[NapCat] [WebUi] Get Publish Panel Url Error: ${err}`);
|
logger.logError.bind(logger)(`[NapCat] [WebUi] Get Publish Panel Url Error: ${err}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
undefined,
|
undefined,
|
||||||
SettingButton('V2.4.0', 'napcat-update-button', 'secondary'),
|
SettingButton('V2.6.13', 'napcat-update-button', 'secondary'),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
void 0,
|
void 0,
|
||||||
SettingButton("V2.4.0", "napcat-update-button", "secondary")
|
SettingButton("V2.6.13", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
// import PreprocessorDirectives from 'unplugin-preprocessor-directives/vite';
|
|
||||||
import cp from 'vite-plugin-cp';
|
import cp from 'vite-plugin-cp';
|
||||||
import { defineConfig, PluginOption, UserConfig } from 'vite';
|
import { defineConfig, PluginOption, UserConfig } from 'vite';
|
||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
import nodeResolve from '@rollup/plugin-node-resolve';
|
import nodeResolve from '@rollup/plugin-node-resolve';
|
||||||
import { builtinModules } from 'module';
|
import { builtinModules } from 'module';
|
||||||
import babel from 'vite-plugin-babel';
|
|
||||||
//依赖排除
|
//依赖排除
|
||||||
const external = ['silk-wasm', 'ws', 'express', 'fluent-ffmpeg', 'log4js', 'qrcode-terminal'];
|
const external = ['silk-wasm', 'ws', 'express', 'fluent-ffmpeg', 'log4js', 'qrcode-terminal'];
|
||||||
const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat();
|
const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat();
|
||||||
@@ -15,31 +13,15 @@ let startScripts: string[] | undefined = undefined;
|
|||||||
if (process.env.NAPCAT_BUILDSYS == 'linux') {
|
if (process.env.NAPCAT_BUILDSYS == 'linux') {
|
||||||
if (process.env.NAPCAT_BUILDARCH == 'x64') {
|
if (process.env.NAPCAT_BUILDARCH == 'x64') {
|
||||||
}
|
}
|
||||||
startScripts = ['./script/napcat.sh'];
|
startScripts = [];
|
||||||
} else if (process.env.NAPCAT_BUILDSYS == 'win32') {
|
} else if (process.env.NAPCAT_BUILDSYS == 'win32') {
|
||||||
if (process.env.NAPCAT_BUILDARCH == 'x64') {
|
if (process.env.NAPCAT_BUILDARCH == 'x64') {
|
||||||
}
|
}
|
||||||
startScripts = ['./script/BootWay05.ps1', './script/dbghelp.dll',
|
startScripts = ['./script/KillQQ.bat'];
|
||||||
'./script/BootWay05_init.bat', './script/BootWay05_run.bat', './script/BootWay05_run.utf8.bat', './script/KillQQ.bat'];
|
|
||||||
} else {
|
} else {
|
||||||
startScripts = ['./script/BootWay05.ps1', './script/dbghelp.dll',
|
startScripts = ['./script/KillQQ.bat'];
|
||||||
'./script/BootWay05_init.bat', './script/BootWay05_run.bat', './script/BootWay05_run.utf8.bat', './script/KillQQ.bat'];
|
|
||||||
}
|
}
|
||||||
const FrameworkBaseConfigPlugin: PluginOption[] = [
|
const FrameworkBaseConfigPlugin: PluginOption[] = [
|
||||||
// PreprocessorDirectives(),
|
|
||||||
babel({
|
|
||||||
filter: /.*\.(ts|js)$/,
|
|
||||||
babelConfig: {
|
|
||||||
babelrc: false,
|
|
||||||
configFile: false,
|
|
||||||
presets: ['@babel/preset-typescript'],
|
|
||||||
plugins: [
|
|
||||||
//'2018-09', decoratorsBeforeExport: true
|
|
||||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
|
||||||
'@babel/plugin-proposal-class-properties',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
cp({
|
cp({
|
||||||
targets: [
|
targets: [
|
||||||
{ src: './manifest.json', dest: 'dist' },
|
{ src: './manifest.json', dest: 'dist' },
|
||||||
@@ -52,38 +34,18 @@ const FrameworkBaseConfigPlugin: PluginOption[] = [
|
|||||||
{ src: './src/framework/renderer.js', dest: 'dist' },
|
{ src: './src/framework/renderer.js', dest: 'dist' },
|
||||||
{ src: './package.json', dest: 'dist' },
|
{ src: './package.json', dest: 'dist' },
|
||||||
{ src: './logo.png', dest: 'dist' },
|
{ src: './logo.png', dest: 'dist' },
|
||||||
//...external.map(genCpModule)
|
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
nodeResolve(),
|
nodeResolve(),
|
||||||
];
|
];
|
||||||
const ShellBaseConfigPlugin: PluginOption[] = [
|
const ShellBaseConfigPlugin: PluginOption[] = [
|
||||||
// PreprocessorDirectives(),
|
|
||||||
babel({
|
|
||||||
filter: /.*\.(ts|js)$/,
|
|
||||||
babelConfig: {
|
|
||||||
babelrc: false,
|
|
||||||
configFile: false,
|
|
||||||
presets: ['@babel/preset-typescript'],
|
|
||||||
plugins: [
|
|
||||||
//'2018-09', decoratorsBeforeExport: true
|
|
||||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
|
||||||
'@babel/plugin-proposal-class-properties',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
cp({
|
cp({
|
||||||
targets: [
|
targets: [
|
||||||
// ...external.map(genCpModule),
|
|
||||||
// { src: './src/napcat.json', dest: 'dist/config/' },
|
|
||||||
{ src: './static/', dest: 'dist/static/', flatten: false },
|
{ src: './static/', dest: 'dist/static/', flatten: false },
|
||||||
// { src: './src/onebot11/onebot11.json', dest: 'dist/config/' },
|
|
||||||
{ src: './src/core/external/napcat.json', dest: 'dist/config/' },
|
{ src: './src/core/external/napcat.json', dest: 'dist/config/' },
|
||||||
{ src: './src/onebot/config/onebot11.json', dest: 'dist/config/' },
|
{ src: './src/onebot/config/onebot11.json', dest: 'dist/config/' },
|
||||||
{ src: './package.json', dest: 'dist' },
|
{ src: './package.json', dest: 'dist' },
|
||||||
{ src: './launcher/', dest: 'dist', flatten: true },
|
{ src: './launcher/', dest: 'dist', flatten: true },
|
||||||
// { src: './README.md', dest: 'dist' },
|
|
||||||
// { src: './logo.png', dest: 'dist/logs' },
|
|
||||||
...(startScripts.map((startScript) => {
|
...(startScripts.map((startScript) => {
|
||||||
return { src: startScript, dest: 'dist' };
|
return { src: startScript, dest: 'dist' };
|
||||||
})),
|
})),
|
||||||
|
Reference in New Issue
Block a user