Compare commits

..

7 Commits

Author SHA1 Message Date
手瓜一十雪
05043f8dfc fix: code 2024-12-03 21:41:53 +08:00
手瓜一十雪
dc2b45fa00 fix: 优化处理 2024-12-03 21:36:55 +08:00
手瓜一十雪
cc70fc766a fix 2024-12-03 21:14:18 +08:00
手瓜一十雪
d2e9db5571 fix: 临时的抽象方案 2024-12-03 20:55:24 +08:00
手瓜一十雪
8e01638a36 fix: error 2024-12-03 19:50:47 +08:00
手瓜一十雪
e8b8eae8a9 refactor: GroupAdminChange 2024-12-03 19:44:38 +08:00
手瓜一十雪
0f0275243b feat: 迁移事件解析原理 2024-12-03 19:28:51 +08:00
23 changed files with 260 additions and 152 deletions

View File

@@ -4,7 +4,7 @@
"name": "NapCatQQ", "name": "NapCatQQ",
"slug": "NapCat.Framework", "slug": "NapCat.Framework",
"description": "高性能的 OneBot 11 协议实现", "description": "高性能的 OneBot 11 协议实现",
"version": "4.2.17", "version": "4.2.12",
"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": "4.2.17", "version": "4.2.12",
"scripts": { "scripts": {
"build:universal": "npm run build:webui && vite build --mode universal || exit 1", "build:universal": "npm run build:webui && vite build --mode universal || exit 1",
"build:framework": "npm run build:webui && vite build --mode framework || exit 1", "build:framework": "npm run build:webui && vite build --mode framework || exit 1",

View File

@@ -1,7 +1,9 @@
import fs from 'fs'; import fs from 'fs';
import { stat } from 'fs/promises'; import { stat } from 'fs/promises';
import crypto, { randomUUID } from 'crypto'; import crypto, { randomUUID } from 'crypto';
import util from 'util';
import path from 'node:path'; import path from 'node:path';
import * as fileType from 'file-type';
import { solveProblem } from '@/common/helper'; import { solveProblem } from '@/common/helper';
export interface HttpDownloadOptions { export interface HttpDownloadOptions {
@@ -13,6 +15,7 @@ type Uri2LocalRes = {
success: boolean, success: boolean,
errMsg: string, errMsg: string,
fileName: string, fileName: string,
ext: string,
path: string path: string
} }
@@ -70,6 +73,27 @@ async function checkFile(path: string): Promise<void> {
// 如果文件存在则无需做任何事情Promise 解决resolve自身 // 如果文件存在则无需做任何事情Promise 解决resolve自身
} }
export async function file2base64(path: string) {
const readFile = util.promisify(fs.readFile);
const result = {
err: '',
data: '',
};
try {
try {
await checkFileExist(path, 5000);
} catch (e: any) {
result.err = e.toString();
return result;
}
const data = await readFile(path);
result.data = data.toString('base64');
} catch (err: any) {
result.err = err.toString();
}
return result;
}
export function calculateFileMD5(filePath: string): Promise<string> { export function calculateFileMD5(filePath: string): Promise<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// 创建一个流式读取器 // 创建一个流式读取器
@@ -136,6 +160,20 @@ export async function httpDownload(options: string | HttpDownloadOptions): Promi
return Buffer.from(buffer); return Buffer.from(buffer);
} }
export async function checkFileV2(filePath: string) {
try {
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 { export enum FileUriType {
Unknown = 0, Unknown = 0,
Local = 1, Local = 1,
@@ -175,32 +213,63 @@ export async function checkUriType(Uri: string) {
return { Uri: Uri, Type: FileUriType.Unknown }; return { Uri: Uri, Type: FileUriType.Unknown };
} }
export async function uriToLocalFile(dir: string, uri: string): Promise<Uri2LocalRes> { export async function uri2local(dir: string, uri: string, filename: string | undefined = undefined): Promise<Uri2LocalRes> {
const { Uri: HandledUri, Type: UriType } = await checkUriType(uri); const { Uri: HandledUri, Type: UriType } = await checkUriType(uri);
const filename = randomUUID(); //解析失败
const filePath = path.join(dir, filename); const tempName = randomUUID();
if (!filename) filename = randomUUID();
switch (UriType) { //解析Http和Https协议
case FileUriType.Local: if (UriType == FileUriType.Unknown) {
const fileExt = path.extname(HandledUri); return { success: false, errMsg: `未知文件类型, uri= ${uri}`, fileName: '', ext: '', path: '' };
const localFileName = path.basename(HandledUri, fileExt) + fileExt;
const tempFilePath = path.join(dir, filename + fileExt);
fs.copyFileSync(HandledUri, tempFilePath);
return { success: true, errMsg: '', fileName: localFileName, path: tempFilePath };
case FileUriType.Remote:
const buffer = await httpDownload(HandledUri);
fs.writeFileSync(filePath, buffer, { flag: 'wx' });
return { success: true, errMsg: '', fileName: filename, path: filePath };
case FileUriType.Base64:
const base64 = HandledUri.replace(/^base64:\/\//, '');
const base64Buffer = Buffer.from(base64, 'base64');
fs.writeFileSync(filePath, base64Buffer, { flag: 'wx' });
return { success: true, errMsg: '', fileName: filename, path: filePath };
default:
return { success: false, errMsg: `识别URL失败, uri= ${uri}`, fileName: '', path: '' };
} }
//解析File协议和本地文件
if (UriType == FileUriType.Local) {
const fileExt = path.extname(HandledUri);
let filename = path.basename(HandledUri, fileExt);
filename += fileExt;
//复制文件到临时文件并保持后缀
const filenameTemp = tempName + fileExt;
const filePath = path.join(dir, filenameTemp);
fs.copyFileSync(HandledUri, filePath);
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
}
//接下来都要有文件名
if (UriType == FileUriType.Remote) {
const pathInfo = path.parse(decodeURIComponent(new URL(HandledUri).pathname));
if (pathInfo.name) {
const pathlen = 200 - dir.length - pathInfo.name.length;
filename = pathlen > 0 ? pathInfo.name.substring(0, pathlen) : pathInfo.name.substring(pathInfo.name.length, pathInfo.name.length - 10);//过长截断
if (pathInfo.ext) {
filename += pathInfo.ext;
}
}
filename = filename.replace(/[/\\:*?"<>|]/g, '_');
const fileExt = path.extname(HandledUri).replace(/[/\\:*?"<>|]/g, '_').substring(0, 10);
const filePath = path.join(dir, tempName + fileExt);
const buffer = await httpDownload(HandledUri);
//没有文件就创建
fs.writeFileSync(filePath, buffer, { flag: 'wx' });
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
}
//解析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 = filename + '.' + ext;
}
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
}
return { success: false, errMsg: `未知文件类型, uri= ${uri}`, fileName: '', ext: '', path: '' };
} }

View File

@@ -1 +1 @@
export const napCatVersion = '4.2.17'; export const napCatVersion = '4.2.12';

View File

@@ -6,6 +6,7 @@ import {
Peer, Peer,
PicElement, PicElement,
PicSubType, PicSubType,
PicType,
RawMessage, RawMessage,
SendFileElement, SendFileElement,
SendPicElement, SendPicElement,
@@ -16,7 +17,7 @@ import path from 'path';
import fs from 'fs'; import fs from 'fs';
import fsPromises from 'fs/promises'; import fsPromises from 'fs/promises';
import { InstanceContext, NapCatCore, SearchResultItem } from '@/core'; import { InstanceContext, NapCatCore, SearchResultItem } from '@/core';
import { fileTypeFromFile } from 'file-type'; import * as fileType from 'file-type';
import imageSize from 'image-size'; import imageSize from 'image-size';
import { ISizeCalculationResult } from 'image-size/dist/types/interface'; import { ISizeCalculationResult } from 'image-size/dist/types/interface';
import { RkeyManager } from '@/core/helper/rkey'; import { RkeyManager } from '@/core/helper/rkey';
@@ -40,7 +41,7 @@ export class NTQQFileApi {
this.rkeyManager = new RkeyManager([ this.rkeyManager = new RkeyManager([
'https://rkey.napneko.icu/rkeys' 'https://rkey.napneko.icu/rkeys'
], ],
this.context.logger this.context.logger
); );
} }
@@ -61,7 +62,7 @@ export class NTQQFileApi {
async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) { async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) {
const fileMd5 = await calculateFileMD5(filePath); const fileMd5 = await calculateFileMD5(filePath);
let extOrEmpty = await fileTypeFromFile(filePath).then(e => e?.ext ?? '').catch(e => ''); const extOrEmpty = (await fileType.fileTypeFromFile(filePath))?.ext;
const ext = extOrEmpty ? `.${extOrEmpty}` : ''; const ext = extOrEmpty ? `.${extOrEmpty}` : '';
let fileName = `${path.basename(filePath)}`; let fileName = `${path.basename(filePath)}`;
if (fileName.indexOf('.') === -1) { if (fileName.indexOf('.') === -1) {
@@ -157,7 +158,7 @@ export class NTQQFileApi {
let fileExt = 'mp4'; let fileExt = 'mp4';
try { try {
const tempExt = (await fileTypeFromFile(filePath))?.ext; const tempExt = (await fileType.fileTypeFromFile(filePath))?.ext;
if (tempExt) fileExt = tempExt; if (tempExt) fileExt = tempExt;
} catch (e) { } catch (e) {
this.context.logger.logError('获取文件类型失败', e); this.context.logger.logError('获取文件类型失败', e);
@@ -305,18 +306,18 @@ export class NTQQFileApi {
element.elementType === ElementType.FILE element.elementType === ElementType.FILE
) { ) {
switch (element.elementType) { switch (element.elementType) {
case ElementType.PIC: case ElementType.PIC:
element.picElement!.sourcePath = elementResults[elementIndex]; element.picElement!.sourcePath = elementResults[elementIndex];
break; break;
case ElementType.VIDEO: case ElementType.VIDEO:
element.videoElement!.filePath = elementResults[elementIndex]; element.videoElement!.filePath = elementResults[elementIndex];
break; break;
case ElementType.PTT: case ElementType.PTT:
element.pttElement!.filePath = elementResults[elementIndex]; element.pttElement!.filePath = elementResults[elementIndex];
break; break;
case ElementType.FILE: case ElementType.FILE:
element.fileElement!.filePath = elementResults[elementIndex]; element.fileElement!.filePath = elementResults[elementIndex];
break; break;
} }
elementIndex++; elementIndex++;
} }

View File

@@ -1,5 +1,6 @@
import { import {
GeneralCallResult, GeneralCallResult,
Group,
GroupMember, GroupMember,
NTGroupMemberRole, NTGroupMemberRole,
NTGroupRequestOperateTypes, NTGroupRequestOperateTypes,
@@ -15,22 +16,35 @@ import { NTEventWrapper } from '@/common/event';
export class NTQQGroupApi { export class NTQQGroupApi {
context: InstanceContext; context: InstanceContext;
core: NapCatCore; core: NapCatCore;
groupCache: Map<string, Group> = new Map<string, Group>();
groupMemberCache: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>(); groupMemberCache: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
groups: Group[] = [];
essenceLRU = new LimitedHashTable<number, string>(1000); essenceLRU = new LimitedHashTable<number, string>(1000);
session: any;
constructor(context: InstanceContext, core: NapCatCore) { constructor(context: InstanceContext, core: NapCatCore) {
this.context = context; this.context = context;
this.core = core; this.core = core;
} }
async initApi() { async initApi() {
this.initCache().then().catch(e => this.context.logger.logError(e)); this.initCache().then().catch(e => this.context.logger.logError(e));
} }
async initCache() { async initCache() {
for (const group of await this.getGroups(true)) { this.groups = await this.getGroups();
this.refreshGroupMemberCache(group.groupCode).then().catch(); for (const group of this.groups) {
this.groupCache.set(group.groupCode, group);
this.refreshGroupMemberCache(group.groupCode).then().catch(e => this.context.logger.logError(e));
} }
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
// process.pid 调试点
}
async getCoreAndBaseInfo(uids: string[]) {
return await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getCoreAndBaseInfo',
'nodeStore',
uids,
);
} }
async fetchGroupEssenceList(groupCode: string) { async fetchGroupEssenceList(groupCode: string) {
@@ -48,15 +62,15 @@ export class NTQQGroupApi {
return (await data)[1]; return (await data)[1];
} }
async clearGroupNotifiesUnreadCount(doubt: boolean) { async clearGroupNotifiesUnreadCount(uk: boolean) {
return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(doubt); return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(uk);
} }
async setGroupAvatar(groupCode: string, filePath: string) { async setGroupAvatar(gc: string, filePath: string) {
return this.context.session.getGroupService().setHeader(groupCode, filePath); return this.context.session.getGroupService().setHeader(gc, filePath);
} }
async getGroups(forced: boolean = false) { async getGroups(forced = false) {
const [, , groupList] = await this.core.eventWrapper.callNormalEventV2( const [, , groupList] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelGroupService/getGroupList', 'NodeIKernelGroupService/getGroupList',
'NodeIKernelGroupListener/onGroupListUpdate', 'NodeIKernelGroupListener/onGroupListUpdate',
@@ -65,9 +79,9 @@ export class NTQQGroupApi {
return groupList; return groupList;
} }
async getGroupExtFE0Info(groupCodes: Array<string>, forced = true) { async getGroupExtFE0Info(groupCode: string[], forced = true) {
return this.context.session.getGroupService().getGroupExt0xEF0Info( return this.context.session.getGroupService().getGroupExt0xEF0Info(
groupCodes, groupCode,
[], [],
{ {
bindGuildId: 1, bindGuildId: 1,
@@ -107,6 +121,24 @@ export class NTQQGroupApi {
); );
} }
async getGroup(groupCode: string, forced = false) {
let group = this.groupCache.get(groupCode.toString());
if (!group) {
try {
const groupList = await this.getGroups(forced);
if (groupList.length) {
groupList.forEach(g => {
this.groupCache.set(g.groupCode, g);
});
}
} catch (e) {
return undefined;
}
}
group = this.groupCache.get(groupCode.toString());
return group;
}
async getGroupMemberAll(groupCode: string, forced = false) { async getGroupMemberAll(groupCode: string, forced = false) {
return this.context.session.getGroupService().getAllMemberList(groupCode, forced); return this.context.session.getGroupService().getAllMemberList(groupCode, forced);
} }
@@ -114,35 +146,56 @@ export class NTQQGroupApi {
async refreshGroupMemberCache(groupCode: string) { async refreshGroupMemberCache(groupCode: string) {
try { try {
const members = await this.getGroupMemberAll(groupCode, true); const members = await this.getGroupMemberAll(groupCode, true);
this.groupMemberCache.set(groupCode, members.result.infos); // 首先填入基础信息
const existingMembers = this.groupMemberCache.get(groupCode) ?? new Map<string, GroupMember>();
members.result.infos.forEach((value, key) => {
existingMembers.set(value.uid, { ...value, ...existingMembers.get(value.uid) });
});
// 后台补全复杂信息
let event = (async () => {
let data = (await Promise.allSettled(members.result.ids.map(e => this.core.apis.UserApi.getUserDetailInfo(e.uid)))).filter(e => e.status === 'fulfilled').map(e => e.value);
data.forEach(e => {
const existingMember = members.result.infos.get(e.uid);
if (existingMember) {
members.result.infos.set(e.uid, { ...existingMember, ...e });
}
});
this.groupMemberCache.set(groupCode, members.result.infos);
})().then().catch(e => this.context.logger.logError(e));
// 处理首次空缺
if (!this.groupMemberCache.get(groupCode)) {
await event;
}
} catch (e) { } catch (e) {
this.context.logger.logError(`刷新群成员缓存失败, 群号: ${groupCode}, 错误: ${e}`); this.context.logger.logError(`刷新群成员缓存失败, ${e}`);
} }
return this.groupMemberCache;
} }
async getGroupMember(groupCode: string | number, memberUinOrUid: string | number) { async getGroupMember(groupCode: string | number, memberUinOrUid: string | number) {
const groupCodeStr = groupCode.toString(); const groupCodeStr = groupCode.toString();
const memberUinOrUidStr = memberUinOrUid.toString(); const memberUinOrUidStr = memberUinOrUid.toString();
// 获取群成员缓存 // 检查群缓存
let members = this.groupMemberCache.get(groupCodeStr); let members = this.groupMemberCache.get(groupCodeStr);
if (!members) { if (!members) {
members = (await this.refreshGroupMemberCache(groupCodeStr)).get(groupCodeStr); await this.refreshGroupMemberCache(groupCodeStr);
} }
const getMember = () => { function getMember() {
let member: GroupMember | undefined;
if (isNumeric(memberUinOrUidStr)) { if (isNumeric(memberUinOrUidStr)) {
return Array.from(members!.values()).find(member => member.uin === memberUinOrUidStr); member = Array.from(members!.values()).find(member => member.uin === memberUinOrUidStr);
} else { } else {
return members!.get(memberUinOrUidStr); member = members!.get(memberUinOrUidStr);
} }
}; return member;
}
let member = getMember(); let member = getMember();
// 如果缓存中不存在该成员,尝试刷新缓存 // 不存在群友缓存 尝试刷新
if (!member) { if (!member) {
members = (await this.refreshGroupMemberCache(groupCodeStr)).get(groupCodeStr); await this.refreshGroupMemberCache(groupCode.toString());
member = getMember(); member = getMember();
} }
return member; return member;
@@ -152,26 +205,26 @@ export class NTQQGroupApi {
return this.context.session.getGroupService().getGroupRecommendContactArkJson(groupCode); return this.context.session.getGroupService().getGroupRecommendContactArkJson(groupCode);
} }
async creatGroupFileFolder(groupCode: string, folderName: string) { async CreatGroupFileFolder(groupCode: string, folderName: string) {
return this.context.session.getRichMediaService().createGroupFolder(groupCode, folderName); return this.context.session.getRichMediaService().createGroupFolder(groupCode, folderName);
} }
async delGroupFile(groupCode: string, files: Array<string>) { async DelGroupFile(groupCode: string, files: string[]) {
return this.context.session.getRichMediaService().deleteGroupFile(groupCode, [102], files); return this.context.session.getRichMediaService().deleteGroupFile(groupCode, [102], files);
} }
async delGroupFileFolder(groupCode: string, folderId: string) { async DelGroupFileFolder(groupCode: string, folderId: string) {
return this.context.session.getRichMediaService().deleteGroupFolder(groupCode, folderId); return this.context.session.getRichMediaService().deleteGroupFolder(groupCode, folderId);
} }
async addGroupEssence(groupCode: string, msgId: string) { async addGroupEssence(GroupCode: string, msgId: string) {
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({ const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
chatType: 2, chatType: 2,
guildId: '', guildId: '',
peerUid: groupCode, peerUid: GroupCode,
}, msgId, 1, false); }, msgId, 1, false);
const param = { const param = {
groupCode: groupCode, groupCode: GroupCode,
msgRandom: parseInt(MsgData.msgList[0].msgRandom), msgRandom: parseInt(MsgData.msgList[0].msgRandom),
msgSeq: parseInt(MsgData.msgList[0].msgSeq), msgSeq: parseInt(MsgData.msgList[0].msgSeq),
}; };
@@ -182,9 +235,9 @@ export class NTQQGroupApi {
return this.context.session.getGroupService().kickMemberV2(param); return this.context.session.getGroupService().kickMemberV2(param);
} }
async deleteGroupBulletin(groupCode: string, noticeId: string) { async deleteGroupBulletin(GroupCode: string, noticeId: string) {
const psKey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!; const psKey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
return this.context.session.getGroupService().deleteGroupBulletin(groupCode, psKey, noticeId); return this.context.session.getGroupService().deleteGroupBulletin(GroupCode, psKey, noticeId);
} }
async quitGroupV2(GroupCode: string, needDeleteLocalMsg: boolean) { async quitGroupV2(GroupCode: string, needDeleteLocalMsg: boolean) {
@@ -195,37 +248,37 @@ export class NTQQGroupApi {
return this.context.session.getGroupService().quitGroupV2(param); return this.context.session.getGroupService().quitGroupV2(param);
} }
async removeGroupEssenceBySeq(groupCode: string, msgRandom: string, msgSeq: string) { async removeGroupEssenceBySeq(GroupCode: string, msgRandom: string, msgSeq: string) {
const param = { const param = {
groupCode: groupCode, groupCode: GroupCode,
msgRandom: parseInt(msgRandom), msgRandom: parseInt(msgRandom),
msgSeq: parseInt(msgSeq), msgSeq: parseInt(msgSeq),
}; };
return this.context.session.getGroupService().removeGroupEssence(param); return this.context.session.getGroupService().removeGroupEssence(param);
} }
async removeGroupEssence(groupCode: string, msgId: string) { async removeGroupEssence(GroupCode: string, msgId: string) {
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({ const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
chatType: 2, chatType: 2,
guildId: '', guildId: '',
peerUid: groupCode, peerUid: GroupCode,
}, msgId, 1, false); }, msgId, 1, false);
const param = { const param = {
groupCode: groupCode, groupCode: GroupCode,
msgRandom: parseInt(MsgData.msgList[0].msgRandom), msgRandom: parseInt(MsgData.msgList[0].msgRandom),
msgSeq: parseInt(MsgData.msgList[0].msgSeq), msgSeq: parseInt(MsgData.msgList[0].msgSeq),
}; };
return this.context.session.getGroupService().removeGroupEssence(param); return this.context.session.getGroupService().removeGroupEssence(param);
} }
async getSingleScreenNotifies(doubt: boolean, count: number) { async getSingleScreenNotifies(doubt: boolean, num: number) {
const [, , , notifies] = await this.core.eventWrapper.callNormalEventV2( const [, , , notifies] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelGroupService/getSingleScreenNotifies', 'NodeIKernelGroupService/getSingleScreenNotifies',
'NodeIKernelGroupListener/onGroupSingleScreenNotifies', 'NodeIKernelGroupListener/onGroupSingleScreenNotifies',
[ [
doubt, doubt,
'', '',
count, num,
], ],
); );
return notifies; return notifies;
@@ -249,43 +302,44 @@ export class NTQQGroupApi {
return ret.groupInfos.find(g => g.groupCode === groupCode); return ret.groupInfos.find(g => g.groupCode === groupCode);
} }
async getGroupMemberEx(groupCode: string, uid: string, forced: boolean = false, retry: number = 2) { async getGroupMemberEx(GroupCode: string, uid: string, forced = false, retry = 2) {
const data = await solveAsyncProblem((eventWrapper: NTEventWrapper, GroupCode: string, uid: string, forced = false) => { const data = await solveAsyncProblem((eventWrapper: NTEventWrapper, GroupCode: string, uid: string, forced = false) => {
return eventWrapper.callNormalEventV2( return eventWrapper.callNormalEventV2(
'NodeIKernelGroupService/getMemberInfo', 'NodeIKernelGroupService/getMemberInfo',
'NodeIKernelGroupListener/onMemberInfoChange', 'NodeIKernelGroupListener/onMemberInfoChange',
[groupCode, [uid], forced], [GroupCode, [uid], forced],
(ret) => ret.result === 0, (ret) => ret.result === 0,
(params, _, members) => params === GroupCode && members.size > 0 && members.has(uid), (params, _, members) => params === GroupCode && members.size > 0 && members.has(uid),
1, 1,
forced ? 2500 : 250 forced ? 2500 : 250
); );
}, this.core.eventWrapper, groupCode, uid, forced); }, this.core.eventWrapper, GroupCode, uid, forced);
if (data && data[3] instanceof Map && data[3].has(uid)) { if (data && data[3] instanceof Map && data[3].has(uid)) {
return data[3].get(uid); return data[3].get(uid);
} }
if (retry > 0) { if (retry > 0) {
const trydata = await this.getGroupMemberEx(groupCode, uid, true, retry - 1) as GroupMember | undefined; const trydata = await this.getGroupMemberEx(GroupCode, uid, true, retry - 1) as GroupMember | undefined;
if (trydata) return trydata; if (trydata) return trydata;
} }
return undefined; return undefined;
} }
async getGroupFileCount(groupCodes: Array<string>) { async getGroupFileCount(group_ids: Array<string>) {
return this.context.session.getRichMediaService().batchGetGroupFileCount(groupCodes); return this.context.session.getRichMediaService().batchGetGroupFileCount(group_ids);
} }
async getArkJsonGroupShare(groupCode: string) { async getArkJsonGroupShare(GroupCode: string) {
const ret = await this.core.eventWrapper.callNoListenerEvent( const ret = await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelGroupService/getGroupRecommendContactArkJson', 'NodeIKernelGroupService/getGroupRecommendContactArkJson',
groupCode, GroupCode,
) as GeneralCallResult & { arkJson: string }; ) as GeneralCallResult & { arkJson: string };
return ret.arkJson; return ret.arkJson;
} }
async uploadGroupBulletinPic(groupCode: string, imageurl: string) { //需要异常处理
async uploadGroupBulletinPic(GroupCode: string, imageurl: string) {
const _Pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!; const _Pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
return this.context.session.getGroupService().uploadGroupBulletinPic(groupCode, _Pskey, imageurl); return this.context.session.getGroupService().uploadGroupBulletinPic(GroupCode, _Pskey, imageurl);
} }
async handleGroupRequest(flag: string, operateType: NTGroupRequestOperateTypes, reason?: string) { async handleGroupRequest(flag: string, operateType: NTGroupRequestOperateTypes, reason?: string) {
@@ -307,36 +361,36 @@ export class NTQQGroupApi {
}); });
} }
async quitGroup(groupCode: string) { async quitGroup(groupQQ: string) {
return this.context.session.getGroupService().quitGroup(groupCode); return this.context.session.getGroupService().quitGroup(groupQQ);
} }
async kickMember(groupCode: string, kickUids: string[], refuseForever: boolean = false, kickReason: string = '') { async kickMember(groupQQ: string, kickUids: string[], refuseForever: boolean = false, kickReason: string = '') {
return this.context.session.getGroupService().kickMember(groupCode, kickUids, refuseForever, kickReason); return this.context.session.getGroupService().kickMember(groupQQ, kickUids, refuseForever, kickReason);
} }
async banMember(groupCode: string, memList: Array<{ uid: string, timeStamp: number }>) { async banMember(groupQQ: string, memList: Array<{ uid: string, timeStamp: number }>) {
// timeStamp为秒数, 0为解除禁言 // timeStamp为秒数, 0为解除禁言
return this.context.session.getGroupService().setMemberShutUp(groupCode, memList); return this.context.session.getGroupService().setMemberShutUp(groupQQ, memList);
} }
async banGroup(groupCode: string, shutUp: boolean) { async banGroup(groupQQ: string, shutUp: boolean) {
return this.context.session.getGroupService().setGroupShutUp(groupCode, shutUp); return this.context.session.getGroupService().setGroupShutUp(groupQQ, shutUp);
} }
async setMemberCard(groupCode: string, memberUid: string, cardName: string) { async setMemberCard(groupQQ: string, memberUid: string, cardName: string) {
return this.context.session.getGroupService().modifyMemberCardName(groupCode, memberUid, cardName); return this.context.session.getGroupService().modifyMemberCardName(groupQQ, memberUid, cardName);
} }
async setMemberRole(groupCode: string, memberUid: string, role: NTGroupMemberRole) { async setMemberRole(groupQQ: string, memberUid: string, role: NTGroupMemberRole) {
return this.context.session.getGroupService().modifyMemberRole(groupCode, memberUid, role); return this.context.session.getGroupService().modifyMemberRole(groupQQ, memberUid, role);
} }
async setGroupName(groupCode: string, groupName: string) { async setGroupName(groupQQ: string, groupName: string) {
return this.context.session.getGroupService().modifyGroupName(groupCode, groupName, false); return this.context.session.getGroupService().modifyGroupName(groupQQ, groupName, false);
} }
async publishGroupBulletin(groupCode: string, content: string, picInfo: { async publishGroupBulletin(groupQQ: string, content: string, picInfo: {
id: string, id: string,
width: number, width: number,
height: number height: number
@@ -350,11 +404,11 @@ export class NTQQGroupApi {
pinned: pinned, pinned: pinned,
confirmRequired: confirmRequired, confirmRequired: confirmRequired,
}; };
return this.context.session.getGroupService().publishGroupBulletin(groupCode, psKey!, data); return this.context.session.getGroupService().publishGroupBulletin(groupQQ, psKey!, data);
} }
async getGroupRemainAtTimes(groupCode: string) { async getGroupRemainAtTimes(GroupCode: string) {
return this.context.session.getGroupService().getGroupRemainAtTimes(groupCode); return this.context.session.getGroupService().getGroupRemainAtTimes(GroupCode);
} }
async getMemberExtInfo(groupCode: string, uin: string) { async getMemberExtInfo(groupCode: string, uin: string) {

View File

@@ -18,15 +18,6 @@ export class NTQQUserApi {
async getStatusByUid(uid: string) { async getStatusByUid(uid: string) {
return this.context.session.getProfileService().getStatus(uid); return this.context.session.getProfileService().getStatus(uid);
} }
async getCoreAndBaseInfo(uids: string[]) {
return await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getCoreAndBaseInfo',
'nodeStore',
uids,
);
}
// 默认获取自己的 type = 2 获取别人 type = 1 // 默认获取自己的 type = 2 获取别人 type = 1
async getProfileLike(uid: string, start: number, count: number, type: number = 2) { async getProfileLike(uid: string, start: number, count: number, type: number = 2) {
return this.context.session.getProfileLikeService().getBuddyProfileLike({ return this.context.session.getProfileLikeService().getBuddyProfileLike({

View File

@@ -1,7 +1,7 @@
import { fileTypeFromFile } from 'file-type'; import * as fileType from 'file-type';
import { PicType } from '../types'; import { PicType } from '../types';
export async function getFileTypeForSendType(picPath: string): Promise<PicType> { export async function getFileTypeForSendType(picPath: string): Promise<PicType> {
const fileTypeResult = (await fileTypeFromFile(picPath))?.ext ?? 'jpg'; const fileTypeResult = (await fileType.fileTypeFromFile(picPath))?.ext ?? 'jpg';
const picTypeMap: { [key: string]: PicType } = { const picTypeMap: { [key: string]: PicType } = {
//'webp': PicType.NEWPIC_WEBP, //'webp': PicType.NEWPIC_WEBP,
'gif': PicType.NEWPIC_GIF, 'gif': PicType.NEWPIC_GIF,

View File

@@ -193,7 +193,7 @@ export interface NodeIKernelGroupService {
getGroupNotifiesUnreadCount(unknown: boolean): Promise<GeneralCallResult>; getGroupNotifiesUnreadCount(unknown: boolean): Promise<GeneralCallResult>;
clearGroupNotifiesUnreadCount(doubt: boolean): void; clearGroupNotifiesUnreadCount(unknown: boolean): void;
operateSysNotify( operateSysNotify(
doubt: boolean, doubt: boolean,

View File

@@ -18,7 +18,7 @@ export default class GetGroupAddRequest extends OneBotAction<null, OB11GroupRequ
ignoredNotifies ignoredNotifies
.filter(notify => notify.type === 7) .filter(notify => notify.type === 7)
.map(async SSNotify => ({ .map(async SSNotify => ({
request_id: SSNotify.group.groupCode + '|' + SSNotify.seq + '|' + SSNotify.type, request_id: SSNotify.seq,
requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid), requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid),
requester_nick: SSNotify.user1?.nickName, requester_nick: SSNotify.user1?.nickName,
group_id: SSNotify.group?.groupCode, group_id: SSNotify.group?.groupCode,

View File

@@ -1,6 +1,6 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { checkFileExist, uriToLocalFile } from '@/common/file'; import { checkFileExist, uri2local } from '@/common/file';
import fs from 'fs'; import fs from 'fs';
import { Static, Type } from '@sinclair/typebox'; import { Static, Type } from '@sinclair/typebox';
@@ -15,7 +15,7 @@ export class OCRImage extends OneBotAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const { path, success } = (await uriToLocalFile(this.core.NapCatTempPath, payload.image)); const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.image));
if (!success) { if (!success) {
throw new Error(`OCR ${payload.image}失败,image字段可能格式不正确`); throw new Error(`OCR ${payload.image}失败,image字段可能格式不正确`);
} }

View File

@@ -1,7 +1,7 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import fs from 'node:fs/promises'; import fs from 'node:fs/promises';
import { checkFileExist, uriToLocalFile } from '@/common/file'; import { checkFileExist, uri2local } from '@/common/file';
import { Static, Type } from '@sinclair/typebox'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({ const SchemaData = Type.Object({
@@ -14,7 +14,7 @@ export default class SetAvatar extends OneBotAction<Payload, null> {
actionName = ActionName.SetQQAvatar; actionName = ActionName.SetQQAvatar;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const { path, success } = (await uriToLocalFile(this.core.NapCatTempPath, payload.file)); const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
if (!success) { if (!success) {
throw new Error(`头像${payload.file}设置失败,file字段可能格式不正确`); throw new Error(`头像${payload.file}设置失败,file字段可能格式不正确`);
} }

View File

@@ -13,6 +13,6 @@ export class CreateGroupFileFolder extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_CreateGroupFileFolder; actionName = ActionName.GoCQHTTP_CreateGroupFileFolder;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
return (await this.core.apis.GroupApi.creatGroupFileFolder(payload.group_id.toString(), payload.folder_name)).resultWithGroupItem; return (await this.core.apis.GroupApi.CreatGroupFileFolder(payload.group_id.toString(), payload.folder_name)).resultWithGroupItem;
} }
} }

View File

@@ -17,6 +17,6 @@ export class DeleteGroupFile extends OneBotAction<Payload, any> {
async _handle(payload: Payload) { async _handle(payload: Payload) {
const data = FileNapCatOneBotUUID.decodeModelId(payload.file_id); const data = FileNapCatOneBotUUID.decodeModelId(payload.file_id);
if (!data) throw new Error('Invalid file_id'); if (!data) throw new Error('Invalid file_id');
return await this.core.apis.GroupApi.delGroupFile(payload.group_id.toString(), [data.fileId]); return await this.core.apis.GroupApi.DelGroupFile(payload.group_id.toString(), [data.fileId]);
} }
} }

View File

@@ -14,7 +14,7 @@ export class DeleteGroupFileFolder extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder; actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
return (await this.core.apis.GroupApi.delGroupFileFolder( return (await this.core.apis.GroupApi.DelGroupFileFolder(
payload.group_id.toString(), payload.folder ?? payload.folder_id ?? '')).groupFileCommonResult; payload.group_id.toString(), payload.folder ?? payload.folder_id ?? '')).groupFileCommonResult;
} }
} }

View File

@@ -1,4 +1,4 @@
import { checkFileExist, uriToLocalFile } from '@/common/file'; import { checkFileExist, uri2local } from '@/common/file';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { unlink } from 'node:fs/promises'; import { unlink } from 'node:fs/promises';
@@ -28,7 +28,7 @@ export class SendGroupNotice extends OneBotAction<Payload, null> {
const { const {
path, path,
success, success,
} = (await uriToLocalFile(this.core.NapCatTempPath, payload.image)); } = (await uri2local(this.core.NapCatTempPath, payload.image));
if (!success) { if (!success) {
throw new Error(`群公告${payload.image}设置失败,image字段可能格式不正确`); throw new Error(`群公告${payload.image}设置失败,image字段可能格式不正确`);
} }

View File

@@ -1,6 +1,6 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { checkFileExistV2, uriToLocalFile } from '@/common/file'; import { checkFileExistV2, uri2local } from '@/common/file';
import { Static, Type } from '@sinclair/typebox'; import { Static, Type } from '@sinclair/typebox';
import fs from 'node:fs/promises'; import fs from 'node:fs/promises';
const SchemaData = Type.Object({ const SchemaData = Type.Object({
@@ -15,7 +15,7 @@ export default class SetGroupPortrait extends OneBotAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> { async _handle(payload: Payload): Promise<any> {
const { path, success } = (await uriToLocalFile(this.core.NapCatTempPath, payload.file)); const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
if (!success) { if (!success) {
throw new Error(`头像${payload.file}设置失败,file字段可能格式不正确`); throw new Error(`头像${payload.file}设置失败,file字段可能格式不正确`);
} }

View File

@@ -2,7 +2,7 @@ import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { ChatType, Peer } from '@/core/types'; import { ChatType, Peer } from '@/core/types';
import fs from 'fs'; import fs from 'fs';
import { uriToLocalFile } from '@/common/file'; import { uri2local } from '@/common/file';
import { SendMessageContext } from '@/onebot/api'; import { SendMessageContext } from '@/onebot/api';
import { Static, Type } from '@sinclair/typebox'; import { Static, Type } from '@sinclair/typebox';
@@ -25,7 +25,7 @@ export default class GoCQHTTPUploadGroupFile extends OneBotAction<Payload, null>
if (fs.existsSync(file)) { if (fs.existsSync(file)) {
file = `file://${file}`; file = `file://${file}`;
} }
const downloadResult = await uriToLocalFile(this.core.NapCatTempPath, file); const downloadResult = await uri2local(this.core.NapCatTempPath, file);
const peer: Peer = { const peer: Peer = {
chatType: ChatType.KCHATTYPEGROUP, chatType: ChatType.KCHATTYPEGROUP,
peerUid: payload.group_id.toString(), peerUid: payload.group_id.toString(),

View File

@@ -2,7 +2,7 @@ import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { ChatType, Peer, SendFileElement } from '@/core/types'; import { ChatType, Peer, SendFileElement } from '@/core/types';
import fs from 'fs'; import fs from 'fs';
import { uriToLocalFile } from '@/common/file'; import { uri2local } from '@/common/file';
import { SendMessageContext } from '@/onebot/api'; import { SendMessageContext } from '@/onebot/api';
import { ContextMode, createContext } from '@/onebot/action/msg/SendMsg'; import { ContextMode, createContext } from '@/onebot/action/msg/SendMsg';
import { Static, Type } from '@sinclair/typebox'; import { Static, Type } from '@sinclair/typebox';
@@ -36,7 +36,7 @@ export default class GoCQHTTPUploadPrivateFile extends OneBotAction<Payload, nul
if (fs.existsSync(file)) { if (fs.existsSync(file)) {
file = `file://${file}`; file = `file://${file}`;
} }
const downloadResult = await uriToLocalFile(this.core.NapCatTempPath, file); const downloadResult = await uri2local(this.core.NapCatTempPath, file);
if (!downloadResult.success) { if (!downloadResult.success) {
throw new Error(downloadResult.errMsg); throw new Error(downloadResult.errMsg);
} }

View File

@@ -11,7 +11,7 @@ export class GetGroupIgnoredNotifies extends OneBotAction<void, any> {
ignoredNotifies ignoredNotifies
.filter(notify => notify.type === 7) .filter(notify => notify.type === 7)
.map(async SSNotify => ({ .map(async SSNotify => ({
request_id: SSNotify.group.groupCode + '|' + SSNotify.seq + '|' + SSNotify.type, request_id: SSNotify.seq,
requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid), requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid),
requester_nick: SSNotify.user1?.nickName, requester_nick: SSNotify.user1?.nickName,
group_id: SSNotify.group?.groupCode, group_id: SSNotify.group?.groupCode,

View File

@@ -1,6 +1,6 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
import { uriToLocalFile } from "@/common/file"; import { uri2local } from "@/common/file";
import { ChatType, Peer } from "@/core"; import { ChatType, Peer } from "@/core";
import { AIVoiceChatType } from "@/core/packet/entities/aiChat"; import { AIVoiceChatType } from "@/core/packet/entities/aiChat";
import { Static, Type } from '@sinclair/typebox'; import { Static, Type } from '@sinclair/typebox';
@@ -23,7 +23,7 @@ export class SendGroupAiRecord extends GetPacketStatusDepends<Payload, {
async _handle(payload: Payload) { async _handle(payload: Payload) {
const rawRsp = await this.core.apis.PacketApi.pkt.operation.GetAiVoice(+payload.group_id, payload.character, payload.text, AIVoiceChatType.Sound); const rawRsp = await this.core.apis.PacketApi.pkt.operation.GetAiVoice(+payload.group_id, payload.character, payload.text, AIVoiceChatType.Sound);
const url = await this.core.apis.PacketApi.pkt.operation.GetGroupPttUrl(+payload.group_id, rawRsp.msgInfoBody[0].index); const url = await this.core.apis.PacketApi.pkt.operation.GetGroupPttUrl(+payload.group_id, rawRsp.msgInfoBody[0].index);
const { path, errMsg, success } = (await uriToLocalFile(this.core.NapCatTempPath, url)); const { path, errMsg, success } = (await uri2local(this.core.NapCatTempPath, url));
if (!success) { if (!success) {
throw new Error(errMsg); throw new Error(errMsg);
} }

View File

@@ -8,12 +8,12 @@ export class GetGroupSystemMsg extends OneBotAction<void, any> {
const NTQQUserApi = this.core.apis.UserApi; const NTQQUserApi = this.core.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi; const NTQQGroupApi = this.core.apis.GroupApi;
// 默认10条 该api未完整实现 包括响应数据规范化 类型规范化 // 默认10条 该api未完整实现 包括响应数据规范化 类型规范化
const SingleScreenNotifies = await NTQQGroupApi.getSingleScreenNotifies(false, 10); const SingleScreenNotifies = await NTQQGroupApi.getSingleScreenNotifies(false,10);
const retData: any = { InvitedRequest: [], join_requests: [] }; const retData: any = { InvitedRequest: [], join_requests: [] };
for (const SSNotify of SingleScreenNotifies) { for (const SSNotify of SingleScreenNotifies) {
if (SSNotify.type == 1) { if (SSNotify.type == 1) {
retData.InvitedRequest.push({ retData.InvitedRequest.push({
request_id: SSNotify.group.groupCode + '|' + SSNotify.seq + '|' + SSNotify.type, request_id: SSNotify.seq,
invitor_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid), invitor_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid),
invitor_nick: SSNotify.user1?.nickName, invitor_nick: SSNotify.user1?.nickName,
group_id: SSNotify.group?.groupCode, group_id: SSNotify.group?.groupCode,
@@ -23,7 +23,7 @@ export class GetGroupSystemMsg extends OneBotAction<void, any> {
}); });
} else if (SSNotify.type == 7) { } else if (SSNotify.type == 7) {
retData.join_requests.push({ retData.join_requests.push({
request_id: SSNotify.group.groupCode + '|' + SSNotify.seq + '|' + SSNotify.type, request_id: SSNotify.seq,
requester_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid), requester_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid),
requester_nick: SSNotify.user1?.nickName, requester_nick: SSNotify.user1?.nickName,
group_id: SSNotify.group?.groupCode, group_id: SSNotify.group?.groupCode,

View File

@@ -23,7 +23,7 @@ import { NapCatOneBot11Adapter, OB11Message, OB11MessageData, OB11MessageDataTyp
import { OB11Construct } from '@/onebot/helper/data'; import { OB11Construct } from '@/onebot/helper/data';
import { EventType } from '@/onebot/event/OneBotEvent'; import { EventType } from '@/onebot/event/OneBotEvent';
import { encodeCQCode } from '@/onebot/helper/cqcode'; import { encodeCQCode } from '@/onebot/helper/cqcode';
import { uriToLocalFile } from '@/common/file'; import { uri2local } from '@/common/file';
import { RequestUtil } from '@/common/request'; import { RequestUtil } from '@/common/request';
import fsPromise, { constants } from 'node:fs/promises'; import fsPromise, { constants } from 'node:fs/promises';
import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent'; import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent';
@@ -514,7 +514,7 @@ export class OneBotMsgApi {
let thumb = sendMsg.data.thumb; let thumb = sendMsg.data.thumb;
if (thumb) { if (thumb) {
const uri2LocalRes = await uriToLocalFile(this.core.NapCatTempPath, thumb); const uri2LocalRes = await uri2local(this.core.NapCatTempPath, thumb);
if (uri2LocalRes.success) thumb = uri2LocalRes.path; if (uri2LocalRes.success) thumb = uri2LocalRes.path;
} }
return await this.core.apis.FileApi.createValidSendVideoElement(context, path, fileName, thumb); return await this.core.apis.FileApi.createValidSendVideoElement(context, path, fileName, thumb);
@@ -932,7 +932,7 @@ export class OneBotMsgApi {
{ data: inputdata }: OB11MessageFileBase, { data: inputdata }: OB11MessageFileBase,
{ deleteAfterSentFiles }: SendMessageContext, { deleteAfterSentFiles }: SendMessageContext,
) { ) {
const realUri = inputdata.url ?? inputdata.file ?? inputdata.path ?? ''; const realUri = inputdata.url || inputdata.file || inputdata.path || '';
if (realUri.length === 0) { if (realUri.length === 0) {
this.core.context.logger.logError('文件消息缺少参数', inputdata); this.core.context.logger.logError('文件消息缺少参数', inputdata);
throw Error('文件消息缺少参数'); throw Error('文件消息缺少参数');
@@ -942,7 +942,7 @@ export class OneBotMsgApi {
fileName, fileName,
errMsg, errMsg,
success, success,
} = (await uriToLocalFile(this.core.NapCatTempPath, realUri)); } = (await uri2local(this.core.NapCatTempPath, realUri));
if (!success) { if (!success) {
this.core.context.logger.logError('文件下载失败', errMsg); this.core.context.logger.logError('文件下载失败', errMsg);
@@ -980,14 +980,7 @@ export class OneBotMsgApi {
); );
} else if (SysMessage.contentHead.type == 34 && SysMessage.body?.msgContent) { } else if (SysMessage.contentHead.type == 34 && SysMessage.body?.msgContent) {
const groupChange = new NapProtoMsg(GroupChange).decode(SysMessage.body.msgContent); const groupChange = new NapProtoMsg(GroupChange).decode(SysMessage.body.msgContent);
if (groupChange.memberUid === this.core.selfInfo.uid) { this.core.apis.GroupApi.refreshGroupMemberCache(groupChange.groupUin.toString()).then().catch();
setTimeout(() => {
this.core.apis.GroupApi.groupMemberCache.delete(groupChange.groupUin.toString());
}, 5000);
// 自己被踢了 5S后回收
} else {
this.core.apis.GroupApi.refreshGroupMemberCache(groupChange.groupUin.toString()).then().catch();
}
return new OB11GroupDecreaseEvent( return new OB11GroupDecreaseEvent(
this.core, this.core,
groupChange.groupUin, groupChange.groupUin,