Compare commits

...

14 Commits

Author SHA1 Message Date
手瓜一十雪
75f67caa1b release: v2.0.23 2024-08-15 18:46:26 +08:00
手瓜一十雪
d760ce54b7 chore: 重构文件处理 2024-08-15 18:44:29 +08:00
手瓜一十雪
956976ebd5 fix 2024-08-15 17:10:18 +08:00
手瓜一十雪
f9c2d4ca6c fix 2024-08-15 17:07:26 +08:00
手瓜一十雪
dd5cc3c38c fix 2024-08-15 17:04:34 +08:00
手瓜一十雪
daed4cc13e fix 2024-08-15 17:03:55 +08:00
手瓜一十雪
6ff614dd18 fix 2024-08-15 16:56:03 +08:00
手瓜一十雪
eb70ac4266 release 2024-08-15 16:51:31 +08:00
手瓜一十雪
a3a431adb7 fix 2024-08-15 16:45:24 +08:00
手瓜一十雪
e12c72ab98 action fix 2024-08-15 16:41:47 +08:00
手瓜一十雪
9f8549b831 build: 2.0.22 2024-08-15 16:34:50 +08:00
手瓜一十雪
b2de256f87 release: 2.0.22 2024-08-15 16:15:33 +08:00
手瓜一十雪
7f32a5cf9e build: test 2024-08-15 12:28:51 +08:00
手瓜一十雪
56f8314d29 chore: 进一步清理无用代码 2024-08-15 11:10:02 +08:00
11 changed files with 99 additions and 143 deletions

View File

@@ -98,11 +98,16 @@ jobs:
- name: Compress subdirectories
run: |
for dir in */; do
base=$(basename "$dir")
zip -r "${base}.zip" "$dir"
done
cd ./NapCat.Shell/
zip -q -r NapCat.Shell.zip *
cd ..
cd ./NapCat.Framework/
zip -q -r NapCat.Framework.zip *
cd ..
rm ./NapCat.Shell.zip -rf
rm ./NapCat.Framework.zip -rf
mv ./NapCat.Shell/NapCat.Shell.zip ./
mv ./NapCat.Framework/NapCat.Framework.zip ./
- name: Extract version from tag
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
@@ -118,6 +123,4 @@ jobs:
files: |
NapCat.Framework.zip
NapCat.Shell.zip
# NapCat.darwin.x64.zip
# NapCat.darwin.arm64.zip
draft: true

View File

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

View File

@@ -2,7 +2,7 @@
"name": "napcat",
"private": true,
"type": "module",
"version": "2.0.21",
"version": "2.0.23",
"scripts": {
"build:framework": "vite build --mode framework",
"build:shell": "vite build --mode shell",

View File

@@ -2,7 +2,7 @@ import path, { dirname } from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
export const napcat_version = '2.0.21';
export const napcat_version = '2.0.23';
export class NapCatPathWrapper {
binaryPath: string;

View File

@@ -165,118 +165,98 @@ type Uri2LocalRes = {
path: string,
isLocal: boolean
}
export async function uri2local(TempDir: string, UriOrPath: string, fileName: string | null = null): Promise<Uri2LocalRes> {
const res = {
success: false,
errMsg: '',
fileName: '',
ext: '',
path: '',
isLocal: false,
};
if (!fileName) fileName = randomUUID();
let filePath = path.join(TempDir, fileName);//临时目录
let url = null;
//区分path和uri
export async function checkFileV2(filePath: string) {
try {
if (fs.existsSync(UriOrPath)) url = new URL('file://' + UriOrPath);
} catch (error: any) {
const ext: string | undefined = (await fileType.fileTypeFromFile(filePath))?.ext;
if (ext) {
fs.renameSync(filePath, filePath + `.${ext}`);
filePath += `.${ext}`;
return { success: true, ext: ext, path: filePath };
}
} catch (e) {
// log("获取文件类型失败", filePath,e.stack)
}
return { success: false, ext: '', path: filePath };
}
export enum FileUriType {
Unknown = 0,
Local = 1,
Remote = 2,
Base64 = 3
}
export async function checkUriType(Uri: string) {
//先判断是否是本地文件
try {
if (fs.existsSync(Uri)) return { Uri: Uri, Type: FileUriType.Local };
} catch (error) {
}
try {
url = new URL(UriOrPath);
} catch (error: any) {
}
//验证url
if (!url) {
res.errMsg = `UriOrPath ${UriOrPath} 解析失败,可能${UriOrPath}不存在`;
return res;
}
if (url.protocol == 'base64:') {
// base64转成文件
const base64Data = UriOrPath.split('base64://')[1];
try {
const buffer = Buffer.from(base64Data, 'base64');
fs.writeFileSync(filePath, buffer);
} catch (e: any) {
res.errMsg = 'base64文件下载失败,' + e.toString();
return res;
//再判断是否是Http
if (Uri.startsWith('http://') || Uri.startsWith('https://')) {
return { Uri: Uri, Type: FileUriType.Remote };
}
} else if (url.protocol == 'http:' || url.protocol == 'https:') {
// 下载文件
let buffer: Buffer | null = null;
try {
buffer = await httpDownload(UriOrPath);
} catch (e: any) {
res.errMsg = `${url}下载失败,` + e.toString();
return res;
//再判断是否是Base64
if (Uri.startsWith('base64://')) {
return { Uri: Uri, Type: FileUriType.Base64 };
}
try {
const pathInfo = path.parse(decodeURIComponent(url.pathname));
if (pathInfo.name) {
fileName = pathInfo.name;
if (pathInfo.ext) {
fileName += pathInfo.ext;
// res.ext = pathInfo.ext
}
}
fileName = fileName.replace(/[/\\:*?"<>|]/g, '_');
res.fileName = fileName;
filePath = path.join(TempDir, randomUUID() + fileName);
fs.writeFileSync(filePath, buffer);
} catch (e: any) {
res.errMsg = `${url}下载失败,` + e.toString();
return res;
}
} else {
let pathname: string;
if (url.protocol === 'file:') {
if (Uri.startsWith('file://')) {
let pathname: string;
let filePath: string;
// await fs.copyFile(url.pathname, filePath);
pathname = decodeURIComponent(url.pathname);
pathname = decodeURIComponent(new URL(Uri).pathname);
if (process.platform === 'win32') {
filePath = pathname.slice(1);
} else {
filePath = pathname;
}
} else {
// 26702执行forword file文件操作 不应该在这里乱来
// const cache = await dbUtil.getFileCacheByName(uri);
// if (cache) {
// filePath = cache.path;
// } else {
// filePath = uri;
// }
return { Uri: filePath, Type: FileUriType.Local };
}
res.isLocal = true;
} catch (error) {
}
// else{
// res.errMsg = `不支持的file协议,` + url.protocol
// return res
// }
// if (isGIF(filePath) && !res.isLocal) {
// await fs.rename(filePath, filePath + ".gif");
// filePath += ".gif";
// }
if (!res.isLocal && !res.ext) {
try {
const ext: string | undefined = (await fileType.fileTypeFromFile(filePath))?.ext;
if (ext) {
fs.renameSync(filePath, filePath + `.${ext}`);
filePath += `.${ext}`;
res.fileName += `.${ext}`;
res.ext = ext;
}
} catch (e) {
// log("获取文件类型失败", filePath,e.stack)
}
}
res.success = true;
res.path = filePath;
return res;
return { Uri: Uri, Type: FileUriType.Unknown };
}
export async function uri2local(dir: string, uri: string, filename: string | undefined = undefined): Promise<Uri2LocalRes> {
let { Uri: HandledUri, Type: UriType } = await checkUriType(uri);
//解析失败
if (UriType == FileUriType.Unknown) {
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
}
//解析File协议和本地文件
if (UriType == FileUriType.Local) {
const fileExt = path.extname(HandledUri);
const filename = path.basename(HandledUri, fileExt);
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: HandledUri, isLocal: true };
}
//接下来都要有文件名
if (!filename) filename = randomUUID();
//解析Http和Https协议
if (UriType == FileUriType.Remote) {
const fileExt = path.extname(HandledUri);
const fileName = filename + fileExt;
const filePath = path.join(dir, fileName);
const buffer = await httpDownload(HandledUri);
fs.writeFileSync(filePath, buffer);
return { success: true, errMsg: '', fileName: fileName, ext: fileExt, path: filePath, isLocal: true };
}
//解析Base64
if (UriType == FileUriType.Base64) {
const base64 = HandledUri.replace(/^base64:\/\//, '');
const buffer = Buffer.from(base64, 'base64');
let filePath = path.join(dir, filename);
let fileExt = '';
fs.writeFileSync(filePath, buffer);
const { success, ext, path: fileTypePath } = await checkFileV2(filePath);
if (success) {
filePath = fileTypePath;
fileExt = ext;
filename = path.basename(filePath, fileExt);
}
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: true };
}
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
}
export async function copyFolder(sourcePath: string, destPath: string, logger: LogWrapper) {
try {
const entries = await fsPromise.readdir(sourcePath, { withFileTypes: true });

View File

@@ -127,25 +127,7 @@ export class NTQQUserApi {
}
async getUserDetailInfo(uid: string) {
if (this.context.basicInfoWrapper.requireMinNTQQBuild('26702')) {
return this.fetchUserDetailInfo(uid);
}
return this.getUserDetailInfoOld(uid);
}
async getUserDetailInfoOld(uid: string) {
type EventService = NodeIKernelProfileService['getUserDetailInfoWithBizInfo'];
type EventListener = NodeIKernelProfileListener['onProfileDetailInfoChanged'];
const [_retData, profile] = await this.core.eventWrapper.CallNormalEvent<EventService, EventListener>(
'NodeIKernelProfileService/getUserDetailInfoWithBizInfo',
'NodeIKernelProfileListener/onProfileDetailInfoChanged',
2,
5000,
(profile) => profile.uid === uid,
uid,
[0],
);
return profile;
return this.fetchUserDetailInfo(uid);
}
async modifySelfProfile(param: ModifyProfileParams) {

View File

@@ -56,7 +56,7 @@ const _handlers: {
if (atQQ === 'all') return SendMsgElementConstructor.at(coreContext, atQQ, atQQ, AtType.atAll, '全体成员');
// then the qq is a group member
// Mlikiowa V2.0.21 Refactor Todo
// Mlikiowa V2.0.23 Refactor Todo
const uid = await coreContext.apis.UserApi.getUidByUinV2(`${atQQ}`);
if (!uid) throw new Error('Get Uid Error');
return SendMsgElementConstructor.at(coreContext, atQQ, uid, AtType.atUser, '');
@@ -161,7 +161,7 @@ const _handlers: {
} else {
postData = data;
}
// Mlikiowa V2.0.21 Refactor Todo
// Mlikiowa V2.0.23 Refactor Todo
const signUrl = obContext.configLoader.configData.musicSignUrl;
if (!signUrl) {
if (data.type === 'qq') {

View File

@@ -417,7 +417,7 @@ export class OB11Constructor {
return;
}
//log("group msg", msg);
// Mlikiowa V2.0.21 Refactor Todo
// Mlikiowa V2.0.23 Refactor Todo
// if (msg.senderUin && msg.senderUin !== '0') {
// const member = await getGroupMember(msg.peerUid, msg.senderUin);
// if (member && member.cardName !== msg.sendMemberName) {

View File

@@ -4,6 +4,7 @@ import http from 'http';
import { NapCatCore } from '@/core';
import { OB11Response } from '../action/OB11Response';
import { ActionMap } from '@/onebot/action';
import cors from 'cors';
export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
private app: Express | undefined;
@@ -43,21 +44,11 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
this.server?.close();
this.app = undefined;
}
cors(): any {
return (req: Request, res: Response, next: any) => {
if (req.method === 'OPTIONS') {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
}
next();
};
}
private initializeServer() {
this.app = express();
this.server = http.createServer(this.app);
this.app.use(this.cors());
this.app.use(cors());
this.app.use(express.urlencoded({ extended: true, limit: '5000mb' }));
this.app.use((req, res, next) => {
// 兼容处理没有带content-type的请求
@@ -70,7 +61,7 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
next();
});
});
this.app.use((req, res, next) => this.authorize(this.token, req, res, next));
this.app.use((req, res) => this.handleRequest(req, res));

View File

@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
SettingItem(
'<span id="napcat-update-title">Napcat</span>',
undefined,
SettingButton('V2.0.21', 'napcat-update-button', 'secondary'),
SettingButton('V2.0.23', 'napcat-update-button', 'secondary'),
),
]),
SettingList([

View File

@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
SettingItem(
'<span id="napcat-update-title">Napcat</span>',
void 0,
SettingButton("V2.0.21", "napcat-update-button", "secondary")
SettingButton("V2.0.23", "napcat-update-button", "secondary")
)
]),
SettingList([