mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a582026037 | ||
![]() |
1a67a001c5 | ||
![]() |
406deac592 | ||
![]() |
e719ae0676 | ||
![]() |
d8b7726440 | ||
![]() |
49f642e712 | ||
![]() |
70117016ce | ||
![]() |
a4738f6281 | ||
![]() |
b1fc72d696 | ||
![]() |
457c2c2b50 | ||
![]() |
48848d7d1a | ||
![]() |
55b07ca3ab | ||
![]() |
a1d4882e18 | ||
![]() |
3843795d8f | ||
![]() |
f2bf8d42da | ||
![]() |
a3b244e114 | ||
![]() |
3093bdbc68 | ||
![]() |
9ab0799283 | ||
![]() |
236bec11ed | ||
![]() |
de48b0f940 | ||
![]() |
4885d4db86 | ||
![]() |
0c7bbda936 | ||
![]() |
fa07c2c1fb | ||
![]() |
5d17a191f6 | ||
![]() |
d61d481965 | ||
![]() |
d0f248aaf9 | ||
![]() |
85c9227515 | ||
![]() |
eb4828d81f | ||
![]() |
640e3516d4 | ||
![]() |
bd295a4632 | ||
![]() |
66656304f9 | ||
![]() |
07f66e379d | ||
![]() |
7275066994 | ||
![]() |
385adec186 | ||
![]() |
6a9ec4e5f0 | ||
![]() |
efdb520414 | ||
![]() |
2cae30ba88 | ||
![]() |
3300304feb | ||
![]() |
16f7bb48f2 | ||
![]() |
7f383dd29b | ||
![]() |
45dedb4872 |
Binary file not shown.
Binary file not shown.
@@ -9,7 +9,7 @@ if %errorLevel% == 0 (
|
|||||||
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
|
||||||
|
@@ -9,7 +9,7 @@ if %errorLevel% == 0 (
|
|||||||
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
|
||||||
|
@@ -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-28060",
|
||||||
|
"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": "28060",
|
||||||
|
"isPureShell": true,
|
||||||
|
"isByteCodeShell": true,
|
||||||
|
"platform": "win32",
|
||||||
|
"eleArch": "x64"
|
||||||
|
}
|
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "2.5.3",
|
"version": "2.6.3",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
13
package.json
13
package.json
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.5.3",
|
"version": "2.6.3",
|
||||||
"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"
|
||||||
|
@@ -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.
@@ -45,9 +45,9 @@ async function handleWavFile(
|
|||||||
): Promise<{input: Buffer, sampleRate: number}> {
|
): Promise<{input: Buffer, sampleRate: number}> {
|
||||||
const { fmt } = getWavFileInfo(file);
|
const { fmt } = getWavFileInfo(file);
|
||||||
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
|
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
|
||||||
return {input: await convert(filePath, pcmPath, logger), sampleRate: 24000};
|
return { input: await convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
||||||
}
|
}
|
||||||
return {input: file, sampleRate: fmt.sampleRate};
|
return { input: file, sampleRate: fmt.sampleRate };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) {
|
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) {
|
||||||
@@ -59,7 +59,7 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
|||||||
const pcmPath = `${pttPath}.pcm`;
|
const pcmPath = `${pttPath}.pcm`;
|
||||||
const { input, sampleRate } = isWav(file)
|
const { input, sampleRate } = isWav(file)
|
||||||
? (await handleWavFile(file, filePath, pcmPath, logger))
|
? (await handleWavFile(file, filePath, pcmPath, logger))
|
||||||
: {input: await convert(filePath, pcmPath, logger), sampleRate: 24000};
|
: { input: await convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
||||||
const silk = await encode(input, sampleRate);
|
const silk = await encode(input, sampleRate);
|
||||||
await fsPromise.writeFile(pttPath, silk.data);
|
await fsPromise.writeFile(pttPath, silk.data);
|
||||||
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
||||||
|
@@ -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
|
|
@@ -183,11 +183,11 @@ export class NTEventWrapper {
|
|||||||
timeout = 5000,
|
timeout = 5000,
|
||||||
) {
|
) {
|
||||||
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(
|
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(
|
||||||
async (resolve, reject) => {
|
(resolve, reject) => {
|
||||||
const id = randomUUID();
|
const id = randomUUID();
|
||||||
let complete = 0;
|
let complete = 0;
|
||||||
let retData: Parameters<ListenerType> | undefined = undefined;
|
let retData: Parameters<ListenerType> | undefined = undefined;
|
||||||
let retEvent: any = {};
|
const retEvent: any = {};
|
||||||
|
|
||||||
function sendDataCallback() {
|
function sendDataCallback() {
|
||||||
if (complete == 0) {
|
if (complete == 0) {
|
||||||
@@ -235,56 +235,12 @@ export class NTEventWrapper {
|
|||||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallback);
|
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallback);
|
||||||
this.createListenerFunction(ListenerMainName);
|
this.createListenerFunction(ListenerMainName);
|
||||||
const eventFunction = this.createEventFunction(serviceAndMethod);
|
const eventFunction = this.createEventFunction(serviceAndMethod);
|
||||||
retEvent = await eventFunction!(...(args));
|
if (eventFunction) eventFunction(...(args)).then((retEvent: Awaited<ReturnType<EventType>>) => {
|
||||||
if (!checkerEvent(retEvent)) {
|
if (!checkerEvent(retEvent) && timeoutRef.hasRef()) {
|
||||||
clearTimeout(timeoutRef);
|
clearTimeout(timeoutRef);
|
||||||
reject(
|
|
||||||
new Error(
|
|
||||||
'EventChecker Failed: NTEvent serviceAndMethod:' +
|
|
||||||
serviceAndMethod +
|
|
||||||
' ListenerName:' +
|
|
||||||
listenerAndMethod +
|
|
||||||
' EventRet:\n' +
|
|
||||||
JSON.stringify(retEvent, null, 4) +
|
|
||||||
'\n',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
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(
|
reject(
|
||||||
new Error(
|
new Error(
|
||||||
'Timeout: NTEvent EventName:' +
|
'EventChecker Failed: NTEvent serviceAndMethod:' +
|
||||||
serviceAndMethod +
|
serviceAndMethod +
|
||||||
' ListenerName:' +
|
' ListenerName:' +
|
||||||
listenerAndMethod +
|
listenerAndMethod +
|
||||||
@@ -293,43 +249,9 @@ export class NTEventWrapper {
|
|||||||
'\n',
|
'\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,12 +123,11 @@ 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> = {
|
||||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36',
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36',
|
||||||
'referer': typeof options === 'string' ? options : options.url,
|
|
||||||
};
|
};
|
||||||
if (typeof options === 'string') {
|
if (typeof options === 'string') {
|
||||||
url = options;
|
url = options;
|
||||||
@@ -143,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);
|
||||||
}
|
}
|
||||||
|
@@ -163,8 +163,8 @@ export function isEqual(obj1: any, obj2: any) {
|
|||||||
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
||||||
if (os.platform() === 'linux') {
|
if (os.platform() === 'linux') {
|
||||||
return {
|
return {
|
||||||
baseVersion: '3.2.12.27254',
|
baseVersion: '3.2.12.28060',
|
||||||
curVersion: '3.2.12.27254',
|
curVersion: '3.2.12.28060',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '27254',
|
buildId: '27254',
|
||||||
@@ -172,34 +172,42 @@ export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
|||||||
}
|
}
|
||||||
if (os.platform() === 'darwin') {
|
if (os.platform() === 'darwin') {
|
||||||
return {
|
return {
|
||||||
baseVersion: '6.9.53.27597',
|
baseVersion: '6.9.53.28060',
|
||||||
curVersion: '6.9.53.27597',
|
curVersion: '6.9.53.28060',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '27597',
|
buildId: '28060',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
baseVersion: '9.9.15-27597',
|
baseVersion: '9.9.15-28060',
|
||||||
curVersion: '9.9.15-27597',
|
curVersion: '9.9.15-28060',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '27597',
|
buildId: '28060',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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');
|
||||||
@@ -212,6 +220,10 @@ 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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
@@ -53,23 +55,23 @@ export class QQBasicInfoWrapper {
|
|||||||
//此方法不要直接使用
|
//此方法不要直接使用
|
||||||
getQUAInternal() {
|
getQUAInternal() {
|
||||||
switch (systemPlatform) {
|
switch (systemPlatform) {
|
||||||
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`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getAppidInternal() {
|
getAppidInternal() {
|
||||||
switch (systemPlatform) {
|
switch (systemPlatform) {
|
||||||
case 'linux':
|
case 'linux':
|
||||||
return '537240795';
|
return '537246140';
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
return '537243538';
|
return '537246140';
|
||||||
default:
|
default:
|
||||||
return '537243441';
|
return '537246092';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '2.5.3';
|
export const napCatVersion = '2.6.3';
|
||||||
|
27
src/core/external/appid.json
vendored
27
src/core/external/appid.json
vendored
@@ -1,29 +1,10 @@
|
|||||||
{
|
{
|
||||||
|
|
||||||
"3.2.12-27254":{
|
|
||||||
"appid": 537240795,
|
|
||||||
"qua": "V1_LNX_NQ_3.2.12_27254_GW_B"
|
|
||||||
},
|
|
||||||
"9.9.15-27254":{
|
|
||||||
"appid": 537240709,
|
|
||||||
"qua": "V1_WIN_NQ_9.9.15_27254_GW_B"
|
|
||||||
},
|
|
||||||
|
|
||||||
"3.2.12-27597": {
|
|
||||||
"appid": 537243600,
|
|
||||||
"qua": "V1_LNX_NQ_3.2.12_27597_GW_B"
|
|
||||||
},
|
|
||||||
"9.9.15-27597": {
|
|
||||||
"appid": 537243441,
|
|
||||||
"qua": "V1_WIN_NQ_9.9.15_27597_GW_B"
|
|
||||||
},
|
|
||||||
"6.9.53-27597": {
|
|
||||||
"appid": 537243538,
|
|
||||||
"qua": "V1_MAC_NQ_6.9.53_27597_GW_B"
|
|
||||||
},
|
|
||||||
|
|
||||||
"9.9.15-28060":{
|
"9.9.15-28060":{
|
||||||
"appid": 537246092,
|
"appid": 537246092,
|
||||||
"qua": "V1_WIN_NQ_9.9.15_28060_GW_B"
|
"qua": "V1_WIN_NQ_9.9.15_28060_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.12-28060":{
|
||||||
|
"appid": 537246140,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.12_28060_GW_B"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
@@ -59,9 +59,9 @@ export interface QuickLoginResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeIKernelLoginService {
|
export interface NodeIKernelLoginService {
|
||||||
|
get(): NodeIKernelLoginService;
|
||||||
|
|
||||||
connect(): boolean;
|
connect(): boolean;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(): NodeIKernelLoginService;
|
|
||||||
|
|
||||||
addKernelLoginListener(listener: NodeIKernelLoginListener): number;
|
addKernelLoginListener(listener: NodeIKernelLoginListener): number;
|
||||||
|
|
||||||
|
@@ -143,9 +143,8 @@ 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,
|
||||||
nodeIDependsAdapter: NodeIDependsAdapter,
|
nodeIDependsAdapter: NodeIDependsAdapter,
|
||||||
|
@@ -23,7 +23,7 @@ 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());
|
||||||
let uids = groupMembersArr.map(item => item.uid);
|
const uids = groupMembersArr.map(item => item.uid);
|
||||||
//let CoreAndBase = await this.core.apis.GroupApi.getCoreAndBaseInfo(uids)
|
//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);
|
||||||
|
@@ -574,9 +574,10 @@ export class OneBotMsgApi {
|
|||||||
} 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);
|
||||||
@@ -609,7 +610,7 @@ export class OneBotMsgApi {
|
|||||||
[OB11MessageDataType.miniapp]: async () => undefined,
|
[OB11MessageDataType.miniapp]: async () => undefined,
|
||||||
|
|
||||||
[OB11MessageDataType.contact]: async ({ data }, context) => {
|
[OB11MessageDataType.contact]: async ({ data }, context) => {
|
||||||
let arkJson = await this.core.apis.UserApi.getBuddyRecommendContactArkJson(data.qq, '');
|
const arkJson = await this.core.apis.UserApi.getBuddyRecommendContactArkJson(data.id.toString(), '');
|
||||||
return this.ob11ToRawConverters.json({
|
return this.ob11ToRawConverters.json({
|
||||||
data: { data: arkJson.arkMsg },
|
data: { data: arkJson.arkMsg },
|
||||||
type: OB11MessageDataType.json
|
type: OB11MessageDataType.json
|
||||||
|
@@ -48,8 +48,8 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
//鉴权
|
//鉴权
|
||||||
this.authorize(token, wsClient, wsReq);
|
this.authorize(token, wsClient, wsReq);
|
||||||
const paramUrl = wsReq.url?.indexOf('?') !== -1 ? wsReq.url?.substring(0, wsReq.url?.indexOf('?')) : wsReq.url;
|
const paramUrl = wsReq.url?.indexOf('?') !== -1 ? wsReq.url?.substring(0, wsReq.url?.indexOf('?')) : wsReq.url;
|
||||||
const isEventConnect = paramUrl === '/event' || paramUrl === '' || paramUrl === '/';
|
const isApiConnect = paramUrl === '/api' || paramUrl === '/api/';
|
||||||
if (isEventConnect) {
|
if (!isApiConnect) {
|
||||||
this.connectEvent(core, wsClient);
|
this.connectEvent(core, wsClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
await this.wsClientsMutex.runExclusive(async () => {
|
await this.wsClientsMutex.runExclusive(async () => {
|
||||||
if(isEventConnect){
|
if (!isApiConnect) {
|
||||||
this.wsClientWithEvent.push(wsClient);
|
this.wsClientWithEvent.push(wsClient);
|
||||||
}
|
}
|
||||||
this.wsClients.push(wsClient);
|
this.wsClients.push(wsClient);
|
||||||
|
@@ -85,7 +85,7 @@ export interface OB11MessageText {
|
|||||||
export interface OB11MessageContext {
|
export interface OB11MessageContext {
|
||||||
type: OB11MessageDataType.contact,
|
type: OB11MessageDataType.contact,
|
||||||
data: {
|
data: {
|
||||||
qq: string,
|
id: string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export interface OB11MessageFileBase {
|
export interface OB11MessageFileBase {
|
||||||
|
@@ -45,8 +45,8 @@ export async function NCoreInitShell() {
|
|||||||
// from constructor
|
// from constructor
|
||||||
const engine = new wrapper.NodeIQQNTWrapperEngine();
|
const engine = new wrapper.NodeIQQNTWrapperEngine();
|
||||||
//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] = (() => {
|
||||||
@@ -103,18 +103,21 @@ export async function NCoreInitShell() {
|
|||||||
|
|
||||||
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(`当前账号(${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
|
||||||
@@ -138,11 +141,13 @@ 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);
|
//logger.logError('登录失败(onQRCodeSessionFailed)', errCode, errMsg);
|
||||||
logger.logError('[Core] [Login] Login Error,ErrCode: ', errCode, ' ErrMsg:', errMsg);
|
if (!isLogined) {
|
||||||
if (errType == 1 && errCode == 3) {
|
logger.logError('[Core] [Login] Login Error,ErrCode: ', errCode, ' ErrMsg:', errMsg);
|
||||||
// 二维码过期刷新
|
if (errType == 1 && errCode == 3) {
|
||||||
|
// 二维码过期刷新
|
||||||
|
}
|
||||||
|
loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
loginService.getQRCodePicture();
|
|
||||||
};
|
};
|
||||||
loginListener.onLoginFailed = (args) => {
|
loginListener.onLoginFailed = (args) => {
|
||||||
//logger.logError('登录失败(onLoginFailed)', args);
|
//logger.logError('登录失败(onLoginFailed)', args);
|
||||||
@@ -189,14 +194,14 @@ export async function NCoreInitShell() {
|
|||||||
.then(result => {
|
.then(result => {
|
||||||
if (result.loginErrorInfo.errMsg) {
|
if (result.loginErrorInfo.errMsg) {
|
||||||
logger.logError('快速登录错误:', result.loginErrorInfo.errMsg);
|
logger.logError('快速登录错误:', result.loginErrorInfo.errMsg);
|
||||||
loginService.getQRCodePicture();
|
if (!isLogined) loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch();
|
.catch();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
logger.logError('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
logger.logError('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
||||||
loginService.getQRCodePicture();
|
if (!isLogined) loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log('没有 -q 指令指定快速登录,将使用二维码登录方式');
|
logger.log('没有 -q 指令指定快速登录,将使用二维码登录方式');
|
||||||
|
@@ -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.5.3', 'napcat-update-button', 'secondary'),
|
SettingButton('V2.6.3', '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.5.3", "napcat-update-button", "secondary")
|
SettingButton("V2.6.3", "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