Compare commits

...

6 Commits

Author SHA1 Message Date
手瓜一十雪
40b2f6bfd6 release: 2.4.7 2024-09-12 18:31:11 +08:00
手瓜一十雪
911e4921e2 fix: 删除旧文件 2024-09-12 18:15:38 +08:00
手瓜一十雪
1db9bb419d fix: 一处异常字段 2024-09-12 10:55:18 +08:00
手瓜一十雪
c6241a94e3 style: lint 2024-09-12 09:28:41 +08:00
手瓜一十雪
1cbf75ca36 style: lint 2024-09-12 09:28:26 +08:00
手瓜一十雪
8f85c897c8 refactor: SysMsg 2024-09-12 09:20:10 +08:00
18 changed files with 74 additions and 76 deletions

View File

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

View File

@@ -2,7 +2,7 @@
"name": "napcat", "name": "napcat",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "2.4.6", "version": "2.4.7",
"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",

View File

@@ -1,4 +1,3 @@
import fs from 'fs';
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';
@@ -12,7 +11,7 @@ const FFMPEG_PATH = process.env.FFMPEG_PATH || 'ffmpeg';
async function guessDuration(pttPath: string, logger: LogWrapper) { async function guessDuration(pttPath: string, logger: LogWrapper) {
const pttFileInfo = await fsPromise.stat(pttPath); const pttFileInfo = await fsPromise.stat(pttPath);
let duration = Math.max(1, Math.floor(pttFileInfo.size / 1024 / 3)); // 3kb/s const duration = Math.max(1, Math.floor(pttFileInfo.size / 1024 / 3)); // 3kb/s
logger.log('通过文件大小估算语音的时长:', duration); logger.log('通过文件大小估算语音的时长:', duration);
return duration; return duration;
} }
@@ -20,7 +19,7 @@ async function guessDuration(pttPath: string, logger: LogWrapper) {
async function convert(filePath: string, pcmPath: string, logger: LogWrapper): Promise<Buffer> { async function convert(filePath: string, pcmPath: string, logger: LogWrapper): Promise<Buffer> {
return new Promise<Buffer>((resolve, reject) => { return new Promise<Buffer>((resolve, reject) => {
const cp = spawn(FFMPEG_PATH, ['-y', '-i', filePath, '-ar', '24000', '-ac', '1', '-f', 's16le', pcmPath]); const cp = spawn(FFMPEG_PATH, ['-y', '-i', filePath, '-ar', '24000', '-ac', '1', '-f', 's16le', pcmPath]);
cp.on('error', err => { cp.on('error', (err: Error) => {
logger.log('FFmpeg处理转换出错: ', err.message); logger.log('FFmpeg处理转换出错: ', err.message);
reject(err); reject(err);
}); });

View File

@@ -242,7 +242,6 @@ export async function uri2local(dir: string, uri: string, filename: string | und
const filenameTemp = tempName + fileExt; const filenameTemp = tempName + fileExt;
const filePath = path.join(dir, filenameTemp); const filePath = path.join(dir, filenameTemp);
fs.copyFileSync(HandledUri, filePath); fs.copyFileSync(HandledUri, filePath);
//console.log('复制文件到临时文件', HandledUri, filePath);
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath }; return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
} }
//接下来都要有文件名 //接下来都要有文件名
@@ -250,7 +249,7 @@ export async function uri2local(dir: string, uri: string, filename: string | und
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) {
let pathlen = 200 - dir.length - pathInfo.name.length; 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);//过长截断 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;
@@ -260,7 +259,6 @@ export async function uri2local(dir: string, uri: string, filename: string | und
const fileExt = path.extname(HandledUri).replace(/[/\\:*?"<>|]/g, '_').substring(0, 10); const fileExt = path.extname(HandledUri).replace(/[/\\:*?"<>|]/g, '_').substring(0, 10);
const filePath = path.join(dir, tempName + fileExt); const filePath = path.join(dir, tempName + fileExt);
const buffer = await httpDownload(HandledUri); const buffer = await httpDownload(HandledUri);
//fs.writeFileSync(filePath, buffer);
//没有文件就创建 //没有文件就创建
fs.writeFileSync(filePath, buffer, { flag: 'wx' }); fs.writeFileSync(filePath, buffer, { flag: 'wx' });
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath }; return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };

View File

@@ -1 +1 @@
export const napCatVersion = '2.4.6'; export const napCatVersion = '2.4.7';

View File

@@ -147,8 +147,9 @@ export class NTQQFileApi {
} catch (e) { } catch (e) {
logger.logError('获取视频信息失败,将使用默认值', e); logger.logError('获取视频信息失败,将使用默认值', e);
} }
let newFilePath = filePath + '.mp4'; const newFilePath = filePath + '.mp4';
fs.renameSync(filePath, newFilePath); fs.copyFileSync(filePath, newFilePath);
context.deleteAfterSentFiles.push(newFilePath);
filePath = newFilePath; filePath = newFilePath;
const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO); const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
if (fileSize === 0) { if (fileSize === 0) {

View File

@@ -32,10 +32,6 @@ export class NTQQGroupApi {
for (const group of this.groups) { for (const group of this.groups) {
this.groupCache.set(group.groupCode, group); this.groupCache.set(group.groupCode, group);
} }
// let text = await this.context.session.getMsgService().sendSsoCmdReqByContend(
// 'LightAppSvc.mini_app_share.AdaptShareInfo',
// JSON.stringify({ data: 'test' }));
// console.log(text);
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`); this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
} }

View File

@@ -40,7 +40,7 @@ export class RkeyManager {
async refreshRkey(): Promise<any> { async refreshRkey(): Promise<any> {
//刷新rkey //刷新rkey
for (let url of this.serverUrl) { for (const url of this.serverUrl) {
try { try {
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET'); this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET');
} catch (e) { } catch (e) {

View File

@@ -145,7 +145,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;
} }

View File

@@ -57,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,
@@ -71,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;
} }

View File

@@ -37,10 +37,10 @@ export default class GoCQHTTPUploadGroupFile extends BaseAction<Payload, null> {
if (!downloadResult.success) { if (!downloadResult.success) {
throw new Error(downloadResult.errMsg); throw new Error(downloadResult.errMsg);
} }
let msgContext: MessageContext = { const msgContext: MessageContext = {
peer: peer, peer: peer,
deleteAfterSentFiles: [] deleteAfterSentFiles: []
} };
const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name, payload.folder_id); const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name, payload.folder_id);
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, [sendFileEle], [], true); await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, [sendFileEle], [], true);
return null; return null;

View File

@@ -45,13 +45,13 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
throw new Error(downloadResult.errMsg); throw new Error(downloadResult.errMsg);
} }
let msgContext: MessageContext = { const msgContext: MessageContext = {
peer: await createContext(this.core, { peer: await createContext(this.core, {
user_id: payload.user_id.toString(), user_id: payload.user_id.toString(),
group_id: undefined, group_id: undefined,
}, ContextMode.Private), }, ContextMode.Private),
deleteAfterSentFiles: [] deleteAfterSentFiles: []
} };
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name); 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;

View File

@@ -152,7 +152,7 @@ export class OneBotGroupApi {
parseInt(memberUin), parseInt(memberUin),
title, title,
); );
}; }
case "移出": case "移出":
logger.logDebug('收到机器人被踢消息', json); logger.logDebug('收到机器人被踢消息', json);
return; return;

View File

@@ -34,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]: (
@@ -185,7 +186,7 @@ export class OneBotMsgApi {
data: { data: {
file: 'marketface', file: 'marketface',
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + _.key + ".jpg"), file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + _.key + ".jpg"),
path: elementWrapper.elementId, path: url,
url: url, url: url,
file_unique: _.key file_unique: _.key
}, },
@@ -818,4 +819,38 @@ export class OneBotMsgApi {
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);
}
}
*/
}
} }

View File

@@ -238,39 +238,10 @@ export class NapCatOneBot11Adapter {
private initMsgListener() { private initMsgListener() {
const msgListener = new NodeIKernelMsgListener(); const msgListener = new NodeIKernelMsgListener();
msgListener.onRecvSysMsg = async (msg) => { msgListener.onRecvSysMsg = (msg) => {
const sysMsg = SysMessage.decode(Uint8Array.from(msg)) as unknown as SysMessageType; this.apis.MsgApi.parseSysMessage(msg).then((event) => {
if (sysMsg.msgSpec.length === 0) { if (event) this.networkManager.emitEvent(event);
return; }).catch(e => this.context.logger.logError('constructSysMessage error: ', e));
}
const { msgType, subType, subSubType } = sysMsg.msgSpec[0];
if (msgType === 528 && subType === 39 && subSubType === 39) {
if (!sysMsg.bodyWrapper) return;
let event = await this.apis.UserApi.parseLikeEvent(sysMsg.bodyWrapper.wrappedBody);
if (event) await this.networkManager.emitEvent(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);
}
}
*/
}; };
msgListener.onInputStatusPush = async data => { msgListener.onInputStatusPush = async data => {

View File

@@ -47,7 +47,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
} }
//鉴权 //鉴权
this.authorize(token, wsClient, wsReq); this.authorize(token, wsClient, wsReq);
let 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 isEventConnect = paramUrl === '/event' || paramUrl === '' || paramUrl === '/';
if (isEventConnect) { if (isEventConnect) {
this.connectEvent(core, wsClient); this.connectEvent(core, wsClient);

View File

@@ -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.6', 'napcat-update-button', 'secondary'), SettingButton('V2.4.7', 'napcat-update-button', 'secondary'),
), ),
]), ]),
SettingList([ SettingList([

View File

@@ -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.6", "napcat-update-button", "secondary") SettingButton("V2.4.7", "napcat-update-button", "secondary")
) )
]), ]),
SettingList([ SettingList([