mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3987e0ee0b | ||
![]() |
9f53bea02f | ||
![]() |
737709f9e7 | ||
![]() |
39477aa6a0 | ||
![]() |
f097050b56 | ||
![]() |
f14726ed1a | ||
![]() |
e1e4d038d9 | ||
![]() |
d2db4cf887 | ||
![]() |
2f3ece9ca3 |
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "2.2.24",
|
"version": "2.2.25",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.2.24",
|
"version": "2.2.25",
|
||||||
"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",
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '2.2.24';
|
export const napCatVersion = '2.2.25';
|
||||||
|
@@ -17,7 +17,7 @@ import {
|
|||||||
import path from 'path';
|
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 } from '@/core';
|
import { InstanceContext, NapCatCore, SearchResultItem } from '@/core';
|
||||||
import * as fileType 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';
|
||||||
@@ -302,16 +302,13 @@ export class NTQQFileApi {
|
|||||||
async downloadMediaByUuid() {
|
async downloadMediaByUuid() {
|
||||||
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
|
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
|
||||||
}
|
}
|
||||||
async downloadFileForModelId(peer: Peer, modelId: string, unknown: string, timeout = 1000 * 60 * 2) {
|
async downloadFileForModelId(peer: Peer, modelId: string, timeout = 1000 * 60 * 2) {
|
||||||
const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2(
|
const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
'NodeIKernelRichMediaService/downloadFileForModelId',
|
'NodeIKernelRichMediaService/downloadFileForModelId',
|
||||||
'NodeIKernelMsgListener/onRichMediaDownloadComplete',
|
'NodeIKernelMsgListener/onRichMediaDownloadComplete',
|
||||||
[peer, [modelId], unknown],
|
[peer, [modelId]],
|
||||||
() => true,
|
() => true,
|
||||||
(arg) => {
|
(arg) => arg?.commonFileInfo?.fileModelId === modelId,
|
||||||
console.log(arg);
|
|
||||||
return arg?.commonFileInfo?.fileModelId === modelId
|
|
||||||
},
|
|
||||||
1,
|
1,
|
||||||
timeout,
|
timeout,
|
||||||
);
|
);
|
||||||
@@ -356,15 +353,12 @@ export class NTQQFileApi {
|
|||||||
chatType: chatType,
|
chatType: chatType,
|
||||||
peerUid: peerUid,
|
peerUid: peerUid,
|
||||||
}, [msgId]);
|
}, [msgId]);
|
||||||
if (msg.msgList.length === 0) {
|
|
||||||
return fileTransNotifyInfo.filePath;
|
|
||||||
}
|
|
||||||
const mixElement = msg.msgList.find((msg) => msg.msgId === msgId)?.elements.find((e) => e.elementId === elementId);
|
const mixElement = msg.msgList.find((msg) => msg.msgId === msgId)?.elements.find((e) => e.elementId === elementId);
|
||||||
const mixElementInner = mixElement?.videoElement ?? mixElement?.fileElement ?? mixElement?.pttElement ?? mixElement?.picElement;
|
const mixElementInner = mixElement?.videoElement ?? mixElement?.fileElement ?? mixElement?.pttElement ?? mixElement?.picElement;
|
||||||
let realPath = mixElementInner?.filePath;
|
let realPath = mixElementInner?.filePath;
|
||||||
if (!realPath) {
|
if (!realPath) {
|
||||||
let picThumbPath: Map<number, string> = (mixElementInner as any)?.picThumbPath;
|
const picThumbPath: Map<number, string> = (mixElementInner as any)?.picThumbPath;
|
||||||
let picThumbPathList = Array.from(picThumbPath.values());
|
const picThumbPathList = Array.from(picThumbPath.values());
|
||||||
if (picThumbPathList.length > 0) realPath = picThumbPathList[0];
|
if (picThumbPathList.length > 0) realPath = picThumbPathList[0];
|
||||||
}
|
}
|
||||||
return realPath;
|
return realPath;
|
||||||
@@ -441,17 +435,36 @@ export class NTQQFileApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchfile(keys: string[]) {
|
async searchForFile(keys: string[]): Promise<SearchResultItem | undefined> {
|
||||||
const Event = this.core.eventWrapper.createEventFunction('NodeIKernelSearchService/searchFileWithKeywords');
|
const [, searchResult] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
const id = await Event!(keys, 12);
|
'NodeIKernelFileAssistantService/searchFile',
|
||||||
const Listener = this.core.eventWrapper.registerListen(
|
'NodeIKernelFileAssistantListener/onFileSearch',
|
||||||
'NodeIKernelSearchListener/onSearchFileKeywordsResult',
|
[
|
||||||
1,
|
keys,
|
||||||
20000,
|
{
|
||||||
(params) => id !== '' && params.searchId == id,
|
resultType: 2,
|
||||||
|
pageLimit: 1,
|
||||||
|
}
|
||||||
|
]
|
||||||
);
|
);
|
||||||
const [ret] = (await Listener);
|
return searchResult.resultItems[0];
|
||||||
return ret;
|
}
|
||||||
|
|
||||||
|
async downloadFileById(
|
||||||
|
fileId: string,
|
||||||
|
fileSize: number = 1024576,
|
||||||
|
estimatedTime: number = (fileSize * 1000 / 1024576) + 5000,
|
||||||
|
) {
|
||||||
|
const [, ret] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
|
'NodeIKernelFileAssistantService/downloadFile',
|
||||||
|
'NodeIKernelFileAssistantListener/onFileStatusChanged',
|
||||||
|
[[fileId]],
|
||||||
|
ret => ret.result === 0,
|
||||||
|
status => status.fileStatus === 2 && status.fileProgress === '0',
|
||||||
|
1,
|
||||||
|
estimatedTime, // estimate 1MB/s
|
||||||
|
);
|
||||||
|
return ret.filePath!;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getImageUrl(element: PicElement) {
|
async getImageUrl(element: PicElement) {
|
||||||
|
@@ -1,5 +1,13 @@
|
|||||||
export class NodeIKernelFileAssistantListener {
|
export class NodeIKernelFileAssistantListener {
|
||||||
onFileStatusChanged(...args: unknown[]) {
|
onFileStatusChanged(fileStatus: {
|
||||||
|
id: string,
|
||||||
|
fileStatus: number,
|
||||||
|
fileProgress: `${number}`,
|
||||||
|
fileSize: `${number}`,
|
||||||
|
fileSpeed: number,
|
||||||
|
thumbPath: string | null,
|
||||||
|
filePath: string | null,
|
||||||
|
}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onSessionListChanged(...args: unknown[]) {
|
onSessionListChanged(...args: unknown[]) {
|
||||||
@@ -11,6 +19,42 @@ export class NodeIKernelFileAssistantListener {
|
|||||||
onFileListChanged(...args: unknown[]) {
|
onFileListChanged(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onFileSearch(...args: unknown[]) {
|
onFileSearch(searchResult: SearchResultWrapper) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SearchResultWrapper = {
|
||||||
|
searchId: number,
|
||||||
|
resultType: number,
|
||||||
|
hasMore: boolean,
|
||||||
|
resultItems: SearchResultItem[],
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SearchResultItem = {
|
||||||
|
id: string,
|
||||||
|
fileName: string,
|
||||||
|
fileNameHits: string[],
|
||||||
|
fileStatus: number,
|
||||||
|
fileSize: string,
|
||||||
|
isSend: boolean,
|
||||||
|
source: number,
|
||||||
|
fileTime: string,
|
||||||
|
expTime: string,
|
||||||
|
session: {
|
||||||
|
context: null,
|
||||||
|
uid: string,
|
||||||
|
nick: string,
|
||||||
|
remark: string,
|
||||||
|
memberCard: string,
|
||||||
|
groupCode: string,
|
||||||
|
groupName: string,
|
||||||
|
groupRemark: string,
|
||||||
|
count: number,
|
||||||
|
},
|
||||||
|
thumbPath: string,
|
||||||
|
filePath: string,
|
||||||
|
msgId: string,
|
||||||
|
chatType: number,
|
||||||
|
peerUid: string,
|
||||||
|
fileType: number,
|
||||||
|
};
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
|
import { NodeIKernelFileAssistantListener } from '@/core';
|
||||||
|
|
||||||
export interface NodeIKernelFileAssistantService {
|
export interface NodeIKernelFileAssistantService {
|
||||||
addKernelFileAssistantListener(arg1: unknown[]): unknown;
|
addKernelFileAssistantListener(listener: NodeIKernelFileAssistantListener): unknown;
|
||||||
|
|
||||||
removeKernelFileAssistantListener(arg1: unknown[]): unknown;
|
removeKernelFileAssistantListener(arg1: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -9,7 +11,7 @@ export interface NodeIKernelFileAssistantService {
|
|||||||
|
|
||||||
getFileSessionList(): unknown;
|
getFileSessionList(): unknown;
|
||||||
|
|
||||||
searchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
searchFile(keywords: string[], params: { resultType: number, pageLimit: number }): unknown;
|
||||||
|
|
||||||
resetSearchFileSortType(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
resetSearchFileSortType(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||||
|
|
||||||
@@ -17,7 +19,7 @@ export interface NodeIKernelFileAssistantService {
|
|||||||
|
|
||||||
cancelSearchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
cancelSearchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||||
|
|
||||||
downloadFile(arg1: unknown[]): unknown;
|
downloadFile(fileIds: string[]): { result: number, errMsg: string };
|
||||||
|
|
||||||
forwardFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
forwardFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||||
|
|
||||||
|
@@ -155,7 +155,7 @@ export interface NodeIKernelRichMediaService {
|
|||||||
}): unknown;
|
}): unknown;
|
||||||
|
|
||||||
//arg3为“”
|
//arg3为“”
|
||||||
downloadFileForModelId(peer: Peer, ModelId: string[], unknown: string): Promise<unknown>;
|
downloadFileForModelId(peer: Peer, ModelId: string[]): Promise<unknown>;
|
||||||
|
|
||||||
//第三个参数 Array<Type>
|
//第三个参数 Array<Type>
|
||||||
// this.fileId = "";
|
// this.fileId = "";
|
||||||
|
@@ -60,11 +60,12 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
//群文件模式
|
//群文件模式
|
||||||
const contextModelIdFile = FileNapCatOneBotUUID.decodeModelId(payload.file);
|
const contextModelIdFile = FileNapCatOneBotUUID.decodeModelId(payload.file);
|
||||||
if (contextModelIdFile) {
|
if (contextModelIdFile) {
|
||||||
const { peer, modelId } = contextModelIdFile;
|
const { peer, modelId } = contextModelIdFile;
|
||||||
const downloadPath = await NTQQFileApi.downloadFileForModelId(peer, modelId,'');
|
const downloadPath = await NTQQFileApi.downloadFileForModelId(peer, modelId);
|
||||||
const res: GetFileResponse = {
|
const res: GetFileResponse = {
|
||||||
file: downloadPath,
|
file: downloadPath,
|
||||||
url: downloadPath,
|
url: downloadPath,
|
||||||
@@ -83,29 +84,14 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//搜索名字模式
|
//搜索名字模式
|
||||||
const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems;
|
const searchResult = (await NTQQFileApi.searchForFile([payload.file]));
|
||||||
if (NTSearchNameResult.length !== 0) {
|
if (searchResult) {
|
||||||
const MsgId = NTSearchNameResult[0].msgId;
|
const downloadPath = await NTQQFileApi.downloadFileById(searchResult.id, parseInt(searchResult.fileSize));
|
||||||
let peer: Peer | undefined = undefined;
|
|
||||||
if (NTSearchNameResult[0].chatType == ChatType.KCHATTYPEGROUP) {
|
|
||||||
peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: NTSearchNameResult[0].groupChatInfo[0].groupCode };
|
|
||||||
}
|
|
||||||
if (!peer) throw new Error('chattype not support');
|
|
||||||
const msgList: RawMessage[] = (await NTQQMsgApi.getMsgsByMsgId(peer, [MsgId]))?.msgList;
|
|
||||||
if (!msgList || msgList.length == 0) {
|
|
||||||
throw new Error('msg not found');
|
|
||||||
}
|
|
||||||
const msg = msgList[0];
|
|
||||||
const file = msg.elements.filter(e => e.elementType == NTSearchNameResult[0].elemType);
|
|
||||||
if (file.length == 0) {
|
|
||||||
throw new Error('file not found');
|
|
||||||
}
|
|
||||||
const downloadPath = await NTQQFileApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid, file[0].elementId, '', '');
|
|
||||||
const res: GetFileResponse = {
|
const res: GetFileResponse = {
|
||||||
file: downloadPath,
|
file: downloadPath,
|
||||||
url: downloadPath,
|
url: downloadPath,
|
||||||
file_size: NTSearchNameResult[0].fileSize.toString(),
|
file_size: searchResult.fileSize.toString(),
|
||||||
file_name: NTSearchNameResult[0].fileName,
|
file_name: searchResult.fileName,
|
||||||
};
|
};
|
||||||
if (this.obContext.configLoader.configData.enableLocalFile2Url && downloadPath) {
|
if (this.obContext.configLoader.configData.enableLocalFile2Url && downloadPath) {
|
||||||
try {
|
try {
|
||||||
|
@@ -78,7 +78,7 @@ export class OneBotQuickActionApi {
|
|||||||
sendElements,
|
sendElements,
|
||||||
deleteAfterSentFiles,
|
deleteAfterSentFiles,
|
||||||
} = await this.obContext.apis.MsgApi.createSendElements(replyMessage, peer);
|
} = await this.obContext.apis.MsgApi.createSendElements(replyMessage, peer);
|
||||||
this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, sendElements, deleteAfterSentFiles, false).then().catch(this.core.context.logger.logError);
|
this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, sendElements, deleteAfterSentFiles, false).then().catch(this.core.context.logger.logError.bind(this.core.context.logger));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,13 +88,13 @@ export class OneBotQuickActionApi {
|
|||||||
request.flag,
|
request.flag,
|
||||||
quickAction.approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
|
quickAction.approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
|
||||||
quickAction.reason,
|
quickAction.reason,
|
||||||
).catch(this.core.context.logger.logError);
|
).catch(this.core.context.logger.logError.bind(this.core.context.logger));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleFriendRequest(request: OB11FriendRequestEvent, quickAction: QuickActionFriendRequest) {
|
async handleFriendRequest(request: OB11FriendRequestEvent, quickAction: QuickActionFriendRequest) {
|
||||||
if (!isNull(quickAction.approve)) {
|
if (!isNull(quickAction.approve)) {
|
||||||
this.core.apis.FriendApi.handleFriendRequest(request.flag, !!quickAction.approve).then().catch(this.core.context.logger.logError);
|
this.core.apis.FriendApi.handleFriendRequest(request.flag, !!quickAction.approve).then().catch(this.core.context.logger.logError.bind(this.core.context.logger));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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.2.24', 'napcat-update-button', 'secondary'),
|
SettingButton('V2.2.25', '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.2.24", "napcat-update-button", "secondary")
|
SettingButton("V2.2.25", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
Reference in New Issue
Block a user