Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
linyuchen committed May 15, 2024
2 parents d14ba3f + dc39da8 commit dc6951c
Show file tree
Hide file tree
Showing 81 changed files with 1,013 additions and 639 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
end_of_line = lf|crlf
insert_final_newline = true

# Matches multiple files with brace expansion notation
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ jobs:
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV

- name: Clone Changes Log
run: curl -o CHANGELOG.md https://fastly.jsdelivr.net/gh/NapNeko/NapCatQQ@main/CHANGELOG.md
run: curl -o CHANGELOG.md https://fastly.jsdelivr.net/gh/NapNeko/NapCatQQ@main/docs/CHANGELOG.v${{ env.VERSION }}.md

- name: Create Release Draft and Upload Artifacts
uses: softprops/action-gh-release@v1
Expand Down
15 changes: 15 additions & 0 deletions docs/changelogs/CHANGELOG.v1.3.5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# v1.3.5

QQ Version: Windows 9.9.9-23424 / Linux 3.2.7-23361

## 修复与优化
* 优化启动脚本
* 修复非管理时群成员减少事件上报 **无法获取操作者与操作类型**
* 修复快速重启进程清理问题
* 优化配置文件格式 **注意备份配置**
## 新增与调整
* 支持WebUi热重载
* 新增首次启动输出webui秘钥
* 新增群荣誉信息 /get_group_honor_info

新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
53 changes: 41 additions & 12 deletions script/checkVersion.cjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@
let fs = require("fs");
let process = require("process")
const fs = require("fs");
const process = require("process");

console.log("[NapCat] [CheckVersion] 开始检测当前仓库版本...");
let currentVersion = require("../package.json").version;
let targetVersion = process.env.VERSION;
console.log("[NapCat] [CheckVersion] currentVersion:", currentVersion, " targetVersion:", targetVersion);
// fs.mkdirSync("./dist");
if (currentVersion === targetVersion) {
fs.writeFileSync("./checkVersion.sh", "#!/bin/bashe\necho \"CheckVersion Is Done\"")
} else {
let runscript = "sed -i 's/\"version\": \"" + currentVersion + "\"/\"version\": \"" + targetVersion + "\"/g' package.json";
fs.writeFileSync("./checkVersion.sh", "#!/bin/bashe\ngit config --global user.email \"[email protected]\"\n git config --global user.name \"Version\"\n" + runscript + "\ngit add .\n git commit -m \"chore:version change\"\n git push -u origin main")
}
try {
const packageJson = require("../package.json");
const currentVersion = packageJson.version;
const targetVersion = process.env.VERSION;

console.log("[NapCat] [CheckVersion] currentVersion:", currentVersion, "targetVersion:", targetVersion);

// 验证 targetVersion 格式
if (!targetVersion || typeof targetVersion !== 'string') {
console.error("[NapCat] [CheckVersion] 目标版本格式不正确或未设置!");
return;
}

// 写入脚本文件的统一函数
const writeScriptToFile = (content) => {
fs.writeFileSync("./checkVersion.sh", content, { flag: 'w' });
console.log("[NapCat] [CheckVersion] checkVersion.sh 文件已更新。");
};

if (currentVersion === targetVersion) {
// 不需要更新版本,写入一个简单的脚本
const simpleScript = "#!/bin/bash\necho \"CheckVersion Is Done\"";
writeScriptToFile(simpleScript);
} else {
// 更新版本,构建安全的sed命令
const safeScriptContent = `
#!/bin/bash
git config --global user.email "[email protected]"
git config --global user.name "Version"
sed -i "s/\\\"version\\\": \\\"${currentVersion}\\\"/\\\"version\\\": \\\"${targetVersion}\\\"/g" package.json
git add .
git commit -m "chore:version change"
git push -u origin main`;
writeScriptToFile(safeScriptContent);
}
} catch (error) {
console.error("[NapCat] [CheckVersion] 检测过程中发生错误:", error);
}
23 changes: 18 additions & 5 deletions script/napcat-utf8.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@ function Get-QQpath {
$key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ"
$uninstallString = $key.UninstallString
return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe"
}
catch {
return "D:\QQ.exe"
} catch {
throw "get QQ path error: $_"
}
}
$params = $args -join " "
$QQpath = Get-QQpath
Try {
$QQpath = Get-QQpath
} Catch {
$QQpath = Read-Host -Prompt "select QQ path"
if (!$QQpath) {
Write-Host "not select QQ path, exit"
exit
}
}

if (!(Test-Path $QQpath)) {
throw "provided QQ path is invalid: $QQpath"
}

$Bootfile = Join-Path $PSScriptRoot "napcat.cjs"
$env:ELECTRON_RUN_AS_NODE = 1
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& '$QQpath' $Bootfile $params}"
$commandInfo = Get-Command $QQpath -ErrorAction Stop
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& '$($commandInfo.Path)' $Bootfile $params}"
23 changes: 18 additions & 5 deletions script/napcat.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@ function Get-QQpath {
$key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ"
$uninstallString = $key.UninstallString
return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe"
}
catch {
return "D:\QQ.exe"
} catch {
throw "get QQ path error: $_"
}
}
$params = $args -join " "
$QQpath = Get-QQpath
Try {
$QQpath = Get-QQpath
} Catch {
$QQpath = Read-Host -Prompt "select QQ path"
if (!$QQpath) {
Write-Host "not select QQ path, exit"
exit
}
}

if (!(Test-Path $QQpath)) {
throw "provided QQ path is invalid: $QQpath"
}

$Bootfile = Join-Path $PSScriptRoot "napcat.cjs"
$env:ELECTRON_RUN_AS_NODE = 1
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& '$QQpath' $Bootfile $params}"
$commandInfo = Get-Command $QQpath -ErrorAction Stop
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& '$($commandInfo.Path)' $Bootfile $params}"
21 changes: 19 additions & 2 deletions script/napcat.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
#!/bin/bash
SCRIPT_DIR=$(realpath $(dirname "${BASH_SOURCE[0]}"))

get_script_dir() {
local script_path="${1:-$0}"
local script_dir
script_path=$(readlink -f "$script_path")
script_dir=$(dirname "$script_path")

echo "$script_dir"
}

SCRIPT_DIR=$(get_script_dir)

export ELECTRON_RUN_AS_NODE=1
/opt/QQ/qq ${SCRIPT_DIR}/napcat.cjs $@

if ! [ -x /opt/QQ/qq ]; then
echo "Error: /opt/QQ/qq is not executable or does not exist." >&2
exit 1
fi

/opt/QQ/qq "${SCRIPT_DIR}/napcat.cjs" "$@"
29 changes: 18 additions & 11 deletions src/common/utils/reboot.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
import { exit } from "process";
import { resolve } from "path";
import { resolve } from "node:path";
import { spawn } from "node:child_process";
import { sleep } from "./helper";

import { pid, ppid, exit } from 'node:process';
export async function rebootWithQuickLogin(uin: string) {
let batScript = resolve(__dirname, './napcat.bat');
let batUtf8Script = resolve(__dirname, './napcat-utf8.bat');
let bashScript = resolve(__dirname, './napcat.sh');
if (process.platform === 'win32') {
let subProcess = spawn(`start ${batUtf8Script} -q ${uin}`, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore'});
const subProcess = spawn(`start ${batUtf8Script} -q ${uin}`, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' });
subProcess.unref();
// 子父进程一起送走 有点效果
spawn('cmd /c taskkill /t /f /pid ' + pid.toString(), { detached: true, shell: true, stdio: 'ignore' });
spawn('cmd /c taskkill /t /f /pid ' + ppid.toString(), { detached: true, shell: true, stdio: 'ignore' });
} else if (process.platform === 'linux') {
let subProcess = spawn(`${bashScript} -q ${uin}`, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' });
const subProcess = spawn(`${bashScript} -q ${uin}`, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' });
//还没兼容
subProcess.unref();
exit(0);
}
exit(0);
//exit(0);
}
export async function rebootWithNormolLogin() {
let batScript = resolve(__dirname, './napcat.bat');
let batUtf8Script = resolve(__dirname, './napcat-utf8.bat');
let bashScript = resolve(__dirname, './napcat.sh');
if (process.platform === 'win32') {
spawn(`start ${batUtf8Script}`, { detached: true, windowsHide: false, env: process.env, shell: true });
const subProcess = spawn(`start ${batUtf8Script} `, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' });
subProcess.unref();
// 子父进程一起送走 有点效果
spawn('cmd /c taskkill /t /f /pid ' + pid.toString(), { detached: true, shell: true, stdio: 'ignore' });
spawn('cmd /c taskkill /t /f /pid ' + ppid.toString(), { detached: true, shell: true, stdio: 'ignore' });
} else if (process.platform === 'linux') {
spawn(`${bashScript}`, { detached: true, windowsHide: false, env: process.env, shell: true });
const subProcess = spawn(`${bashScript}`, { detached: true, windowsHide: false, env: process.env, shell: true });
subProcess.unref();
exit(0);
}
await sleep(500);
exit(0);
}
120 changes: 73 additions & 47 deletions src/common/utils/request.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,83 @@
const https = require('node:https');
export async function HttpGetCookies(url: string): Promise<Map<string, string>> {
return new Promise((resolve, reject) => {
const result: Map<string, string> = new Map<string, string>();
const req = https.get(url, (res: any) => {
res.on('data', (data: any) => {
});
res.on('end', () => {
try {
const responseCookies = res.headers['set-cookie'];
for (const line of responseCookies) {
const parts = line.split(';');
const [key, value] = parts[0].split('=');
result.set(key, value);
}
} catch (e) {
}
resolve(result);
import https from 'node:https';
import http from 'node:http';

export class RequestUtil {
// 适用于获取服务器下发cookies时获取,仅GET
static async HttpsGetCookies(url: string): Promise<Map<string, string>> {
return new Promise<Map<string, string>>((resolve, reject) => {
const protocol = url.startsWith('https://') ? https : http;
protocol.get(url, (res) => {
const cookiesHeader = res.headers['set-cookie'];
if (!cookiesHeader) {
resolve(new Map<string, string>());
} else {
const cookiesMap = new Map<string, string>();
cookiesHeader.forEach((cookieStr) => {
cookieStr.split(';').forEach((cookiePart) => {
const trimmedPart = cookiePart.trim();
if (trimmedPart.includes('=')) {
const [key, value] = trimmedPart.split('=').map(part => part.trim());
cookiesMap.set(key, decodeURIComponent(value)); // 解码cookie值
}
});
});
resolve(cookiesMap);
}
}).on('error', (error) => {
reject(error);
});
});
req.on('error', (error: any) => {
resolve(result);
// console.log(error)
});
req.end();
});
}

}
export async function HttpPostCookies(url: string): Promise<Map<string, string>> {
return new Promise((resolve, reject) => {
const result: Map<string, string> = new Map<string, string>();
const req = https.get(url, (res: any) => {
res.on('data', (data: any) => {
});
res.on('end', () => {
try {
const responseCookies = res.headers['set-cookie'];
for (const line of responseCookies) {
const parts = line.split(';');
const [key, value] = parts[0].split('=');
result.set(key, value);
// 请求和回复都是JSON data传原始内容 自动编码json
static async HttpGetJson<T>(url: string, method: string = 'GET', data?: any, headers: Record<string, string> = {}, isJsonRet: boolean = true): Promise<T> {
let option = new URL(url);
const protocol = url.startsWith('https://') ? https : http;
const options = {
hostname: option.hostname,
port: option.port,
path: option.href,
method: method,
headers: headers
};
return new Promise((resolve, reject) => {
const req = protocol.request(options, (res: any) => {
let responseBody = '';
res.on('data', (chunk: string | Buffer) => {
responseBody += chunk.toString();
});

res.on('end', () => {
try {
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
if (isJsonRet) {
const responseJson = JSON.parse(responseBody);
resolve(responseJson as T);
} else {
resolve(responseBody as T);
}
} else {
reject(new Error(`Unexpected status code: ${res.statusCode}`));
}
} catch (parseError) {
reject(parseError);
}
} catch (e) {
}
resolve(result);
});
});

req.on('error', (error: any) => {
reject(error);
});
if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
req.write(JSON.stringify(data));
}
req.end();
});
req.on('error', (error: any) => {
resolve(result);
// console.log(error)
});
req.end();
});
}

// 请求返回都是原始内容
static async HttpGetText(url: string, method: string = 'GET', data?: any, headers: Record<string, string> = {}) {
//console.log(url);
return this.HttpGetJson<string>(url, method, data, headers, false);
}
}
Loading

0 comments on commit dc6951c

Please sign in to comment.