Compare commits

...

35 Commits

Author SHA1 Message Date
手瓜一十雪
30d0174f47 fix: #334 2024-09-03 13:20:10 +08:00
手瓜一十雪
5a986ba25c release: 2.2.40 2024-09-03 13:01:37 +08:00
手瓜一十雪
fe63c24ac3 release: 2.2.39 2024-09-03 12:40:13 +08:00
手瓜一十雪
c384bd6875 release: 2.2.38 2024-09-02 17:31:27 +08:00
手瓜一十雪
dcbff3f569 release: 2.2.37 2024-09-02 16:31:42 +08:00
手瓜一十雪
7d91e05a69 fix: #332 2024-09-02 16:31:18 +08:00
手瓜一十雪
a5ce424a40 release: 2.2.36 2024-09-01 18:44:23 +08:00
手瓜一十雪
47c36ca062 release: 2.2.35 2024-09-01 18:24:49 +08:00
手瓜一十雪
c4c5b3bf8b fix: remark 2024-09-01 18:24:29 +08:00
手瓜一十雪
b1a81b0d12 release: 2.2.32 2024-09-01 16:32:13 +08:00
手瓜一十雪
ad9fe64850 release: 2.2.32 2024-09-01 16:13:41 +08:00
手瓜一十雪
f236349dc6 Revert "release:2.2.31"
This reverts commit 309d8a9f18.
2024-09-01 16:13:14 +08:00
手瓜一十雪
5f56c8a7d4 fix 2024-09-01 16:10:16 +08:00
手瓜一十雪
309d8a9f18 release:2.2.31 2024-09-01 15:59:02 +08:00
手瓜一十雪
2981799803 fix: file api 2024-09-01 14:11:28 +08:00
手瓜一十雪
00f8e1c0da Revert "fix: fileId"
This reverts commit ae009f98c1.
2024-09-01 13:41:19 +08:00
手瓜一十雪
e9482e2ec4 Revert "fix: encode fileId"
This reverts commit 9bff327377.
2024-09-01 13:41:14 +08:00
手瓜一十雪
9bff327377 fix: encode fileId 2024-09-01 12:17:42 +08:00
手瓜一十雪
ae009f98c1 fix: fileId 2024-09-01 12:17:17 +08:00
手瓜一十雪
77505a6f5b release: 2.2.31 2024-09-01 09:31:59 +08:00
手瓜一十雪
19c729aa23 chore: appid 2024-09-01 09:30:38 +08:00
Wesley F. Young
595888128a release: 2.2.30 2024-08-31 23:43:01 +08:00
手瓜一十雪
51589d0eae fix: 群精华上限修改 2024-08-31 22:11:18 +08:00
Wesley F. Young
f1643ac549 fix: get file way 01 get by msg & seq id 2024-08-31 20:30:42 +08:00
手瓜一十雪
3f24461612 feat: support 27597 2024-08-31 19:01:25 +08:00
Wesley F. Young
b5deb198de refactor: inline all NTQQXxxApi uses 2024-08-31 16:00:03 +08:00
Wesley F. Young
78452cf6a9 chore: clean code for webapi.ts 2024-08-31 14:18:11 +08:00
Wesley F. Young
4b4a784f56 chore: clean code for user.ts 2024-08-31 14:11:22 +08:00
Wesley F. Young
3e53cbcf8f chore: clean code for system.ts 2024-08-31 14:09:25 +08:00
Wesley F. Young
f34740f1f0 chore: clean code for group.ts 2024-08-31 14:07:48 +08:00
Wesley F. Young
b406bdfc37 chore: clean code for group.ts 2024-08-31 14:02:36 +08:00
Wesley F. Young
03c056702c chore: clean code for friend.ts 2024-08-31 13:53:30 +08:00
Wesley F. Young
9c5f3f1946 chore: clean code for collection.ts 2024-08-31 13:37:22 +08:00
Wesley F. Young
b50d7c24e7 refactor: move CacheApi to cache.ts 2024-08-31 13:36:21 +08:00
Wesley F. Young
f05cf68945 chore: clean code for file.ts 2024-08-31 13:35:29 +08:00
98 changed files with 557 additions and 1166 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.2.29", "version": "2.2.41",
"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.2.29", "version": "2.2.41",
"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",

Binary file not shown.

View File

@@ -25,29 +25,31 @@ export async function solveAsyncProblem<T extends (...args: any[]) => Promise<an
} }
export class FileNapCatOneBotUUID { export class FileNapCatOneBotUUID {
static encodeModelId(peer: Peer, modelId: string): string { static encodeModelId(peer: Peer, modelId: string, fileId: string): string {
return `NapCatOneBot-ModelIdFile-${peer.chatType}-${peer.peerUid}-${modelId}`; return `NapCatOneBot|ModelIdFile|${peer.chatType}|${peer.peerUid}|${modelId}|${fileId}`;
} }
static decodeModelId(uuid: string): undefined | { static decodeModelId(uuid: string): undefined | {
peer: Peer, peer: Peer,
modelId: string modelId: string,
fileId: string
} { } {
if (!uuid.startsWith('NapCatOneBot-ModelIdFile-')) return undefined; if (!uuid.startsWith('NapCatOneBot|ModelIdFile|')) return undefined;
const data = uuid.split('-'); const data = uuid.split('|');
if (data.length !== 5) return undefined; if (data.length !== 6) return undefined;
const [, , chatType, peerUid, modelId] = data; const [, , chatType, peerUid, modelId,fileId] = data;
return { return {
peer: { peer: {
chatType: chatType as any, chatType: chatType as any,
peerUid: peerUid, peerUid: peerUid,
}, },
modelId, modelId,
fileId
}; };
} }
static encode(peer: Peer, msgId: string, elementId: string): string { static encode(peer: Peer, msgId: string, elementId: string): string {
return `NapCatOneBot-MsgFile-${peer.chatType}-${peer.peerUid}-${msgId}-${elementId}`; return `NapCatOneBot|MsgFile|${peer.chatType}|${peer.peerUid}|${msgId}|${elementId}`;
} }
static decode(uuid: string): undefined | { static decode(uuid: string): undefined | {
@@ -55,8 +57,8 @@ export class FileNapCatOneBotUUID {
msgId: string, msgId: string,
elementId: string elementId: string
} { } {
if (!uuid.startsWith('NapCatOneBot-MsgFile-')) return undefined; if (!uuid.startsWith('NapCatOneBot|MsgFile|')) return undefined;
const data = uuid.split('-'); const data = uuid.split('|');
if (data.length !== 6) return undefined; if (data.length !== 6) return undefined;
const [, , chatType, peerUid, msgId, elementId] = data; const [, , chatType, peerUid, msgId, elementId] = data;
return { return {
@@ -138,19 +140,19 @@ export function isEqual(obj1: any, obj2: any) {
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType { export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
if (os.platform() === 'linux') { if (os.platform() === 'linux') {
return { return {
baseVersion: '3.2.12-27254', baseVersion: '3.2.12-27597',
curVersion: '3.2.12-27254', curVersion: '3.2.12-27597',
prevVersion: '', prevVersion: '',
onErrorVersions: [], onErrorVersions: [],
buildId: '27254', buildId: '27597',
}; };
} }
return { return {
baseVersion: '9.9.15-27391', baseVersion: '9.9.15-27597',
curVersion: '9.9.15-27391', curVersion: '9.9.15-27597',
prevVersion: '', prevVersion: '',
onErrorVersions: [], onErrorVersions: [],
buildId: '27391', buildId: '27597',
}; };
} }

View File

@@ -71,6 +71,6 @@ export class QQBasicInfoWrapper {
// else // else
this.context.logger.log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`); this.context.logger.log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`);
this.context.logger.log(`[QQ版本兼容性检测] ${fullVersion} 版本兼容性不佳,可能会导致一些功能无法正常使用`,); this.context.logger.log(`[QQ版本兼容性检测] ${fullVersion} 版本兼容性不佳,可能会导致一些功能无法正常使用`,);
return { appid: systemPlatform === 'linux' ? '537240795' : '537240709', qua: this.getQUAInternal() }; return { appid: systemPlatform === 'linux' ? '537243600' : '537243441', qua: this.getQUAInternal() };
} }
} }

View File

@@ -1 +1 @@
export const napCatVersion = '2.2.29'; export const napCatVersion = '2.2.41';

View File

@@ -16,7 +16,8 @@ export async function getVideoInfo(filePath: string, logger: LogWrapper) {
filePath: string filePath: string
}>((resolve, reject) => { }>((resolve, reject) => {
const ffmpegPath = process.env.FFMPEG_PATH; const ffmpegPath = process.env.FFMPEG_PATH;
ffmpegPath && ffmpeg.setFfmpegPath(ffmpegPath); if (ffmpegPath)
ffmpeg.setFfmpegPath(ffmpegPath);
ffmpeg(filePath).ffprobe((err: any, metadata: ffmpeg.FfprobeData) => { ffmpeg(filePath).ffprobe((err: any, metadata: ffmpeg.FfprobeData) => {
if (err) { if (err) {
reject(err); reject(err);

63
src/core/apis/cache.ts Normal file
View File

@@ -0,0 +1,63 @@
import {
CacheFileListItem,
CacheFileType,
ChatCacheListItemBasic,
ChatType,
InstanceContext,
NapCatCore,
} from '@/core';
export class NTQQCacheApi {
context: InstanceContext;
core: NapCatCore;
constructor(context: InstanceContext, core: NapCatCore) {
this.context = context;
this.core = core;
}
async setCacheSilentScan(isSilent: boolean = true) {
return '';
}
getCacheSessionPathList() {
return '';
}
clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
// 参数未验证
return this.context.session.getStorageCleanService().clearCacheDataByKeys(cacheKeys);
}
addCacheScannedPaths(pathMap: object = {}) {
return this.context.session.getStorageCleanService().addCacheScanedPaths(pathMap);
}
scanCache() {
//return (await this.context.session.getStorageCleanService().scanCache()).size;
}
getHotUpdateCachePath() {
// 未实现
return '';
}
getDesktopTmpPath() {
// 未实现
return '';
}
getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) {
return this.context.session.getStorageCleanService().getChatCacheInfo(type, pageSize, 1, pageIndex);
}
getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
// const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
// 需要五个参数
// return napCatCore.session.getStorageCleanService().getFileCacheInfo();
}
async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
return this.context.session.getStorageCleanService().clearChatCacheInfo(chats, fileKeys);
}
}

View File

@@ -10,7 +10,7 @@ export class NTQQCollectionApi {
} }
async createCollection(authorUin: string, authorUid: string, authorName: string, brief: string, rawData: string) { async createCollection(authorUin: string, authorUid: string, authorName: string, brief: string, rawData: string) {
const param = { return this.context.session.getCollectionService().createNewCollectionItem({
commInfo: { commInfo: {
bid: 1, bid: 1,
category: 2, category: 2,
@@ -43,12 +43,11 @@ export class NTQQCollectionApi {
fileList: [], fileList: [],
}, },
need_share_url: false, need_share_url: false,
}; });
return this.context.session.getCollectionService().createNewCollectionItem(param);
} }
async getAllCollection(category: number = 0, count: number = 50) { async getAllCollection(category: number = 0, count: number = 50) {
const param = { return this.context.session.getCollectionService().getCollectionItemList({
category: category, category: category,
groupId: -1, groupId: -1,
forceSync: true, forceSync: true,
@@ -56,7 +55,6 @@ export class NTQQCollectionApi {
timeStamp: '0', timeStamp: '0',
count: count, count: count,
searchDown: true, searchDown: true,
}; });
return this.context.session.getCollectionService().getCollectionItemList(param);
} }
} }

View File

@@ -1,7 +1,4 @@
import { import {
CacheFileListItem,
CacheFileType,
ChatCacheListItemBasic,
ChatType, ChatType,
ElementType, ElementType,
IMAGE_HTTP_HOST, IMAGE_HTTP_HOST,
@@ -26,10 +23,8 @@ import { calculateFileMD5, isGIF } from '@/common/file';
import pathLib from 'node:path'; import pathLib from 'node:path';
import { defaultVideoThumbB64, getVideoInfo } from '@/common/video'; import { defaultVideoThumbB64, getVideoInfo } from '@/common/video';
import ffmpeg from 'fluent-ffmpeg'; import ffmpeg from 'fluent-ffmpeg';
import fsnormal from 'node:fs';
import { encodeSilk } from '@/common/audio'; import { encodeSilk } from '@/common/audio';
export class NTQQFileApi { export class NTQQFileApi {
context: InstanceContext; context: InstanceContext;
core: NapCatCore; core: NapCatCore;
@@ -41,10 +36,6 @@ export class NTQQFileApi {
this.rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey', this.context.logger); this.rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey', this.context.logger);
} }
async getFileType(filePath: string) {
return fileType.fileTypeFromFile(filePath);
}
async copyFile(filePath: string, destPath: string) { async copyFile(filePath: string, destPath: string) {
await this.core.util.copyFile(filePath, destPath); await this.core.util.copyFile(filePath, destPath);
} }
@@ -60,18 +51,15 @@ export class NTQQFileApi {
})).urlResult.domainUrl; })).urlResult.domainUrl;
} }
// 上传文件到QQ的文件夹
async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) { async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) {
// napCatCore.wrapper.util.
const fileMd5 = await calculateFileMD5(filePath); const fileMd5 = await calculateFileMD5(filePath);
let ext: string = (await this.getFileType(filePath))?.ext as string || ''; const extOrEmpty = (await fileType.fileTypeFromFile(filePath))?.ext;
if (ext) { const ext = extOrEmpty ? `.${extOrEmpty}` : '';
ext = '.' + ext;
}
let fileName = `${path.basename(filePath)}`; let fileName = `${path.basename(filePath)}`;
if (fileName.indexOf('.') === -1) { if (fileName.indexOf('.') === -1) {
fileName += ext; fileName += ext;
} }
const mediaPath = this.context.session.getMsgService().getRichMediaFilePathForGuild({ const mediaPath = this.context.session.getMsgService().getRichMediaFilePathForGuild({
md5HexStr: fileMd5, md5HexStr: fileMd5,
fileName: fileName, fileName: fileName,
@@ -82,6 +70,7 @@ export class NTQQFileApi {
downloadType: 1, downloadType: 1,
file_uuid: '', file_uuid: '',
}); });
await this.copyFile(filePath, mediaPath!); await this.copyFile(filePath, mediaPath!);
const fileSize = await this.getFileSize(filePath); const fileSize = await this.getFileSize(filePath);
return { return {
@@ -93,11 +82,7 @@ export class NTQQFileApi {
}; };
} }
async createValidSendFileElement( async createValidSendFileElement(filePath: string, fileName: string = '', folderId: string = '',): Promise<SendFileElement> {
filePath: string,
fileName: string = '',
folderId: string = '',
): Promise<SendFileElement> {
const { const {
fileName: _fileName, fileName: _fileName,
path, path,
@@ -118,55 +103,36 @@ export class NTQQFileApi {
}; };
} }
async createValidSendPicElement( async createValidSendPicElement(picPath: string, summary: string = '', subType: 0 | 1 = 0,): Promise<SendPicElement> {
picPath: string, const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType);
summary: string = '',
subType: 0 | 1 = 0,
): Promise<SendPicElement> {
const {
md5,
fileName,
path,
fileSize,
} = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType);
if (fileSize === 0) { if (fileSize === 0) {
throw new Error('文件异常大小为0'); throw new Error('文件异常大小为0');
} }
const imageSize = await this.core.apis.FileApi.getImageSize(picPath); const imageSize = await this.core.apis.FileApi.getImageSize(picPath);
const picElement: any = {
md5HexStr: md5,
fileSize: fileSize.toString(),
picWidth: imageSize?.width,
picHeight: imageSize?.height,
fileName: fileName,
sourcePath: path,
original: true,
picType: isGIF(picPath) ? PicType.gif : PicType.jpg,
picSubType: subType,
fileUuid: '',
fileSubId: '',
thumbFileSize: 0,
summary,
};
return { return {
elementType: ElementType.PIC, elementType: ElementType.PIC,
elementId: '', elementId: '',
picElement, picElement: {
md5HexStr: md5,
fileSize: fileSize.toString(),
picWidth: imageSize.width,
picHeight: imageSize.height,
fileName: fileName,
sourcePath: path,
original: true,
picType: isGIF(picPath) ? PicType.gif : PicType.jpg,
picSubType: subType,
fileUuid: '',
fileSubId: '',
thumbFileSize: 0,
summary,
} as PicElement,
}; };
} }
async createValidSendVideoElement( async createValidSendVideoElement(filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> {
filePath: string,
fileName: string = '',
diyThumbPath: string = '',
): Promise<SendVideoElement> {
const logger = this.core.context.logger; const logger = this.core.context.logger;
const { const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
fileName: _fileName,
path,
fileSize,
md5,
} = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
if (fileSize === 0) { if (fileSize === 0) {
throw new Error('文件异常大小为0'); throw new Error('文件异常大小为0');
} }
@@ -182,9 +148,10 @@ export class NTQQFileApi {
try { try {
videoInfo = await getVideoInfo(path, logger); videoInfo = await getVideoInfo(path, logger);
} catch (e) { } catch (e) {
logger.logError('获取视频信息失败', e); logger.logError('获取视频信息失败,将使用默认值', e);
} }
const createThumb = new Promise<string | undefined>((resolve, reject) => { const thumbPath = new Map();
const _thumbPath = await new Promise<string | undefined>((resolve, reject) => {
const thumbFileName = `${md5}_0.png`; const thumbFileName = `${md5}_0.png`;
const thumbPath = pathLib.join(thumb, thumbFileName); const thumbPath = pathLib.join(thumb, thumbFileName);
ffmpeg(filePath) ffmpeg(filePath)
@@ -195,7 +162,7 @@ export class NTQQFileApi {
resolve(thumbPath); resolve(thumbPath);
}).catch(reject); }).catch(reject);
} else { } else {
fsnormal.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64')); fs.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64'));
resolve(thumbPath); resolve(thumbPath);
} }
}) })
@@ -204,31 +171,14 @@ export class NTQQFileApi {
filename: thumbFileName, filename: thumbFileName,
folder: thumb, folder: thumb,
size: videoInfo.width + 'x' + videoInfo.height, size: videoInfo.width + 'x' + videoInfo.height,
}).on('end', () => { })
.on('end', () => {
resolve(thumbPath); resolve(thumbPath);
}); });
}); });
const thumbPath = new Map();
const _thumbPath = await createThumb;
const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0; const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0;
// log("生成缩略图", _thumbPath)
thumbPath.set(0, _thumbPath); thumbPath.set(0, _thumbPath);
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : ''; const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : '';
// "fileElement": {
// "fileMd5": "",
// "fileName": "1.mp4",
// "filePath": "C:\\Users\\nanae\\OneDrive\\Desktop\\1.mp4",
// "fileSize": "1847007",
// "picHeight": 1280,
// "picWidth": 720,
// "picThumbPath": {},
// "file10MMd5": "",
// "fileSha": "",
// "fileSha3": "",
// "fileUuid": "",
// "fileSubId": "",
// "thumbFileSize": 750
// }
return { return {
elementType: ElementType.VIDEO, elementType: ElementType.VIDEO,
elementId: '', elementId: '',
@@ -243,28 +193,12 @@ export class NTQQFileApi {
thumbWidth: videoInfo.width, thumbWidth: videoInfo.width,
thumbHeight: videoInfo.height, thumbHeight: videoInfo.height,
fileSize: '' + fileSize, fileSize: '' + fileSize,
// fileFormat: videotype
// fileUuid: "",
// transferStatus: 0,
// progress: 0,
// invalidState: 0,
// fileSubId: "",
// fileBizId: null,
// originVideoMd5: "",
// fileFormat: 2,
// import_rich_media_context: null,
// sourceVideoCodecFormat: 2
}, },
}; };
} }
async createValidSendPttElement(pttPath: string): Promise<SendPttElement> { async createValidSendPttElement(pttPath: string): Promise<SendPttElement> {
const { const { converted, path: silkPath, duration } = await encodeSilk(pttPath, this.core.NapCatTempPath, this.core.context.logger);
converted,
path: silkPath,
duration,
} = await encodeSilk(pttPath, this.core.NapCatTempPath, this.core.context.logger);
// 生成语音 Path: silkPath Time: duration
if (!silkPath) { if (!silkPath) {
throw new Error('语音转换失败, 请检查语音文件是否正常'); throw new Error('语音转换失败, 请检查语音文件是否正常');
} }
@@ -283,7 +217,6 @@ export class NTQQFileApi {
filePath: path, filePath: path,
md5HexStr: md5, md5HexStr: md5,
fileSize: fileSize, fileSize: fileSize,
// duration: Math.max(1, Math.round(fileSize / 1024 / 3)), // 一秒钟大概是3kb大小, 小于1秒的按1秒算
duration: duration ?? 1, duration: duration ?? 1,
formatType: 1, formatType: 1,
voiceType: 1, voiceType: 1,
@@ -299,9 +232,6 @@ export class NTQQFileApi {
}; };
} }
async downloadMediaByUuid() {
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
}
async downloadFileForModelId(peer: Peer, modelId: string, unknown: string, timeout = 1000 * 60 * 2) { async downloadFileForModelId(peer: Peer, modelId: string, unknown: string, timeout = 1000 * 60 * 2) {
const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2( const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelRichMediaService/downloadFileForModelId', 'NodeIKernelRichMediaService/downloadFileForModelId',
@@ -314,6 +244,7 @@ export class NTQQFileApi {
); );
return fileTransNotifyInfo.filePath; return fileTransNotifyInfo.filePath;
} }
async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) { async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
//logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force); //logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
// 用于下载收到的消息中的图片等 // 用于下载收到的消息中的图片等
@@ -328,7 +259,7 @@ export class NTQQFileApi {
return sourcePath; return sourcePath;
} }
} }
const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2( const [, completeRetData] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelMsgService/downloadRichMedia', 'NodeIKernelMsgService/downloadRichMedia',
'NodeIKernelMsgListener/onRichMediaDownloadComplete', 'NodeIKernelMsgListener/onRichMediaDownloadComplete',
[{ [{
@@ -348,29 +279,20 @@ export class NTQQFileApi {
1, 1,
timeout, timeout,
); );
const msg = await this.core.apis.MsgApi.getMsgsByMsgId({ return completeRetData.filePath;
guildId: '',
chatType: chatType,
peerUid: peerUid,
}, [msgId]);
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;
let realPath = mixElementInner?.filePath;
if (!realPath) {
const picThumbPath: Map<number, string> = (mixElementInner as any)?.picThumbPath;
const picThumbPathList = Array.from(picThumbPath.values());
if (picThumbPathList.length > 0) realPath = picThumbPathList[0];
}
return realPath;
} }
async getImageSize(filePath: string): Promise<ISizeCalculationResult | undefined> { async getImageSize(filePath: string): Promise<ISizeCalculationResult> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
imageSize(filePath, (err, dimensions) => { imageSize(filePath, (err, dimensions) => {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
resolve(dimensions); if (!dimensions) {
reject(new Error('获取图片尺寸失败'));
} else {
resolve(dimensions);
}
} }
}); });
}); });
@@ -443,11 +365,8 @@ export class NTQQFileApi {
'NodeIKernelFileAssistantListener/onFileSearch', 'NodeIKernelFileAssistantListener/onFileSearch',
[ [
keys, keys,
{ { resultType: 2, pageLimit: 1 },
resultType: 2, randomResultId,
pageLimit: 1,
},
randomResultId
], ],
(ret) => { (ret) => {
searchId = ret; searchId = ret;
@@ -463,7 +382,7 @@ export class NTQQFileApi {
fileSize: number = 1024576, fileSize: number = 1024576,
estimatedTime: number = (fileSize * 1000 / 1024576) + 5000, estimatedTime: number = (fileSize * 1000 / 1024576) + 5000,
) { ) {
const [, ret] = await this.core.eventWrapper.callNormalEventV2( const [, fileData] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelFileAssistantService/downloadFile', 'NodeIKernelFileAssistantService/downloadFile',
'NodeIKernelFileAssistantListener/onFileStatusChanged', 'NodeIKernelFileAssistantListener/onFileStatusChanged',
[[fileId]], [[fileId]],
@@ -472,7 +391,7 @@ export class NTQQFileApi {
1, 1,
estimatedTime, // estimate 1MB/s estimatedTime, // estimate 1MB/s
); );
return ret.filePath!; return fileData.filePath!;
} }
async getImageUrl(element: PicElement) { async getImageUrl(element: PicElement) {
@@ -482,20 +401,19 @@ export class NTQQFileApi {
const url: string = element.originImageUrl!; // 没有域名 const url: string = element.originImageUrl!; // 没有域名
const md5HexStr = element.md5HexStr; const md5HexStr = element.md5HexStr;
const fileMd5 = element.md5HexStr; const fileMd5 = element.md5HexStr;
// const fileUuid = element.fileUuid;
if (url) { if (url) {
const UrlParse = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接 const parsedUrl = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接
const imageAppid = UrlParse.searchParams.get('appid'); const imageAppid = parsedUrl.searchParams.get('appid');
const isNewPic = imageAppid && ['1406', '1407'].includes(imageAppid); const isNTFlavoredPic = imageAppid && ['1406', '1407'].includes(imageAppid);
if (isNewPic) { if (isNTFlavoredPic) {
let UrlRkey = UrlParse.searchParams.get('rkey'); let rkey = parsedUrl.searchParams.get('rkey');
if (UrlRkey) { if (rkey) {
return IMAGE_HTTP_HOST_NT + url; return IMAGE_HTTP_HOST_NT + url;
} }
const rkeyData = await this.rkeyManager.getRkey(); const rkeyData = await this.rkeyManager.getRkey();
UrlRkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey; rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
return IMAGE_HTTP_HOST_NT + url + `${UrlRkey}`; return IMAGE_HTTP_HOST_NT + url + `${rkey}`;
} else { } else {
// 老的图片url不需要rkey // 老的图片url不需要rkey
return IMAGE_HTTP_HOST + url; return IMAGE_HTTP_HOST + url;
@@ -509,57 +427,3 @@ export class NTQQFileApi {
} }
} }
export class NTQQFileCacheApi {
context: InstanceContext;
core: NapCatCore;
constructor(context: InstanceContext, core: NapCatCore) {
this.context = context;
this.core = core;
}
async setCacheSilentScan(isSilent: boolean = true) {
return '';
}
getCacheSessionPathList() {
return '';
}
clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
// 参数未验证
return this.context.session.getStorageCleanService().clearCacheDataByKeys(cacheKeys);
}
addCacheScannedPaths(pathMap: object = {}) {
return this.context.session.getStorageCleanService().addCacheScanedPaths(pathMap);
}
scanCache() {
//return (await this.context.session.getStorageCleanService().scanCache()).size;
}
getHotUpdateCachePath() {
// 未实现
return '';
}
getDesktopTmpPath() {
// 未实现
return '';
}
getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) {
return this.context.session.getStorageCleanService().getChatCacheInfo(type, pageSize, 1, pageIndex);
}
getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
// const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
// 需要五个参数
// return napCatCore.session.getStorageCleanService().getFileCacheInfo();
}
async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
return this.context.session.getStorageCleanService().clearChatCacheInfo(chats, fileKeys);
}
}

View File

@@ -16,47 +16,42 @@ export class NTQQFriendApi {
// } // }
} }
async getBuddyV2(refresh = false): Promise<FriendV2[]> { async getBuddyV2SimpleInfoMap(refresh = false) {
const uids: string[] = [];
const buddyService = this.context.session.getBuddyService(); const buddyService = this.context.session.getBuddyService();
const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL); const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids)); const uids = buddyListV2.data.flatMap(item => item.buddyUids);
const data = await this.core.eventWrapper.callNoListenerEvent( return await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids, 'NodeIKernelProfileService/getCoreAndBaseInfo',
'nodeStore',
uids,
); );
return Array.from(data.values()); }
async getBuddyV2(refresh = false): Promise<FriendV2[]> {
return Array.from((await this.getBuddyV2SimpleInfoMap(refresh)).values());
} }
async getBuddyIdMap(refresh = false): Promise<LimitedHashTable<string, string>> { async getBuddyIdMap(refresh = false): Promise<LimitedHashTable<string, string>> {
const uids: string[] = [];
const retMap: LimitedHashTable<string, string> = new LimitedHashTable<string, string>(5000); const retMap: LimitedHashTable<string, string> = new LimitedHashTable<string, string>(5000);
const buddyService = this.context.session.getBuddyService(); const data = await this.getBuddyV2SimpleInfoMap(refresh);
const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL); data.forEach((value) => retMap.set(value.uin!, value.uid!));
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids));
const data = await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids,
);
data.forEach((value) => {
retMap.set(value.uin!, value.uid!);
});
//console.log('getBuddyIdMap', retMap.getValue);
return retMap; return retMap;
} }
async getBuddyV2ExWithCate(refresh = false) { async getBuddyV2ExWithCate(refresh = false) {
const uids: string[] = [];
const categoryMap: Map<string, any> = new Map(); const categoryMap: Map<string, any> = new Map();
const buddyService = this.context.session.getBuddyService(); const buddyService = this.context.session.getBuddyService();
const buddyListV2 = refresh ? (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data : (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data; const buddyListV2 = refresh ? (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data : (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data;
uids.push( const uids = buddyListV2.flatMap(item => {
...buddyListV2.flatMap(item => { item.buddyUids.forEach(uid => {
item.buddyUids.forEach(uid => { categoryMap.set(uid, { categoryId: item.categoryId, categoryName: item.categroyName });
categoryMap.set(uid, { categoryId: item.categoryId, categoryName: item.categroyName }); });
}); return item.buddyUids;
return item.buddyUids; });
}));
const data = await this.core.eventWrapper.callNoListenerEvent( const data = await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids, 'NodeIKernelProfileService/getCoreAndBaseInfo',
'nodeStore',
uids,
); );
return buddyListV2.map(category => ({ return buddyListV2.map(category => ({
categoryId: category.categoryId, categoryId: category.categoryId,

View File

@@ -34,17 +34,20 @@ export class NTQQGroupApi {
} }
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`); this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
} }
async fetchGroupEssenceList(groupCode: string) { async fetchGroupEssenceList(groupCode: 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().fetchGroupEssenceList({ return this.context.session.getGroupService().fetchGroupEssenceList({
groupCode: groupCode, groupCode: groupCode,
pageStart: 0, pageStart: 0,
pageLimit: 300 pageLimit: 300,
}, pskey); }, pskey);
} }
async clearGroupNotifiesUnreadCount(unk: boolean) { async clearGroupNotifiesUnreadCount(unk: boolean) {
return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(unk); return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(unk);
} }
async setGroupAvatar(gc: string, filePath: string) { async setGroupAvatar(gc: string, filePath: string) {
return this.context.session.getGroupService().setHeader(gc, filePath); return this.context.session.getGroupService().setHeader(gc, filePath);
} }
@@ -57,6 +60,7 @@ export class NTQQGroupApi {
); );
return groupList; return groupList;
} }
async getGroupExtFE0Info(GroupCode: string[], forced = true) { async getGroupExtFE0Info(GroupCode: string[], forced = true) {
return this.context.session.getGroupService().getGroupExt0xEF0Info( return this.context.session.getGroupService().getGroupExt0xEF0Info(
GroupCode, GroupCode,
@@ -93,11 +97,12 @@ export class NTQQGroupApi {
showPlayTogetherSwitch: 1, showPlayTogetherSwitch: 1,
starId: 1, starId: 1,
todoSeq: 1, todoSeq: 1,
viewedMsgDisappearTime: 1 viewedMsgDisappearTime: 1,
}, },
forced forced,
); );
} }
async getGroup(groupCode: string, forced = false) { async getGroup(groupCode: string, forced = false) {
let group = this.groupCache.get(groupCode.toString()); let group = this.groupCache.get(groupCode.toString());
if (!group) { if (!group) {
@@ -116,62 +121,6 @@ export class NTQQGroupApi {
return group; return group;
} }
async getGroupMemberLatestSendTimeCache(GroupCode: string, uids: string[]) {
return this.getGroupMemberLatestSendTime(GroupCode, uids);
}
/**
* 通过QQ自带数据库获取群成员最后发言时间(仅返回有效数据 且消耗延迟大 需要进行缓存)
* @param GroupCode 群号
* @param uids QQ号
* @returns Map<string, string> key: uin value: sendTime
* @example
* let ret = await NTQQGroupApi.getGroupMemberLastestSendTime('123456');
* for (let [uin, sendTime] of ret) {
* console.log(uin, sendTime);
* }
*/
async getGroupMemberLatestSendTime(GroupCode: string, uids: string[]) {
const getdata = async (uid: string) => {
const NTRet = await this.getLatestMsgByUids(GroupCode, [uid]);
if (NTRet.result != 0 && NTRet.msgList.length < 1) {
return undefined;
}
return { sendUin: NTRet.msgList[0].senderUin, sendTime: NTRet.msgList[0].msgTime };
};
const PromiseData: Promise<({
sendUin: string;
sendTime: string;
} | undefined)>[] = [];
const ret: Map<string, string> = new Map();
for (const uid of uids) {
PromiseData.push(getdata(uid).catch(() => undefined));
}
const allRet = await runAllWithTimeout(PromiseData, 2500);
for (const PromiseDo of allRet) {
if (PromiseDo) {
ret.set(PromiseDo.sendUin, PromiseDo.sendTime);
}
}
return ret;
}
async getLatestMsgByUids(GroupCode: string, uids: string[]) {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
chatInfo: {
peerUid: GroupCode,
chatType: ChatType.KCHATTYPEGROUP,
},
filterMsgType: [],
filterSendersUid: uids,
filterMsgToTime: '0',
filterMsgFromTime: '0',
isReverseOrder: false,
isIncludeCurrent: true,
pageLimit: 1,
});
}
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);
} }
@@ -208,30 +157,6 @@ export class NTQQGroupApi {
} }
return member; return member;
} }
async getLatestMsg(GroupCode: string, uins: string[]) {
const uids: Array<string> = [];
for (const uin of uins) {
const uid = await this.core.apis.UserApi.getUidByUinV2(uin);
if (uid) {
uids.push(uid);
}
}
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
chatInfo: {
peerUid: GroupCode,
chatType: ChatType.KCHATTYPEGROUP,
},
filterMsgType: [],
filterSendersUid: uids,
filterMsgToTime: '0',
filterMsgFromTime: '0',
isReverseOrder: false,
isIncludeCurrent: true,
pageLimit: 1,
});
}
async getGroupRecommendContactArkJson(GroupCode: string) { async getGroupRecommendContactArkJson(GroupCode: string) {
return this.context.session.getGroupService().getGroupRecommendContactArkJson(GroupCode); return this.context.session.getGroupService().getGroupRecommendContactArkJson(GroupCode);
} }
@@ -249,8 +174,7 @@ export class NTQQGroupApi {
} }
async addGroupEssence(GroupCode: string, msgId: string) { async addGroupEssence(GroupCode: string, msgId: string) {
// 代码没测过 // 需要 ob11msgId -> msgId + (peer) -> msgSeq + msgRandom
// 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({ const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
chatType: 2, chatType: 2,
guildId: '', guildId: '',
@@ -261,7 +185,7 @@ export class NTQQGroupApi {
msgRandom: parseInt(MsgData.msgList[0].msgRandom), msgRandom: parseInt(MsgData.msgList[0].msgRandom),
msgSeq: parseInt(MsgData.msgList[0].msgSeq), msgSeq: parseInt(MsgData.msgList[0].msgSeq),
}; };
// GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数 // GetMsgByShortID(shortID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
return this.context.session.getGroupService().addGroupEssence(param); return this.context.session.getGroupService().addGroupEssence(param);
} }
@@ -270,8 +194,8 @@ export class NTQQGroupApi {
} }
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) {
@@ -282,18 +206,17 @@ export class NTQQGroupApi {
//应该是直接返回不需要Listener的 未经测试 需测试再发布 //应该是直接返回不需要Listener的 未经测试 需测试再发布
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),
}; };
// GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
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) {
// 代码没测过
// 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({ const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
chatType: 2, chatType: 2,
guildId: '', guildId: '',
@@ -304,7 +227,6 @@ export class NTQQGroupApi {
msgRandom: parseInt(MsgData.msgList[0].msgRandom), msgRandom: parseInt(MsgData.msgList[0].msgRandom),
msgSeq: parseInt(MsgData.msgList[0].msgSeq), msgSeq: parseInt(MsgData.msgList[0].msgSeq),
}; };
// GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
return this.context.session.getGroupService().removeGroupEssence(param); return this.context.session.getGroupService().removeGroupEssence(param);
} }
@@ -361,7 +283,7 @@ export class NTQQGroupApi {
if (membersFromFunc.status === 'fulfilled' && membersFromListener.status === 'fulfilled') { if (membersFromFunc.status === 'fulfilled' && membersFromListener.status === 'fulfilled') {
return new Map([ return new Map([
...membersFromFunc.value.result.infos, ...membersFromFunc.value.result.infos,
...membersFromListener.value[0].infos ...membersFromListener.value[0].infos,
]); ]);
} }
if (membersFromFunc.status === 'fulfilled') { if (membersFromFunc.status === 'fulfilled') {
@@ -386,19 +308,6 @@ export class NTQQGroupApi {
this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`); //, Array.from(result.result.infos.values())); this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`); //, Array.from(result.result.infos.values()));
return result.result.infos; return result.result.infos;
/*
console.log(sceneId);
const result = await napCatCore.getGroupService().getNextMemberList(sceneId, num);
console.log(result);
return result;
*/
}
async getGroupNotifies() {
// 获取管理员变更
// 加群通知,退出通知,需要管理员权限
} }
async getGroupFileCount(Gids: Array<string>) { async getGroupFileCount(Gids: Array<string>) {
@@ -470,19 +379,12 @@ export class NTQQGroupApi {
return this.context.session.getGroupService().modifyGroupName(groupQQ, groupName, false); return this.context.session.getGroupService().modifyGroupName(groupQQ, groupName, false);
} }
// 头衔不可用
/*
async setGroupTitle(groupQQ: string, uid: string, title: string) {
}
*/
async publishGroupBulletin(groupQQ: string, content: string, picInfo: { async publishGroupBulletin(groupQQ: string, content: string, picInfo: {
id: string, id: string,
width: number, width: number,
height: number height: number
} | undefined = undefined, pinned: number = 0, confirmRequired: number = 0) { } | undefined = undefined, pinned: number = 0, confirmRequired: number = 0) {
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');
//text是content内容url编码 //text是content内容url编码
const data = { const data = {
text: encodeURI(content), text: encodeURI(content),
@@ -491,7 +393,7 @@ export class NTQQGroupApi {
pinned: pinned, pinned: pinned,
confirmRequired: confirmRequired, confirmRequired: confirmRequired,
}; };
return this.context.session.getGroupService().publishGroupBulletin(groupQQ, _Pskey!, data); return this.context.session.getGroupService().publishGroupBulletin(groupQQ, psKey!, data);
} }
async getGroupRemainAtTimes(GroupCode: string) { async getGroupRemainAtTimes(GroupCode: string) {

View File

@@ -5,4 +5,5 @@ export * from './msg';
export * from './user'; export * from './user';
export * from './webapi'; export * from './webapi';
export * from './sign'; export * from './sign';
export * from './system'; export * from './system';
export * from './cache';

View File

@@ -14,12 +14,15 @@ export class NTQQMsgApi {
this.context = context; this.context = context;
this.core = core; this.core = core;
} }
async getAioFirstViewLatestMsgs(peer: Peer, MsgCount: number) { async getAioFirstViewLatestMsgs(peer: Peer, MsgCount: number) {
return this.context.session.getMsgService().getAioFirstViewLatestMsgs(peer, MsgCount); return this.context.session.getMsgService().getAioFirstViewLatestMsgs(peer, MsgCount);
} }
async getLatestDbMsgs(peer: Peer, MsgCount: number) { async getLatestDbMsgs(peer: Peer, MsgCount: number) {
return this.context.session.getMsgService().getLatestDbMsgs(peer, MsgCount); return this.context.session.getMsgService().getLatestDbMsgs(peer, MsgCount);
} }
async FetchLongMsg(peer: Peer, msgId: string) { async FetchLongMsg(peer: Peer, msgId: string) {
return this.context.session.getMsgService().fetchLongMsg(peer, msgId); return this.context.session.getMsgService().fetchLongMsg(peer, msgId);
} }
@@ -29,19 +32,10 @@ export class NTQQMsgApi {
} }
async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) { async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) {
//console.log(peer, msgSeq, emojiId, emojiType, count);
//注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa //注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa
return this.context.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, '', false, count); return this.context.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, '', false, count);
} }
// napCatCore: NapCatCore | null = null;
// enum BaseEmojiType {
// NORMAL_EMOJI,
// SUPER_EMOJI,
// RANDOM_SUPER_EMOJI,
// CHAIN_SUPER_EMOJI,
// EMOJI_EMOJI
// }
async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) { async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) {
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览 // nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
// nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid // nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid
@@ -60,23 +54,10 @@ export class NTQQMsgApi {
return this.context.session.getMsgService().forwardMsg(msgIds, peer, [peer], new Map()); return this.context.session.getMsgService().forwardMsg(msgIds, peer, [peer], new Map());
} }
async getLastestMsgByUids(peer: Peer, count: number = 20, isReverseOrder: boolean = false) {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
chatInfo: peer,
filterMsgType: [],
filterSendersUid: [],
filterMsgToTime: '0',
filterMsgFromTime: '0',
isReverseOrder: isReverseOrder,//此参数有点离谱 注意不是本次查询的排序 而是全部消历史信息的排序 默认false 从新消息拉取到旧消息
isIncludeCurrent: true,
pageLimit: count,
});
}
async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) { async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) {
if (!peer) throw new Error('peer is not allowed'); if (!peer) throw new Error('peer is not allowed');
if (!msgIds) throw new Error('msgIds is not allowed'); if (!msgIds) throw new Error('msgIds is not allowed');
//Mlikiowa 参数不合规会导致NC异常崩溃 原因是TX未对进入参数判断 对应Android标记@NotNull AndroidJADX分析可得 //MliKiowa: 参数不合规会导致NC异常崩溃 原因是TX未对进入参数判断 对应Android标记@NotNull AndroidJADX分析可得
return await this.context.session.getMsgService().getMsgsByMsgId(peer, msgIds); return await this.context.session.getMsgService().getMsgsByMsgId(peer, msgIds);
} }
@@ -90,7 +71,7 @@ export class NTQQMsgApi {
async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) { async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, { return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa chatInfo: peer,
filterMsgType: [], filterMsgType: [],
filterSendersUid: [], filterSendersUid: [],
filterMsgToTime: '0', filterMsgToTime: '0',
@@ -100,11 +81,41 @@ export class NTQQMsgApi {
pageLimit: 1, pageLimit: 1,
}); });
} }
async queryMsgsWithFilterExWithSeqV2(peer: Peer, msgSeq: string, MsgTime: string, SendersUid: string[]) {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
chatInfo: peer,
filterMsgType: [],
filterSendersUid: SendersUid,
filterMsgToTime: MsgTime,
filterMsgFromTime: MsgTime,
isReverseOrder: false,
isIncludeCurrent: true,
pageLimit: 1,
});
}
async queryFirstMsgBySeq(peer: Peer, msgSeq: string) {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
chatInfo: peer,
filterMsgType: [],
filterSendersUid: [],
filterMsgToTime: '0',
filterMsgFromTime: '0',
isReverseOrder: true,
isIncludeCurrent: true,
pageLimit: 1,
});
}
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) { async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z); return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
} }
async getMsgBySeqList(peer: Peer, msgSeqList: string[]) {
//坏的
return await this.context.session.getMsgService().getMsgsBySeqList(peer, msgSeqList);
}
async getMsgBySeqExFirstMsg(peer: Peer, rootMsgId: string, replyMsgId: string) {
let reply = await this.context.session.getMsgService().getSourceOfReplyMsgV2(peer, rootMsgId, replyMsgId);
console.log(reply);
}
async getMsgExBySeq(peer: Peer, msgSeq: string) { async getMsgExBySeq(peer: Peer, msgSeq: string) {
const DateNow = Math.floor(Date.now() / 1000); const DateNow = Math.floor(Date.now() / 1000);
const filterMsgFromTime = (DateNow - 300).toString(); const filterMsgFromTime = (DateNow - 300).toString();
@@ -134,10 +145,7 @@ export class NTQQMsgApi {
params, params,
], ],
() => true, () => true,
( /* groupFileListResult: GroupFileInfoUpdateParamType */) => { () => true, // Todo: 应当通过 groupFileListResult 判断
//Developer Mlikiowa Todo: 此处有问题 无法判断是否成功
return true;
},
1, 1,
5000, 5000,
); );
@@ -157,14 +165,6 @@ export class NTQQMsgApi {
} }
async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) { async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) {
//By Jadx/Ida Mlikiowa
const TempGameSession = {
nickname: '',
gameAppId: '',
selfTinyId: '',
peerRoleId: '',
peerOpenId: '',
};
return this.context.session.getMsgService().prepareTempChat({ return this.context.session.getMsgService().prepareTempChat({
chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP, chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP,
peerUid: toUserUid, peerUid: toUserUid,
@@ -173,7 +173,13 @@ export class NTQQMsgApi {
sig: '', sig: '',
selfPhone: '', selfPhone: '',
selfUid: this.core.selfInfo.uid, selfUid: this.core.selfInfo.uid,
gameSession: TempGameSession, gameSession: {
nickname: '',
gameAppId: '',
selfTinyId: '',
peerRoleId: '',
peerOpenId: '',
},
}); });
} }
@@ -182,7 +188,7 @@ export class NTQQMsgApi {
} }
async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) { async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
//唉? !我有个想法 //唉?!我有个想法
if (peer.chatType === ChatType.KCHATTYPETEMPC2CFROMGROUP && peer.guildId && peer.guildId !== '') { if (peer.chatType === ChatType.KCHATTYPETEMPC2CFROMGROUP && peer.guildId && peer.guildId !== '') {
const member = await this.core.apis.GroupApi.getGroupMember(peer.guildId, peer.peerUid!); const member = await this.core.apis.GroupApi.getGroupMember(peer.guildId, peer.peerUid!);
if (member) { if (member) {
@@ -212,11 +218,7 @@ export class NTQQMsgApi {
1, 1,
timeout, timeout,
); );
return msgList.find(msgRecord => { return msgList.find(msgRecord => msgRecord.guildId === msgId);
if (msgRecord.guildId === msgId) {
return true;
}
});
} }
async generateMsgUniqueId(chatType: number, time: string) { async generateMsgUniqueId(chatType: number, time: string) {
@@ -246,14 +248,10 @@ export class NTQQMsgApi {
new Map(), new Map(),
], ],
() => true, () => true,
(msgRecords) => { (msgRecords) => msgRecords.some(
for (const msgRecord of msgRecords) { msgRecord => msgRecord.peerUid === destPeer.peerUid
if (msgRecord.peerUid == destPeer.peerUid && msgRecord.senderUid == this.core.selfInfo.uid) { && msgRecord.senderUid === this.core.selfInfo.uid
return true; ),
}
}
return false;
},
); );
for (const msg of msgList) { for (const msg of msgList) {
const arkElement = msg.elements.find(ele => ele.arkElement); const arkElement = msg.elements.find(ele => ele.arkElement);
@@ -271,7 +269,7 @@ export class NTQQMsgApi {
throw new Error('转发消息超时'); throw new Error('转发消息超时');
} }
async markallMsgAsRead() { async markAllMsgAsRead() {
return this.context.session.getMsgService().setAllC2CAndGroupMsgRead(); return this.context.session.getMsgService().setAllC2CAndGroupMsgRead();
} }
} }

View File

@@ -13,7 +13,7 @@ export class NTQQSystemApi {
return this.core.util.hasOtherRunningQQProcess(); return this.core.util.hasOtherRunningQQProcess();
} }
async ORCImage(filePath: string) { async ocrImage(filePath: string) {
return this.context.session.getNodeMiscService().wantWinScreenOCR(filePath); return this.context.session.getNodeMiscService().wantWinScreenOCR(filePath);
} }
@@ -21,20 +21,16 @@ export class NTQQSystemApi {
return this.context.session.getRichMediaService().translateEnWordToZn(words); return this.context.session.getRichMediaService().translateEnWordToZn(words);
} }
//调用会超时 没灯用 (好像是通知listener的) onLineDev
async getOnlineDev() { async getOnlineDev() {
return this.context.session.getMsgService().getOnLineDev(); return this.context.session.getMsgService().getOnLineDev();
} }
//1-2-162b9b42-65b9-4405-a8ed-2e256ec8aa50
async getArkJsonCollection(cid: string) { async getArkJsonCollection(cid: string) {
return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelCollectionService/collectionArkShare', '1717662698058'); return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelCollectionService/collectionArkShare', '1717662698058');
} }
async BootMiniApp(appfile: string, params: string) { async bootMiniApp(appFile: string, params: string) {
await this.context.session.getNodeMiscService().setMiniAppVersion('2.16.4'); await this.context.session.getNodeMiscService().setMiniAppVersion('2.16.4');
// const c = await this.context.session.getNodeMiscService().getMiniAppPath(); return this.context.session.getNodeMiscService().startNewMiniApp(appFile, params);
return this.context.session.getNodeMiscService().startNewMiniApp(appfile, params);
} }
} }

View File

@@ -15,9 +15,7 @@ export class NTQQUserApi {
async getProfileLike(uid: string) { async getProfileLike(uid: string) {
return this.context.session.getProfileLikeService().getBuddyProfileLike({ return this.context.session.getProfileLikeService().getBuddyProfileLike({
friendUids: [ friendUids: [uid],
uid,
],
basic: 1, basic: 1,
vote: 1, vote: 1,
favorite: 0, favorite: 0,
@@ -63,41 +61,6 @@ export class NTQQUserApi {
return this.context.session.getGroupService().setHeader(gc, filePath); return this.context.session.getGroupService().setHeader(gc, filePath);
} }
async fetchUserDetailInfos(uids: string[]) {
// TODO: 26702 以上使用新接口 .Dev MliKiowa
const retData: User[] = [];
const [_retData, _retListener] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelProfileService/fetchUserDetailInfo',
'NodeIKernelProfileListener/onUserDetailInfoChanged',
[
'BuddyProfileStore',
uids,
UserDetailSource.KSERVER,
[ProfileBizType.KALL],
],
() => true,
(profile) => {
if (uids.includes(profile.uid)) {
const RetUser: User = {
...profile.simpleInfo.coreInfo,
...profile.simpleInfo.status,
...profile.simpleInfo.vasInfo,
...profile.commonExt,
...profile.simpleInfo.baseInfo,
qqLevel: profile.commonExt.qqLevel,
pendantId: '',
};
retData.push(RetUser);
return true;
}
return false;
},
uids.length,
);
return retData;
}
async fetchUserDetailInfo(uid: string, mode: UserDetailSource = UserDetailSource.KDB) { async fetchUserDetailInfo(uid: string, mode: UserDetailSource = UserDetailSource.KDB) {
const [_retData, profile] = await this.core.eventWrapper.callNormalEventV2( const [_retData, profile] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelProfileService/fetchUserDetailInfo', 'NodeIKernelProfileService/fetchUserDetailInfo',
@@ -156,7 +119,6 @@ export class NTQQUserApi {
version: 0, version: 0,
aioKeywordVersion: 0, aioKeywordVersion: 0,
}); });
// console.log(robotUinRanges?.response?.robotUinRanges);
return robotUinRanges?.response?.robotUinRanges; return robotUinRanges?.response?.robotUinRanges;
} }
@@ -170,7 +132,7 @@ export class NTQQUserApi {
//需要异常处理 //需要异常处理
async getSkey(): Promise<string | undefined> { async getSKey(): Promise<string | undefined> {
const ClientKeyData = await this.forceFetchClientKey(); const ClientKeyData = await this.forceFetchClientKey();
if (ClientKeyData.result !== 0) { if (ClientKeyData.result !== 0) {
throw new Error('getClientKey Error'); throw new Error('getClientKey Error');
@@ -181,7 +143,7 @@ export class NTQQUserApi {
const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl); const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
const skey = cookies['skey']; const skey = cookies['skey'];
if (!skey) { if (!skey) {
throw new Error('getSkey Skey is Empty'); throw new Error('SKey is Empty');
} }
return skey; return skey;
} }
@@ -194,8 +156,8 @@ export class NTQQUserApi {
if (uid) return uid; if (uid) return uid;
uid = (await this.context.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin); uid = (await this.context.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin);
if (uid) return uid; if (uid) return uid;
const unveifyUid = (await this.getUserDetailInfoByUinV2(Uin)).detail.uid;//从QQ Native 特殊转换 const unverifiedUid = (await this.getUserDetailInfoByUinV2(Uin)).detail.uid;//从QQ Native 特殊转换
if (unveifyUid.indexOf('*') == -1) uid = unveifyUid; if (unverifiedUid.indexOf('*') == -1) uid = unverifiedUid;
//if (uid) return uid; //if (uid) return uid;
return uid; return uid;
} }
@@ -231,7 +193,10 @@ export class NTQQUserApi {
} }
async getUserDetailInfoByUinV2(Uin: string) { async getUserDetailInfoByUinV2(Uin: string) {
return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelProfileService/getUserDetailInfoByUin', Uin); return await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getUserDetailInfoByUin',
Uin
);
} }
async forceFetchClientKey() { async forceFetchClientKey() {

View File

@@ -26,8 +26,7 @@ export class NTQQWebApi {
msg_seq: msgSeq, msg_seq: msgSeq,
msg_random: msgRandom, msg_random: msgRandom,
target_group_code: targetGroupCode, target_group_code: targetGroupCode,
}).toString() }).toString()}`;
}`;
try { try {
return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
} catch (e) { } catch (e) {
@@ -35,16 +34,12 @@ export class NTQQWebApi {
} }
} }
async getGroupEssenceMsgAll(GroupCode: string) { async getGroupEssenceMsgAll(GroupCode: string) {
let ret: GroupEssenceMsgRet[] = []; const ret: GroupEssenceMsgRet[] = [];
for (let i = 0; i < 4; i++) { for (let i = 0; i < 20; i++) {
let data = await this.getGroupEssenceMsg(GroupCode, i, 50); const data = await this.getGroupEssenceMsg(GroupCode, i, 50);
if (!data) break; if (!data) break;
if (data.data.is_end) {
ret.push(data);
break;
}
ret.push(data); ret.push(data);
if (data.data.is_end) break;
} }
return ret; return ret;
} }
@@ -55,19 +50,18 @@ export class NTQQWebApi {
page_start: page_start.toString(), page_start: page_start.toString(),
page_limit: page_limit.toString(), page_limit: page_limit.toString(),
group_code: GroupCode, group_code: GroupCode,
}).toString() }).toString()}`;
}`;
let ret;
try { try {
ret = await RequestUtil.HttpGetJson<GroupEssenceMsgRet> const ret = await RequestUtil.HttpGetJson<GroupEssenceMsgRet>(
(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); url,
'GET',
'',
{ 'Cookie': this.cookieToString(cookieObject) }
);
return ret.retcode === 0 ? ret : undefined;
} catch { } catch {
return undefined; return undefined;
} }
if (ret.retcode !== 0) {
return undefined;
}
return ret;
} }
async getGroupMembers(GroupCode: string, cached: boolean = true): Promise<WebApiGroupMember[]> { async getGroupMembers(GroupCode: string, cached: boolean = true): Promise<WebApiGroupMember[]> {
@@ -75,15 +69,18 @@ export class NTQQWebApi {
const memberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>(); const memberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>();
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com'); const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
const retList: Promise<WebApiGroupMemberRet>[] = []; const retList: Promise<WebApiGroupMemberRet>[] = [];
const fastRet = await RequestUtil.HttpGetJson<WebApiGroupMemberRet> const fastRet = await RequestUtil.HttpGetJson<WebApiGroupMemberRet>(
(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({ `https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
st: '0', st: '0',
end: '40', end: '40',
sort: '1', sort: '1',
gc: GroupCode, gc: GroupCode,
bkn: this.getBknFromCookie(cookieObject), bkn: this.getBknFromCookie(cookieObject),
}).toString() }).toString()}`,
}`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) }); 'POST',
'',
{ 'Cookie': this.cookieToString(cookieObject) }
);
if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) { if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) {
return []; return [];
} else { } else {
@@ -95,15 +92,18 @@ export class NTQQWebApi {
const PageNum = Math.ceil(fastRet.count / 40); const PageNum = Math.ceil(fastRet.count / 40);
//遍历批量请求 //遍历批量请求
for (let i = 2; i <= PageNum; i++) { for (let i = 2; i <= PageNum; i++) {
const ret = RequestUtil.HttpGetJson<WebApiGroupMemberRet> const ret = RequestUtil.HttpGetJson<WebApiGroupMemberRet>(
(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({ `https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
st: ((i - 1) * 40).toString(), st: ((i - 1) * 40).toString(),
end: (i * 40).toString(), end: (i * 40).toString(),
sort: '1', sort: '1',
gc: GroupCode, gc: GroupCode,
bkn: this.getBknFromCookie(cookieObject), bkn: this.getBknFromCookie(cookieObject),
}).toString() }).toString()}`,
}`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) }); 'POST',
'',
{ 'Cookie': this.cookieToString(cookieObject) }
);
retList.push(ret); retList.push(ret);
} }
//批量等待 //批量等待
@@ -135,16 +135,19 @@ export class NTQQWebApi {
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com'); const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
let ret: any = undefined; let ret: any = undefined;
try { try {
ret = await RequestUtil.HttpGetJson<any> ret = await RequestUtil.HttpGetJson<any>(
(`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice${new URLSearchParams({ `https://web.qun.qq.com/cgi-bin/announce/add_qun_notice${new URLSearchParams({
bkn: this.getBknFromCookie(cookieObject), bkn: this.getBknFromCookie(cookieObject),
qid: GroupCode, qid: GroupCode,
text: Content, text: Content,
pinned: '0', pinned: '0',
type: '1', type: '1',
settings: '{"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}', settings: '{"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}',
}).toString() }).toString()}`,
}`, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); 'GET',
'',
{ 'Cookie': this.cookieToString(cookieObject) }
);
return ret; return ret;
} catch (e) { } catch (e) {
return undefined; return undefined;
@@ -153,16 +156,24 @@ export class NTQQWebApi {
async getGroupNotice(GroupCode: string): Promise<undefined | WebApiGroupNoticeRet> { async getGroupNotice(GroupCode: string): Promise<undefined | WebApiGroupNoticeRet> {
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com'); const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
let ret: WebApiGroupNoticeRet | undefined = undefined;
try { try {
const url = 'https://web.qun.qq.com/cgi-bin/announce/get_t_list?bkn=' + const ret = await RequestUtil.HttpGetJson<WebApiGroupNoticeRet>(
this.getBknFromCookie(cookieObject) + '&qid=' + GroupCode + '&ft=23&ni=1&n=1&i=1&log_read=1&platform=1&s=-1&n=20'; `https://web.qun.qq.com/cgi-bin/announce/get_t_list?${new URLSearchParams({
bkn: this.getBknFromCookie(cookieObject),
ret = await RequestUtil.HttpGetJson<WebApiGroupNoticeRet>(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); qid: GroupCode,
if (ret?.ec !== 0) { ft: '23',
return undefined; ni: '1',
} n: '1',
return ret; i: '1',
log_read: '1',
platform: '1',
s: '-1',
}).toString()}&n=20`,
'GET',
'',
{ 'Cookie': this.cookieToString(cookieObject) }
);
return ret?.ec === 0 ? ret : undefined;
} catch (e) { } catch (e) {
return undefined; return undefined;
} }
@@ -171,14 +182,17 @@ export class NTQQWebApi {
async getGroupHonorInfo(groupCode: string, getType: WebHonorType) { async getGroupHonorInfo(groupCode: string, getType: WebHonorType) {
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com'); const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
const getDataInternal = async (Internal_groupCode: string, Internal_type: number) => { const getDataInternal = async (Internal_groupCode: string, Internal_type: number) => {
const url = `https://qun.qq.com/interactive/honorlist?${new URLSearchParams({
gc: Internal_groupCode,
type: Internal_type.toString(),
}).toString()
}`;
let resJson; let resJson;
try { try {
const res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); const res = await RequestUtil.HttpGetText(
`https://qun.qq.com/interactive/honorlist?${new URLSearchParams({
gc: Internal_groupCode,
type: Internal_type.toString(),
}).toString()}`,
'GET',
'',
{ 'Cookie': this.cookieToString(cookieObject) }
);
const match = /window\.__INITIAL_STATE__=(.*?);/.exec(res); const match = /window\.__INITIAL_STATE__=(.*?);/.exec(res);
if (match) { if (match) {
resJson = JSON.parse(match[1].trim()); resJson = JSON.parse(match[1].trim());
@@ -189,7 +203,7 @@ export class NTQQWebApi {
return resJson?.actorList; return resJson?.actorList;
} }
} catch (e) { } catch (e) {
this.context.logger.logDebug('获取当前群荣耀失败', url, e); this.context.logger.logDebug('获取当前群荣耀失败', e);
} }
return undefined; return undefined;
}; };
@@ -268,10 +282,12 @@ export class NTQQWebApi {
this.context.logger.logError('获取快乐源泉失败'); this.context.logger.logError('获取快乐源泉失败');
} }
} }
// 冒尖小春笋好像已经被tx扬了 R.I.P. // 冒尖小春笋好像已经被tx扬了 R.I.P.
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) { if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
HonorInfo.strong_newbie_list = []; HonorInfo.strong_newbie_list = [];
} }
return HonorInfo; return HonorInfo;
} }

View File

@@ -370,7 +370,8 @@ export interface ReplyElement {
replayMsgSeq: string; replayMsgSeq: string;
replayMsgId: string; replayMsgId: string;
senderUin: string; senderUin: string;
senderUinStr: string; senderUidStr?: string;
replyMsgTime?: string;
} }
export interface SendReplyElement { export interface SendReplyElement {

View File

@@ -1,34 +1,10 @@
{ {
"3.2.12-27187": { "3.2.12-27597": {
"appid": 537240645, "appid": 537243600,
"qua": "V1_LNX_NQ_3.2.12_27187_GW_B" "qua": "V1_LNX_NQ_3.2.12_27597_GW_B"
}, },
"3.2.12-27206": { "9.9.15-27597": {
"appid": 537240645, "appid": 537243441,
"qua": "V1_LNX_NQ_3.2.12_27206_GW_B" "qua": "V1_WIN_NQ_9.9.15_27597_GW_B"
},
"3.2.12-27254": {
"appid": 537240795,
"qua": "V1_LNX_NQ_3.2.12_27254_GW_B"
},
"9.9.15-27187": {
"appid": 537240610,
"qua": "V1_WIN_NQ_9.9.15_27187_GW_B"
},
"9.9.15-27206": {
"appid": 537240610,
"qua": "V1_WIN_NQ_9.9.15_27206_GW_B"
},
"9.9.15-27254": {
"appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27254_GW_B"
},
"9.9.15-27333": {
"appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27333_GW_B"
},
"9.9.15-27391": {
"appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27333_GW_B"
} }
} }

View File

@@ -1,4 +0,0 @@
# nekodoge
此协议为替代QQ平台 OnebotV11长期不可靠问题
# 规划路线

View File

View File

@@ -1,19 +0,0 @@
import { createServer } from 'node:net';
export class NewAdapterNetwork {
constructor(public host: number, public port: number) { }
async open() {
const server = createServer((socket) => {
socket.on('data', (data) => {
});
socket.on('end', () => {
});
socket.on('connect', () => {
});
});
server.listen(this.port, this.host);
}
}

View File

@@ -24,10 +24,9 @@ export class FetchEmojiLike extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQMsgApi = this.core.apis.MsgApi;
const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
if (!msgIdPeer) throw new Error('消息不存在'); if (!msgIdPeer) throw new Error('消息不存在');
const msg = (await NTQQMsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0]; const msg = (await this.core.apis.MsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0];
return await NTQQMsgApi.getMsgEmojiLikesList(msgIdPeer.Peer, msg.msgSeq, payload.emojiId, payload.emojiType, +(payload.count ?? 20)); return await this.core.apis.MsgApi.getMsgEmojiLikesList(msgIdPeer.Peer, msg.msgSeq, payload.emojiId, payload.emojiType, +(payload.count ?? 20));
} }
} }

View File

@@ -18,7 +18,6 @@ export class GetCollectionList extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQCollectionApi = this.core.apis.CollectionApi; return await this.core.apis.CollectionApi.getAllCollection(parseInt(payload.category.toString()), +(payload.count ?? 1));
return await NTQQCollectionApi.getAllCollection(parseInt(payload.category.toString()), +(payload.count ?? 1));
} }
} }

View File

@@ -17,8 +17,6 @@ export class GetGroupInfoEx extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi; return (await this.core.apis.GroupApi.getGroupExtFE0Info([payload.group_id.toString()])).result.groupExtInfos.get(payload.group_id.toString());
const groupInfoEx = (await NTQQGroupApi.getGroupExtFE0Info([payload.group_id.toString()])).result.groupExtInfos.get(payload.group_id.toString());
return groupInfoEx;
} }
} }

View File

@@ -5,11 +5,10 @@ export class GetProfileLike extends BaseAction<void, any> {
actionName = ActionName.GetProfileLike; actionName = ActionName.GetProfileLike;
async _handle(payload: void) { async _handle(payload: void) {
const NTQQUserApi = this.core.apis.UserApi; const ret = await this.core.apis.UserApi.getProfileLike(this.core.selfInfo.uid);
const ret = await NTQQUserApi.getProfileLike(this.core.selfInfo.uid);
const listdata: any[] = ret.info.userLikeInfos[0].favoriteInfo.userInfos; const listdata: any[] = ret.info.userLikeInfos[0].favoriteInfo.userInfos;
for (let i = 0; i < listdata.length; i++) { for (let i = 0; i < listdata.length; i++) {
listdata[i].uin = parseInt((await NTQQUserApi.getUinByUidV2(listdata[i].uid)) || ''); listdata[i].uin = parseInt((await this.core.apis.UserApi.getUinByUidV2(listdata[i].uid)) || '');
} }
return listdata; return listdata;
} }

View File

@@ -5,7 +5,6 @@ export class GetRobotUinRange extends BaseAction<void, Array<any>> {
actionName = ActionName.GetRobotUinRange; actionName = ActionName.GetRobotUinRange;
async _handle(payload: void) { async _handle(payload: void) {
const NTQQUserApi = this.core.apis.UserApi; return await this.core.apis.UserApi.getRobotUinRange();
return await NTQQUserApi.getRobotUinRange();
} }
} }

View File

@@ -19,14 +19,13 @@ export class OCRImage extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQSystemApi = this.core.apis.SystemApi;
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.image)); const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.image));
if (!success) { if (!success) {
throw `OCR ${payload.image}失败,image字段可能格式不正确`; throw `OCR ${payload.image}失败,image字段可能格式不正确`;
} }
if (path) { if (path) {
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断 await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断
const ret = await NTQQSystemApi.ORCImage(path); const ret = await this.core.apis.SystemApi.ocrImage(path);
if (!isLocal) { if (!isLocal) {
fs.unlink(path, () => { fs.unlink(path, () => {
}); });

View File

@@ -19,8 +19,6 @@ export class SetInputStatus extends BaseAction<Payload, any> {
actionName = ActionName.SetInputStatus; actionName = ActionName.SetInputStatus;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQUserApi = this.core.apis.UserApi;
const NTQQMsgApi = this.core.apis.MsgApi;
let peer: Peer; let peer: Peer;
if (payload.group_id) { if (payload.group_id) {
peer = { peer = {
@@ -28,7 +26,7 @@ export class SetInputStatus extends BaseAction<Payload, any> {
peerUid: payload.group_id, peerUid: payload.group_id,
}; };
} else if (payload.user_id) { } else if (payload.user_id) {
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id); const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id);
if (!uid) throw new Error('uid is empty'); if (!uid) throw new Error('uid is empty');
peer = { peer = {
chatType: ChatType.KCHATTYPEC2C, chatType: ChatType.KCHATTYPEC2C,
@@ -38,6 +36,6 @@ export class SetInputStatus extends BaseAction<Payload, any> {
throw new Error('请指定 group_id 或 user_id'); throw new Error('请指定 group_id 或 user_id');
} }
return await NTQQMsgApi.sendShowInputStatusReq(peer, parseInt(payload.eventType)); return await this.core.apis.MsgApi.sendShowInputStatusReq(peer, parseInt(payload.eventType));
} }
} }

View File

@@ -17,8 +17,6 @@ export class SetLongNick extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQUserApi = this.core.apis.UserApi; return await this.core.apis.UserApi.setLongNick(payload.longNick);
const ret = await NTQQUserApi.setLongNick(payload.longNick);
return ret;
} }
} }

View File

@@ -20,8 +20,7 @@ export class SetOnlineStatus extends BaseAction<Payload, null> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQUserApi = this.core.apis.UserApi; const ret = await this.core.apis.UserApi.setSelfOnlineStatus(
const ret = await NTQQUserApi.setSelfOnlineStatus(
parseInt(payload.status.toString()), parseInt(payload.status.toString()),
parseInt(payload.ext_status.toString()), parseInt(payload.ext_status.toString()),
parseInt(payload.battery_status.toString()), parseInt(payload.battery_status.toString()),

View File

@@ -24,14 +24,13 @@ export default class SetAvatar extends BaseAction<Payload, null> {
} }
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQUserApi = this.core.apis.UserApi; const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
const { path, isLocal, errMsg, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
if (!success) { if (!success) {
throw `头像${payload.file}设置失败,file字段可能格式不正确`; throw `头像${payload.file}设置失败,file字段可能格式不正确`;
} }
if (path) { if (path) {
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断 await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断
const ret = await NTQQUserApi.setQQAvatar(path); const ret = await this.core.apis.UserApi.setQQAvatar(path);
if (!isLocal) { if (!isLocal) {
fs.unlink(path, () => { fs.unlink(path, () => {
}); });

View File

@@ -19,12 +19,10 @@ export class SharePeer extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQUserApi = this.core.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi;
if (payload.group_id) { if (payload.group_id) {
return await NTQQGroupApi.getGroupRecommendContactArkJson(payload.group_id); return await this.core.apis.GroupApi.getGroupRecommendContactArkJson(payload.group_id);
} else if (payload.user_id) { } else if (payload.user_id) {
return await NTQQUserApi.getBuddyRecommendContactArkJson(payload.user_id, payload.phoneNumber || ''); return await this.core.apis.UserApi.getBuddyRecommendContactArkJson(payload.user_id, payload.phoneNumber || '');
} }
} }
} }
@@ -44,7 +42,6 @@ export class ShareGroupEx extends BaseAction<PayloadGroupEx, any> {
payloadSchema = SchemaDataGroupEx; payloadSchema = SchemaDataGroupEx;
async _handle(payload: PayloadGroupEx) { async _handle(payload: PayloadGroupEx) {
const NTQQGroupApi = this.core.apis.GroupApi; return await this.core.apis.GroupApi.getArkJsonGroupShare(payload.group_id);
return await NTQQGroupApi.getArkJsonGroupShare(payload.group_id);
} }
} }

View File

@@ -20,8 +20,7 @@ export class TranslateEnWordToZn extends BaseAction<Payload, Array<any> | null>
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQSystemApi = this.core.apis.SystemApi; const ret = await this.core.apis.SystemApi.translateEnWordToZn(payload.words);
const ret = await NTQQSystemApi.translateEnWordToZn(payload.words);
if (ret.result !== 0) { if (ret.result !== 0) {
throw new Error('翻译失败'); throw new Error('翻译失败');
} }

View File

@@ -1,24 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
file_id: { type: 'string' },
},
required: ['group_id', 'file_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class DelGroupFile extends BaseAction<Payload, any> {
actionName = ActionName.DelGroupFile;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi;
return await NTQQGroupApi.DelGroupFile(payload.group_id.toString(), [payload.file_id]);
}
}

View File

@@ -1,24 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
folder_id: { type: 'string' },
},
required: ['group_id', 'folder_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class DelGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.DelGroupFileFolder;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi;
return (await NTQQGroupApi.DelGroupFileFolder(payload.group_id.toString(), payload.folder_id)).groupFileCommonResult;
}
}

View File

@@ -3,6 +3,7 @@ import fs from 'fs/promises';
import { FileNapCatOneBotUUID } from '@/common/helper'; import { FileNapCatOneBotUUID } from '@/common/helper';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types';
export interface GetFilePayload { export interface GetFilePayload {
file: string; // 文件名或者fileUuid file: string; // 文件名或者fileUuid
@@ -28,24 +29,32 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
payloadSchema: any = GetFileBase_PayloadSchema; payloadSchema: any = GetFileBase_PayloadSchema;
async _handle(payload: GetFilePayload): Promise<GetFileResponse> { async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
const NTQQMsgApi = this.core.apis.MsgApi;
const NTQQFileApi = this.core.apis.FileApi;
//接收消息标记模式 //接收消息标记模式
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file); const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file);
if (contextMsgFile) { if (contextMsgFile) {
const { peer, msgId, elementId } = contextMsgFile; const { peer, msgId, elementId } = contextMsgFile;
const downloadPath = await NTQQFileApi.downloadMedia(msgId, peer.chatType, peer.peerUid, elementId, '', ''); const downloadPath = await this.core.apis.FileApi.downloadMedia(msgId, peer.chatType, peer.peerUid, elementId, '', '');
const mixElement = (await NTQQMsgApi.getMsgsByMsgId(peer, [msgId]))?.msgList const rawMessage = (await this.core.apis.MsgApi.getMsgsByMsgId(peer, [msgId]))?.msgList
.find(msg => msg.msgId === msgId)?.elements.find(e => e.elementId === elementId); .find(msg => msg.msgId === msgId);
const mixElement = rawMessage?.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;
if (!mixElementInner) throw new Error('element not found'); if (!mixElementInner) throw new Error('element not found');
const fileSize = mixElementInner.fileSize?.toString() ?? ''; const fileSize = mixElementInner.fileSize?.toString() ?? '';
const fileName = mixElementInner.fileName ?? ''; const fileName = mixElementInner.fileName ?? '';
let url = '';
if (mixElement?.picElement && rawMessage) {
let tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.picElement?.(mixElement?.picElement, rawMessage, mixElement) as OB11MessageImage | undefined;
url = tempData?.data.url ?? '';
}
if (mixElement?.videoElement && rawMessage) {
let tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.videoElement?.(mixElement?.videoElement, rawMessage, mixElement) as OB11MessageVideo | undefined;
url = tempData?.data.url ?? '';
}
const res: GetFileResponse = { const res: GetFileResponse = {
file: downloadPath, file: downloadPath,
url: downloadPath, url: url !== '' ? url : downloadPath,
file_size: fileSize, file_size: fileSize,
file_name: fileName, file_name: fileName,
}; };
@@ -64,7 +73,7 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
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 this.core.apis.FileApi.downloadFileForModelId(peer, modelId, '');
const res: GetFileResponse = { const res: GetFileResponse = {
file: downloadPath, file: downloadPath,
url: downloadPath, url: downloadPath,
@@ -83,9 +92,9 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
} }
//搜索名字模式 //搜索名字模式
const searchResult = (await NTQQFileApi.searchForFile([payload.file])); const searchResult = (await this.core.apis.FileApi.searchForFile([payload.file]));
if (searchResult) { if (searchResult) {
const downloadPath = await NTQQFileApi.downloadFileById(searchResult.id, parseInt(searchResult.fileSize)); const downloadPath = await this.core.apis.FileApi.downloadFileById(searchResult.id, parseInt(searchResult.fileSize));
const res: GetFileResponse = { const res: GetFileResponse = {
file: downloadPath, file: downloadPath,
url: downloadPath, url: downloadPath,

View File

@@ -1,23 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFileCount extends BaseAction<Payload, { count: number }> {
actionName = ActionName.GetGroupFileCount;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const ret = await this.core.apis.GroupApi.getGroupFileCount([payload.group_id?.toString()]);
return { count: ret.groupFileCounts[0] };
}
}

View File

@@ -1,51 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FileNapCatOneBotUUID } from '@/common/helper';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
start_index: { type: ['string', 'number'] },
file_count: { type: ['string', 'number'] },
folder_id: { type: ['string', 'number'] },
},
required: ['group_id', 'start_index', 'file_count'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFileList extends BaseAction<Payload, { FileList: Array<any> }> {
actionName = ActionName.GetGroupFileList;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQMsgApi = this.core.apis.MsgApi;
let param = {};
if (payload.folder_id) {
param = {
folderId: payload.folder_id.toString(),
};
}
const ret = await NTQQMsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1,
fileCount: +payload.file_count,
startIndex: +payload.start_index,
sortOrder: 2,
showOnlinedocFolder: 0,
...param
}).catch(() => {
return [];
});
ret.forEach((e) => {
const fileModelId = e?.fileInfo?.fileModelId;
if (fileModelId)
e.fileInfo!.fileId = FileNapCatOneBotUUID.encodeModelId({
chatType: 2,
peerUid: payload.group_id.toString()
}, fileModelId);
});
return { FileList: ret };
}
}

View File

@@ -1,24 +0,0 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
folder_name: { type: 'string' },
},
required: ['group_id', 'folder_name'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class SetGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.SetGroupFileFolder;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi;
return (await NTQQGroupApi.CreatGroupFileFolder(payload.group_id.toString(), payload.folder_name)).resultWithGroupItem;
}
}

View File

@@ -1,10 +1,6 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatOneBot11Adapter } from '@/onebot';
import { NapCatCore } from '@/core';
import { SetGroupFileFolder } from '@/onebot/action/file/SetGroupFileFolder';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
properties: { properties: {
@@ -16,17 +12,10 @@ const SchemaData = {
type Payload = FromSchema<typeof SchemaData>; type Payload = FromSchema<typeof SchemaData>;
export class CreateGroupFileFolder extends BaseAction<Payload, null> { export class CreateGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_CreateGroupFileFolder; actionName = ActionName.GoCQHTTP_CreateGroupFileFolder;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncSetGroupFileFolderImpl: SetGroupFileFolder) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
await this.ncSetGroupFileFolderImpl._handle(payload); return (await this.core.apis.GroupApi.CreatGroupFileFolder(payload.group_id.toString(), payload.folder_name)).resultWithGroupItem;
return null;
} }
} }

View File

@@ -1,10 +1,7 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatCore } from '@/core'; import { FileNapCatOneBotUUID } from '@/common/helper';
import { NapCatOneBot11Adapter } from '@/onebot';
import { DelGroupFile } from '@/onebot/action/file/DelGroupFile';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
properties: { properties: {
@@ -16,17 +13,12 @@ const SchemaData = {
type Payload = FromSchema<typeof SchemaData>; type Payload = FromSchema<typeof SchemaData>;
export class DeleteGroupFile extends BaseAction<Payload, null> { export class DeleteGroupFile extends BaseAction<Payload, any> {
actionName = ActionName.GOCQHTTP_DeleteGroupFile; actionName = ActionName.GOCQHTTP_DeleteGroupFile;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncDelGroupFileImpl: DelGroupFile) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
await this.ncDelGroupFileImpl._handle(payload); const data = FileNapCatOneBotUUID.decodeModelId(payload.file_id);
return null; if (!data) throw new Error('Invalid file_id');
return await this.core.apis.GroupApi.DelGroupFile(payload.group_id.toString(), [data.fileId]);
} }
} }

View File

@@ -1,9 +1,6 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatCore } from '@/core'; import BaseAction from '../BaseAction';
import { NapCatOneBot11Adapter } from '@/onebot';
import { DelGroupFileFolder } from '@/onebot/action/file/DelGroupFileFolder';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@@ -16,17 +13,11 @@ const SchemaData = {
type Payload = FromSchema<typeof SchemaData>; type Payload = FromSchema<typeof SchemaData>;
export class DeleteGroupFileFolder extends BaseAction<Payload, null> { export class DeleteGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder; actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncDelGroupFileFolderImpl: DelGroupFileFolder) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
await this.ncDelGroupFileFolderImpl._handle(payload); return (await this.core.apis.GroupApi.DelGroupFileFolder(
return null; payload.group_id.toString(), payload.folder_id)).groupFileCommonResult;
} }
} }

View File

@@ -19,7 +19,6 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> { async _handle(payload: Payload): Promise<any> {
const NTQQMsgApi = this.core.apis.MsgApi;
const msgId = payload.message_id || payload.id; const msgId = payload.message_id || payload.id;
if (!msgId) { if (!msgId) {
throw Error('message_id is required'); throw Error('message_id is required');
@@ -29,7 +28,7 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
if (!rootMsg) { if (!rootMsg) {
throw Error('msg not found'); throw Error('msg not found');
} }
const data = await NTQQMsgApi.getMultiMsg(rootMsg.Peer, rootMsg.MsgId, rootMsg.MsgId); const data = await this.core.apis.MsgApi.getMultiMsg(rootMsg.Peer, rootMsg.MsgId, rootMsg.MsgId);
if (!data || data.result !== 0) { if (!data || data.result !== 0) {
throw Error('找不到相关的聊天记录' + data?.errMsg); throw Error('找不到相关的聊天记录' + data?.errMsg);
} }

View File

@@ -27,21 +27,17 @@ export default class GetFriendMsgHistory extends BaseAction<Payload, Response> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<Response> { async _handle(payload: Payload): Promise<Response> {
const NTQQUserApi = this.core.apis.UserApi;
const NTQQMsgApi = this.core.apis.MsgApi;
const NTQQFriendApi = this.core.apis.FriendApi;
//处理参数 //处理参数
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
const MsgCount = +(payload.count ?? 20); const MsgCount = +(payload.count ?? 20);
const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder; const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder;
if (!uid) throw `记录${payload.user_id}不存在`; if (!uid) throw `记录${payload.user_id}不存在`;
const friend = await NTQQFriendApi.isBuddy(uid); const friend = await this.core.apis.FriendApi.isBuddy(uid);
const peer = { chatType: friend ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid: uid }; const peer = { chatType: friend ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid: uid };
const hasMessageSeq = !payload.message_seq ? !!payload.message_seq : !(payload.message_seq?.toString() === '' || payload.message_seq?.toString() === '0'); const hasMessageSeq = !payload.message_seq ? !!payload.message_seq : !(payload.message_seq?.toString() === '' || payload.message_seq?.toString() === '0');
//拉取消息
const startMsgId = hasMessageSeq ? (MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq!)?.MsgId ?? payload.message_seq!.toString()) : '0'; const startMsgId = hasMessageSeq ? (MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq!)?.MsgId ?? payload.message_seq!.toString()) : '0';
const msgList = hasMessageSeq ? const msgList = hasMessageSeq ?
(await NTQQMsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList : (await NTQQMsgApi.getAioFirstViewLatestMsgs(peer, MsgCount)).msgList; (await this.core.apis.MsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList : (await this.core.apis.MsgApi.getAioFirstViewLatestMsgs(peer, MsgCount)).msgList;
if (msgList.length === 0) throw `消息${payload.message_seq}不存在`; if (msgList.length === 0) throw `消息${payload.message_seq}不存在`;
//翻转消息 //翻转消息
if (isReverseOrder) msgList.reverse(); if (isReverseOrder) msgList.reverse();

View File

@@ -1,43 +1,27 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatOneBot11Adapter, OB11GroupFile } from '@/onebot';
import { NapCatCore } from '@/core';
import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
import { OB11Entities } from '@/onebot/entities'; import { OB11Entities } from '@/onebot/entities';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
properties: { properties: {
group_id: { type: ['string', 'number'] }, group_id: { type: ['string', 'number'] },
folder_id: { type: 'string' }, folder_id: { type: 'string' },
file_count: { type: ['string', 'number'] },
}, },
required: ['group_id', 'folder_id'], required: ['group_id', 'folder_id'],
} as const satisfies JSONSchema; } as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFilesByFolder extends BaseAction<Payload, { export class GetGroupFilesByFolder extends BaseAction<any, any> {
files: OB11GroupFile[],
folders: [] // QQ does not allow nested folders
}> {
actionName = ActionName.GoCQHTTP_GetGroupFilesByFolder; actionName = ActionName.GoCQHTTP_GetGroupFilesByFolder;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private getGroupRootFilesImpl: GetGroupRootFiles) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
const folder = (await this.getGroupRootFilesImpl._handle({ group_id: payload.group_id }))
.folders.find(folder => folder.folder_id === payload.folder_id);
if (!folder) {
throw new Error('Folder not found');
}
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), { const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1, sortType: 1,
fileCount: folder.total_file_count, fileCount: +(payload.file_count ?? 50),
startIndex: 0, startIndex: 0,
sortOrder: 2, sortOrder: 2,
showOnlinedocFolder: 0, showOnlinedocFolder: 0,

View File

@@ -22,7 +22,6 @@ export class GetGroupHonorInfo extends BaseAction<Payload, Array<any>> {
if (!payload.type) { if (!payload.type) {
payload.type = WebHonorType.ALL; payload.type = WebHonorType.ALL;
} }
const NTQQWebApi = this.core.apis.WebApi; return await this.core.apis.WebApi.getGroupHonorInfo(payload.group_id.toString(), payload.type);
return await NTQQWebApi.getGroupHonorInfo(payload.group_id.toString(), payload.type);
} }
} }

View File

@@ -27,7 +27,6 @@ export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Resp
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<Response> { async _handle(payload: Payload): Promise<Response> {
const NTQQMsgApi = this.core.apis.MsgApi;
//处理参数 //处理参数
const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder; const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder;
const MsgCount = +(payload.count ?? 20); const MsgCount = +(payload.count ?? 20);
@@ -36,7 +35,7 @@ export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Resp
//拉取消息 //拉取消息
const startMsgId = hasMessageSeq ? (MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq!)?.MsgId ?? payload.message_seq!.toString()) : '0'; const startMsgId = hasMessageSeq ? (MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq!)?.MsgId ?? payload.message_seq!.toString()) : '0';
const msgList = hasMessageSeq ? const msgList = hasMessageSeq ?
(await NTQQMsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList : (await NTQQMsgApi.getAioFirstViewLatestMsgs(peer, MsgCount)).msgList; (await this.core.apis.MsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList : (await this.core.apis.MsgApi.getAioFirstViewLatestMsgs(peer, MsgCount)).msgList;
if (msgList.length === 0) throw `消息${payload.message_seq}不存在`; if (msgList.length === 0) throw `消息${payload.message_seq}不存在`;
//翻转消息 //翻转消息
if (isReverseOrder) msgList.reverse(); if (isReverseOrder) msgList.reverse();

View File

@@ -1,15 +1,14 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { NapCatOneBot11Adapter, OB11GroupFile, OB11GroupFileFolder } from '@/onebot'; import { OB11GroupFile, OB11GroupFileFolder } from '@/onebot';
import { NapCatCore } from '@/core';
import { GetGroupFileCount } from '@/onebot/action/file/GetGroupFileCount';
import { OB11Entities } from '@/onebot/entities'; import { OB11Entities } from '@/onebot/entities';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
properties: { properties: {
group_id: { type: ['string', 'number'] }, group_id: { type: ['string', 'number'] },
file_count: { type: ['string', 'number'] },
}, },
required: ['group_id'], required: ['group_id'],
} as const satisfies JSONSchema; } as const satisfies JSONSchema;
@@ -22,16 +21,10 @@ export class GetGroupRootFiles extends BaseAction<Payload, {
}> { }> {
actionName = ActionName.GoCQHTTP_GetGroupRootFiles; actionName = ActionName.GoCQHTTP_GetGroupRootFiles;
payloadSchema = SchemaData; payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncGetGroupFileCountImpl: GetGroupFileCount) {
super(obContext, core);
}
async _handle(payload: Payload) { async _handle(payload: Payload) {
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), { const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1, sortType: 1,
fileCount: (await this.ncGetGroupFileCountImpl._handle({ group_id: payload.group_id.toString() })).count, fileCount: +(payload.file_count ?? 50),
startIndex: 0, startIndex: 0,
sortOrder: 2, sortOrder: 2,
showOnlinedocFolder: 0, showOnlinedocFolder: 0,

View File

@@ -15,8 +15,7 @@ export class GetOnlineClient extends BaseAction<void, Array<any>> {
async _handle(payload: void) { async _handle(payload: void) {
//注册监听 //注册监听
const NTQQSystemApi = this.core.apis.SystemApi; this.core.apis.SystemApi.getOnlineDev();
NTQQSystemApi.getOnlineDev();
await sleep(500); await sleep(500);
return []; return [];

View File

@@ -19,10 +19,9 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
actionName = ActionName.GoCQHTTP_GetStrangerInfo; actionName = ActionName.GoCQHTTP_GetStrangerInfo;
async _handle(payload: Payload): Promise<OB11User> { async _handle(payload: Payload): Promise<OB11User> {
const NTQQUserApi = this.core.apis.UserApi;
const user_id = payload.user_id.toString(); const user_id = payload.user_id.toString();
const extendData = await NTQQUserApi.getUserDetailInfoByUinV2(user_id); const extendData = await this.core.apis.UserApi.getUserDetailInfoByUinV2(user_id);
const uid = (await NTQQUserApi.getUidByUinV2(user_id))!; const uid = (await this.core.apis.UserApi.getUidByUinV2(user_id))!;
if (!uid || uid.indexOf('*') != -1) { if (!uid || uid.indexOf('*') != -1) {
return { return {
...extendData.detail.simpleInfo.coreInfo, ...extendData.detail.simpleInfo.coreInfo,
@@ -38,7 +37,7 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
login_days: 0, login_days: 0,
}; };
} }
const data = { ...extendData, ...(await NTQQUserApi.getUserDetailInfo(uid)) }; const data = { ...extendData, ...(await this.core.apis.UserApi.getUserDetailInfo(uid)) };
return OB11Entities.stranger(data); return OB11Entities.stranger(data);
} }
} }

View File

@@ -22,7 +22,6 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_SendGroupNotice; actionName = ActionName.GoCQHTTP_SendGroupNotice;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi;
let UploadImage: { id: string, width: number, height: number } | undefined = undefined; let UploadImage: { id: string, width: number, height: number } | undefined = undefined;
if (payload.image) { if (payload.image) {
//公告图逻辑 //公告图逻辑
@@ -38,7 +37,7 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
throw `群公告${payload.image}设置失败,获取资源失败`; throw `群公告${payload.image}设置失败,获取资源失败`;
} }
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断 await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断
const ImageUploadResult = await NTQQGroupApi.uploadGroupBulletinPic(payload.group_id.toString(), path); const ImageUploadResult = await this.core.apis.GroupApi.uploadGroupBulletinPic(payload.group_id.toString(), path);
if (ImageUploadResult.errCode != 0) { if (ImageUploadResult.errCode != 0) {
throw `群公告${payload.image}设置失败,图片上传失败`; throw `群公告${payload.image}设置失败,图片上传失败`;
} }
@@ -50,7 +49,7 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
} }
const noticePinned = +(payload.pinned ?? 0); const noticePinned = +(payload.pinned ?? 0);
const noticeConfirmRequired = +(payload.confirm_required ?? 0); const noticeConfirmRequired = +(payload.confirm_required ?? 0);
const publishGroupBulletinResult = await NTQQGroupApi.publishGroupBulletin(payload.group_id.toString(), payload.content, UploadImage, noticePinned, noticeConfirmRequired); const publishGroupBulletinResult = await this.core.apis.GroupApi.publishGroupBulletin(payload.group_id.toString(), payload.content, UploadImage, noticePinned, noticeConfirmRequired);
if (publishGroupBulletinResult.result != 0) { if (publishGroupBulletinResult.result != 0) {
throw `设置群公告失败,错误信息:${publishGroupBulletinResult.errMsg}`; throw `设置群公告失败,错误信息:${publishGroupBulletinResult.errMsg}`;

View File

@@ -25,14 +25,13 @@ export default class SetGroupPortrait extends BaseAction<Payload, any> {
} }
async _handle(payload: Payload): Promise<any> { async _handle(payload: Payload): Promise<any> {
const NTQQGroupApi = this.core.apis.GroupApi; const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
const { path, isLocal, errMsg, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
if (!success) { if (!success) {
throw `头像${payload.file}设置失败,file字段可能格式不正确`; throw `头像${payload.file}设置失败,file字段可能格式不正确`;
} }
if (path) { if (path) {
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断 await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃需要提前判断
const ret = await NTQQGroupApi.setGroupAvatar(payload.group_id.toString(), path) as any; const ret = await this.core.apis.GroupApi.setGroupAvatar(payload.group_id.toString(), path) as any;
if (!isLocal) { if (!isLocal) {
fs.unlink(path, () => { fs.unlink(path, () => {
}); });

View File

@@ -19,10 +19,9 @@ export class SetQQProfile extends BaseAction<Payload, any | null> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQUserApi = this.core.apis.UserApi;
const self = this.core.selfInfo; const self = this.core.selfInfo;
const OldProfile = await NTQQUserApi.getUserDetailInfo(self.uid); const OldProfile = await this.core.apis.UserApi.getUserDetailInfo(self.uid);
return await NTQQUserApi.modifySelfProfile({ return await this.core.apis.UserApi.modifySelfProfile({
nick: payload.nickname, nick: payload.nickname,
longNick: (payload?.personal_note ?? OldProfile?.longNick) || '', longNick: (payload?.personal_note ?? OldProfile?.longNick) || '',
sex: parseInt(payload?.sex ? payload?.sex.toString() : OldProfile?.sex!.toString()), sex: parseInt(payload?.sex ? payload?.sex.toString() : OldProfile?.sex!.toString()),

View File

@@ -22,14 +22,12 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
payloadSchema = SchemaData; payloadSchema = SchemaData;
async getPeer(payload: Payload): Promise<Peer> { async getPeer(payload: Payload): Promise<Peer> {
const NTQQUserApi = this.core.apis.UserApi;
const NTQQFriendApi = this.core.apis.FriendApi;
if (payload.user_id) { if (payload.user_id) {
const peerUid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const peerUid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!peerUid) { if (!peerUid) {
throw `私聊${payload.user_id}不存在`; throw `私聊${payload.user_id}不存在`;
} }
const isBuddy = await NTQQFriendApi.isBuddy(peerUid); const isBuddy = await this.core.apis.FriendApi.isBuddy(peerUid);
return { chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid }; return { chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid };
} }
throw new Error('缺少参数 user_id'); throw new Error('缺少参数 user_id');

View File

@@ -18,16 +18,14 @@ export default class DelEssenceMsg extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> { async _handle(payload: Payload): Promise<any> {
const NTQQGroupApi = this.core.apis.GroupApi;
const msg = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id); const msg = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id);
const NTQQWebApi = this.core.apis.WebApi;
if (!msg) { if (!msg) {
const data = NTQQGroupApi.essenceLRU.getValue(+payload.message_id); const data = this.core.apis.GroupApi.essenceLRU.getValue(+payload.message_id);
if(!data) throw new Error('消息不存在'); if(!data) throw new Error('消息不存在');
const { msg_seq, msg_random, group_id } = JSON.parse(data) as { msg_seq: string, msg_random: string, group_id: string }; const { msg_seq, msg_random, group_id } = JSON.parse(data) as { msg_seq: string, msg_random: string, group_id: string };
return await NTQQGroupApi.removeGroupEssenceBySeq(group_id, msg_seq, msg_random); return await this.core.apis.GroupApi.removeGroupEssenceBySeq(group_id, msg_seq, msg_random);
} }
return await NTQQGroupApi.removeGroupEssence( return await this.core.apis.GroupApi.removeGroupEssence(
msg.Peer.peerUid, msg.Peer.peerUid,
msg.MsgId, msg.MsgId,
); );

View File

@@ -19,9 +19,8 @@ export class DelGroupNotice extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi;
const group = payload.group_id.toString(); const group = payload.group_id.toString();
const noticeId = payload.notice_id; const noticeId = payload.notice_id;
return await NTQQGroupApi.deleteGroupBulletin(group, noticeId); return await this.core.apis.GroupApi.deleteGroupBulletin(group, noticeId);
} }
} }

View File

@@ -31,9 +31,7 @@ export class GetGroupEssence extends BaseAction<Payload, any> {
} }
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQWebApi = this.core.apis.WebApi; const msglist = (await this.core.apis.WebApi.getGroupEssenceMsgAll(payload.group_id.toString())).flatMap((e) => e.data.msg_list);
const NTQQGroupApi = this.core.apis.GroupApi;
const msglist = (await NTQQWebApi.getGroupEssenceMsgAll(payload.group_id.toString())).flatMap((e) => e.data.msg_list);
if (!msglist) { if (!msglist) {
throw new Error('获取失败'); throw new Error('获取失败');
} }
@@ -65,7 +63,7 @@ export class GetGroupEssence extends BaseAction<Payload, any> {
//设置第一个bit为0 保证shortId为正数 //设置第一个bit为0 保证shortId为正数
hash[0] &= 0x7f; hash[0] &= 0x7f;
const shortId = hash.readInt32BE(0); const shortId = hash.readInt32BE(0);
NTQQGroupApi.essenceLRU.set(shortId, msgTempData); this.core.apis.GroupApi.essenceLRU.set(shortId, msgTempData);
return { return {
msg_seq: msg.msg_seq, msg_seq: msg.msg_seq,
msg_random: msg.msg_random, msg_random: msg.msg_random,

View File

@@ -16,21 +16,19 @@ export class GetGroupIgnoredNotifies extends BaseAction<void, any> {
actionName = ActionName.GetGroupIgnoredNotifies; actionName = ActionName.GetGroupIgnoredNotifies;
async _handle(payload: void) { async _handle(payload: void) {
const NTQQUserApi = this.core.apis.UserApi; const ignoredNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(true, 10);
const NTQQGroupApi = this.core.apis.GroupApi;
const ignoredNotifies = await NTQQGroupApi.getSingleScreenNotifies(true, 10);
const retData: any = { const retData: any = {
join_requests: await Promise.all( join_requests: await Promise.all(
ignoredNotifies ignoredNotifies
.filter(notify => notify.type === 7) .filter(notify => notify.type === 7)
.map(async SSNotify => ({ .map(async SSNotify => ({
request_id: SSNotify.seq, request_id: SSNotify.seq,
requester_uin: await NTQQUserApi.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,
group_name: SSNotify.group?.groupName, group_name: SSNotify.group?.groupName,
checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE, checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE,
actor: await NTQQUserApi.getUinByUidV2(SSNotify.user2?.uid) || 0, actor: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user2?.uid) || 0,
}))), }))),
}; };

View File

@@ -19,8 +19,7 @@ class GetGroupInfo extends BaseAction<Payload, OB11Group> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi; const group = (await this.core.apis.GroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString());
const group = (await NTQQGroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString());
if (!group) throw `${payload.group_id}不存在`; if (!group) throw `${payload.group_id}不存在`;
return OB11Entities.group(group); return OB11Entities.group(group);
} }

View File

@@ -2,7 +2,6 @@ import { OB11Group } from '@/onebot';
import { OB11Entities } from '@/onebot/entities'; import { OB11Entities } from '@/onebot/entities';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { Group } from '@/core/entities';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
// no_cache get时传字符串 // no_cache get时传字符串
const SchemaData = { const SchemaData = {
@@ -19,9 +18,9 @@ class GetGroupList extends BaseAction<Payload, OB11Group[]> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi; return OB11Entities.groups(
const groupList: Group[] = await NTQQGroupApi.getGroups(typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache); await this.core.apis.GroupApi.getGroups(
return OB11Entities.groups(groupList); typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache));
} }
} }

View File

@@ -22,14 +22,12 @@ class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQUserApi = this.core.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const isNocache = typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache; const isNocache = typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache;
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error(`Uin2Uid Error ${payload.user_id}不存在`); if (!uid) throw new Error(`Uin2Uid Error ${payload.user_id}不存在`);
const [member, info] = await Promise.allSettled([ const [member, info] = await Promise.allSettled([
NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache), this.core.apis.GroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache),
NTQQUserApi.getUserDetailInfo(uid), this.core.apis.UserApi.getUserDetailInfo(uid),
]); ]);
if (member.status !== 'fulfilled') throw new Error(`群(${payload.group_id})成员${payload.user_id}获取失败 ${member.reason}`); if (member.status !== 'fulfilled') throw new Error(`群(${payload.group_id})成员${payload.user_id}获取失败 ${member.reason}`);
if (!member.value) throw new Error(`群(${payload.group_id})成员${payload.user_id}不存在`); if (!member.value) throw new Error(`群(${payload.group_id})成员${payload.user_id}不存在`);

View File

@@ -20,9 +20,7 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi; const groupMembers = await this.core.apis.GroupApi.getGroupMembersV2(payload.group_id.toString());
const NTQQWebApi = this.core.apis.WebApi;
const groupMembers = await NTQQGroupApi.getGroupMembersV2(payload.group_id.toString());
const groupMembersArr = Array.from(groupMembers.values()); const groupMembersArr = Array.from(groupMembers.values());
let _groupMembers = groupMembersArr.map(item => { let _groupMembers = groupMembersArr.map(item => {
@@ -48,7 +46,7 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
}); });
if (isPrivilege) { if (isPrivilege) {
const webGroupMembers = await NTQQWebApi.getGroupMembers(payload.group_id.toString()); const webGroupMembers = await this.core.apis.WebApi.getGroupMembers(payload.group_id.toString());
for (let i = 0, len = webGroupMembers.length; i < len; i++) { for (let i = 0, len = webGroupMembers.length; i < len; i++) {
if (!webGroupMembers[i]?.uin) { if (!webGroupMembers[i]?.uin) {
continue; continue;

View File

@@ -34,10 +34,8 @@ export class GetGroupNotice extends BaseAction<Payload, GroupNotice[]> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQWebApi = this.core.apis.WebApi;
const group = payload.group_id.toString(); const group = payload.group_id.toString();
const ret = await NTQQWebApi.getGroupNotice(group); const ret = await this.core.apis.WebApi.getGroupNotice(group);
if (!ret) { if (!ret) {
throw new Error('获取公告失败'); throw new Error('获取公告失败');
} }

View File

@@ -18,12 +18,11 @@ export default class SetEssenceMsg extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> { async _handle(payload: Payload): Promise<any> {
const NTQQGroupApi = this.core.apis.GroupApi;
const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
if (!msg) { if (!msg) {
throw new Error('msg not found'); throw new Error('msg not found');
} }
return await NTQQGroupApi.addGroupEssence( return await this.core.apis.GroupApi.addGroupEssence(
msg.Peer.peerUid, msg.Peer.peerUid,
msg.MsgId, msg.MsgId,
); );

View File

@@ -20,10 +20,9 @@ export default class SetGroupAddRequest extends BaseAction<Payload, null> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.core.apis.GroupApi;
const flag = payload.flag.toString(); const flag = payload.flag.toString();
const approve = payload.approve?.toString() !== 'false'; const approve = payload.approve?.toString() !== 'false';
await NTQQGroupApi.handleGroupRequest(flag, await this.core.apis.GroupApi.handleGroupRequest(flag,
approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject, approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
payload.reason ?? ' ', payload.reason ?? ' ',
); );

View File

@@ -21,11 +21,9 @@ export default class SetGroupAdmin extends BaseAction<Payload, null> {
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const enable = typeof payload.enable === 'string' ? payload.enable === 'true' : !!payload.enable; const enable = typeof payload.enable === 'string' ? payload.enable === 'true' : !!payload.enable;
const NTQQGroupApi = this.core.apis.GroupApi; const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
const NTQQUserApi = this.core.apis.UserApi;
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('get Uid Error'); if (!uid) throw new Error('get Uid Error');
await NTQQGroupApi.setMemberRole(payload.group_id.toString(), uid, enable ? GroupMemberRole.admin : GroupMemberRole.normal); await this.core.apis.GroupApi.setMemberRole(payload.group_id.toString(), uid, enable ? GroupMemberRole.admin : GroupMemberRole.normal);
return null; return null;
} }
} }

View File

@@ -19,11 +19,9 @@ export default class SetGroupBan extends BaseAction<Payload, null> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.core.apis.GroupApi; const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
const NTQQUserApi = this.core.apis.UserApi;
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('uid error'); if (!uid) throw new Error('uid error');
await NTQQGroupApi.banMember(payload.group_id.toString(), await this.core.apis.GroupApi.banMember(payload.group_id.toString(),
[{ uid: uid, timeStamp: parseInt(payload.duration.toString()) }]); [{ uid: uid, timeStamp: parseInt(payload.duration.toString()) }]);
return null; return null;
} }

View File

@@ -19,9 +19,8 @@ export default class SetGroupCard extends BaseAction<Payload, null> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.core.apis.GroupApi; const member = await this.core.apis.GroupApi.getGroupMember(payload.group_id.toString(), payload.user_id.toString());
const member = await NTQQGroupApi.getGroupMember(payload.group_id.toString(), payload.user_id.toString()); if (member) await this.core.apis.GroupApi.setMemberCard(payload.group_id.toString(), member.uid, payload.card || '');
member && await NTQQGroupApi.setMemberCard(payload.group_id.toString(), member.uid, payload.card || '');
return null; return null;
} }
} }

View File

@@ -20,12 +20,10 @@ export default class SetGroupKick extends BaseAction<Payload, null> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const rejectReq = payload.reject_add_request?.toString() == 'true'; const rejectReq = payload.reject_add_request?.toString() == 'true';
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('get Uid Error'); if (!uid) throw new Error('get Uid Error');
await NTQQGroupApi.kickMember(payload.group_id.toString(), [uid], rejectReq); await this.core.apis.GroupApi.kickMember(payload.group_id.toString(), [uid], rejectReq);
return null; return null;
} }
} }

View File

@@ -17,7 +17,6 @@ export default class SetGroupLeave extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> { async _handle(payload: Payload): Promise<any> {
const NTQQGroupApi = this.core.apis.GroupApi; await this.core.apis.GroupApi.quitGroup(payload.group_id.toString());
await NTQQGroupApi.quitGroup(payload.group_id.toString());
} }
} }

View File

@@ -17,8 +17,7 @@ export default class SetGroupName extends BaseAction<Payload, null> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.core.apis.GroupApi; await this.core.apis.GroupApi.setGroupName(payload.group_id.toString(), payload.group_name);
await NTQQGroupApi.setGroupName(payload.group_id.toString(), payload.group_name);
return null; return null;
} }
} }

View File

@@ -19,8 +19,7 @@ export default class SetGroupWholeBan extends BaseAction<Payload, null> {
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const enable = payload.enable?.toString() !== 'false'; const enable = payload.enable?.toString() !== 'false';
const NTQQGroupApi = this.core.apis.GroupApi; await this.core.apis.GroupApi.banGroup(payload.group_id.toString(), enable);
await NTQQGroupApi.banGroup(payload.group_id.toString(), enable);
return null; return null;
} }
} }

View File

@@ -55,12 +55,7 @@ import { GoCQHTTPHandleQuickAction } from './go-cqhttp/QuickAction';
import { GetGroupIgnoredNotifies } from './group/GetGroupIgnoredNotifies'; import { GetGroupIgnoredNotifies } from './group/GetGroupIgnoredNotifies';
import { GetOnlineClient } from './go-cqhttp/GetOnlineClient'; import { GetOnlineClient } from './go-cqhttp/GetOnlineClient';
import { IOCRImage, OCRImage } from './extends/OCRImage'; import { IOCRImage, OCRImage } from './extends/OCRImage';
import { GetGroupFileCount } from './file/GetGroupFileCount';
import { GetGroupFileList } from './file/GetGroupFileList';
import { TranslateEnWordToZn } from './extends/TranslateEnWordToZn'; import { TranslateEnWordToZn } from './extends/TranslateEnWordToZn';
import { SetGroupFileFolder } from './file/SetGroupFileFolder';
import { DelGroupFile } from './file/DelGroupFile';
import { DelGroupFileFolder } from './file/DelGroupFileFolder';
import { SetQQProfile } from './go-cqhttp/SetQQProfile'; import { SetQQProfile } from './go-cqhttp/SetQQProfile';
import { ShareGroupEx, SharePeer } from './extends/ShareContact'; import { ShareGroupEx, SharePeer } from './extends/ShareContact';
import { CreateCollection } from './extends/CreateCollection'; import { CreateCollection } from './extends/CreateCollection';
@@ -92,11 +87,6 @@ import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesBy
export type ActionMap = Map<string, BaseAction<any, any>>; export type ActionMap = Map<string, BaseAction<any, any>>;
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap { export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap {
const ncDelGroupFile = new DelGroupFile(obContext, core);
const ncSetGroupFileFolder = new SetGroupFileFolder(obContext, core);
const ncDelGroupFileFolder = new DelGroupFileFolder(obContext, core);
const ncGetGroupFileCount = new GetGroupFileCount(obContext, core);
const goCqHttpGetGroupRootFiles = new GetGroupRootFiles(obContext, core, ncGetGroupFileCount);
const actionHandlers = [ const actionHandlers = [
new GetGroupInfoEx(obContext, core), new GetGroupInfoEx(obContext, core),
@@ -113,11 +103,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new MarkPrivateMsgAsRead(obContext, core), new MarkPrivateMsgAsRead(obContext, core),
new SetQQAvatar(obContext, core), new SetQQAvatar(obContext, core),
new TranslateEnWordToZn(obContext, core), new TranslateEnWordToZn(obContext, core),
ncGetGroupFileCount, new GetGroupRootFiles(obContext, core),
new GetGroupFileList(obContext, core),
ncSetGroupFileFolder,
ncDelGroupFile,
ncDelGroupFileFolder,
// onebot11 // onebot11
new SendLike(obContext, core), new SendLike(obContext, core),
new GetMsg(obContext, core), new GetMsg(obContext, core),
@@ -185,12 +171,11 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new SetInputStatus(obContext, core), new SetInputStatus(obContext, core),
new GetCSRF(obContext, core), new GetCSRF(obContext, core),
new DelGroupNotice(obContext, core), new DelGroupNotice(obContext, core),
new DeleteGroupFile(obContext, core, ncDelGroupFile), new DeleteGroupFile(obContext, core),
new CreateGroupFileFolder(obContext, core, ncSetGroupFileFolder), new CreateGroupFileFolder(obContext, core),
new DeleteGroupFileFolder(obContext, core, ncDelGroupFileFolder), new DeleteGroupFileFolder(obContext, core),
new GetGroupFileSystemInfo(obContext, core), new GetGroupFileSystemInfo(obContext, core),
goCqHttpGetGroupRootFiles, new GetGroupFilesByFolder(obContext, core),
new GetGroupFilesByFolder(obContext, core, goCqHttpGetGroupRootFiles),
]; ];
const actionMap = new Map(); const actionMap = new Map();
for (const action of actionHandlers) { for (const action of actionHandlers) {

View File

@@ -23,24 +23,19 @@ class DeleteMsg extends BaseAction<Payload, void> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQMsgApi = this.core.apis.MsgApi;
const msg = MessageUnique.getMsgIdAndPeerByShortId(Number(payload.message_id)); const msg = MessageUnique.getMsgIdAndPeerByShortId(Number(payload.message_id));
if (msg) { if (msg) {
const ret = this.core.eventWrapper.registerListen( const ret = this.core.eventWrapper.registerListen(
'NodeIKernelMsgListener/onMsgInfoListUpdate', 'NodeIKernelMsgListener/onMsgInfoListUpdate',
1, 1,
5000, 1000,
(msgs) => !!msgs.find(m => m.msgId === msg.MsgId && m.recallTime !== '0'), (msgs) => !!msgs.find(m => m.msgId === msg.MsgId && m.recallTime !== '0'),
).catch(() => new Promise<undefined>((resolve) => { ).catch(() => undefined);
resolve(undefined); await this.core.apis.MsgApi.recallMsg(msg.Peer, [msg.MsgId]);
}));
await NTQQMsgApi.recallMsg(msg.Peer, [msg.MsgId]);
const data = await ret; const data = await ret;
if (!data) { if (!data) throw new Error('Recall failed');
//throw new Error('Recall failed'); } else {
} throw new Error('Recall failed');
//await sleep(100);
//await NTQQMsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId]);
} }
} }
} }

View File

@@ -18,9 +18,8 @@ type Payload = FromSchema<typeof SchemaData>;
class ForwardSingleMsg extends BaseAction<Payload, null> { class ForwardSingleMsg extends BaseAction<Payload, null> {
protected async getTargetPeer(payload: Payload): Promise<Peer> { protected async getTargetPeer(payload: Payload): Promise<Peer> {
const NTQQUserApi = this.core.apis.UserApi;
if (payload.user_id) { if (payload.user_id) {
const peerUid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const peerUid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!peerUid) { if (!peerUid) {
throw new Error(`无法找到私聊对象${payload.user_id}`); throw new Error(`无法找到私聊对象${payload.user_id}`);
} }
@@ -30,13 +29,12 @@ class ForwardSingleMsg extends BaseAction<Payload, null> {
} }
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQMsgApi = this.core.apis.MsgApi;
const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
if (!msg) { if (!msg) {
throw new Error(`无法找到消息${payload.message_id}`); throw new Error(`无法找到消息${payload.message_id}`);
} }
const peer = await this.getTargetPeer(payload); const peer = await this.getTargetPeer(payload);
const ret = await NTQQMsgApi.forwardMsg(msg.Peer, const ret = await this.core.apis.MsgApi.forwardMsg(msg.Peer,
peer, peer,
[msg.MsgId], [msg.MsgId],
); );

View File

@@ -22,7 +22,6 @@ class GetMsg extends BaseAction<Payload, OB11Message> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQMsgApi = this.core.apis.MsgApi;
// log("history msg ids", Object.keys(msgHistory)); // log("history msg ids", Object.keys(msgHistory));
if (!payload.message_id) { if (!payload.message_id) {
throw Error('参数message_id不能为空'); throw Error('参数message_id不能为空');
@@ -33,7 +32,7 @@ class GetMsg extends BaseAction<Payload, OB11Message> {
throw new Error('消息不存在'); throw new Error('消息不存在');
} }
const peer = { guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType }; const peer = { guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType };
const msg = await NTQQMsgApi.getMsgsByMsgId( const msg = await this.core.apis.MsgApi.getMsgsByMsgId(
peer, peer,
[msgIdWithPeer?.MsgId || payload.message_id.toString()]); [msgIdWithPeer?.MsgId || payload.message_id.toString()]);
const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg.msgList[0], 'array'); const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg.msgList[0], 'array');

View File

@@ -15,14 +15,12 @@ type PlayloadType = FromSchema<typeof SchemaData>;
class MarkMsgAsRead extends BaseAction<PlayloadType, null> { class MarkMsgAsRead extends BaseAction<PlayloadType, null> {
async getPeer(payload: PlayloadType): Promise<Peer> { async getPeer(payload: PlayloadType): Promise<Peer> {
const NTQQUserApi = this.core.apis.UserApi;
const NTQQFriendApi = this.core.apis.FriendApi;
if (payload.user_id) { if (payload.user_id) {
const peerUid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const peerUid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!peerUid) { if (!peerUid) {
throw `私聊${payload.user_id}不存在`; throw `私聊${payload.user_id}不存在`;
} }
const isBuddy = await NTQQFriendApi.isBuddy(peerUid); const isBuddy = await this.core.apis.FriendApi.isBuddy(peerUid);
return { chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid }; return { chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid };
} }
if (!payload.group_id) { if (!payload.group_id) {
@@ -32,9 +30,7 @@ class MarkMsgAsRead extends BaseAction<PlayloadType, null> {
} }
async _handle(payload: PlayloadType): Promise<null> { async _handle(payload: PlayloadType): Promise<null> {
const NTQQMsgApi = this.core.apis.MsgApi; const ret = await this.core.apis.MsgApi.setMsgRead(await this.getPeer(payload));
// 调用API
const ret = await NTQQMsgApi.setMsgRead(await this.getPeer(payload));
if (ret.result != 0) { if (ret.result != 0) {
throw new Error('设置已读失败,' + ret.errMsg); throw new Error('设置已读失败,' + ret.errMsg);
} }
@@ -70,8 +66,7 @@ export class MarkAllMsgAsRead extends BaseAction<Payload, null> {
actionName = ActionName._MarkAllMsgAsRead; actionName = ActionName._MarkAllMsgAsRead;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQMsgApi = this.core.apis.MsgApi; await this.core.apis.MsgApi.markAllMsgAsRead();
await NTQQMsgApi.markallMsgAsRead();
return null; return null;
} }
} }

View File

@@ -34,9 +34,6 @@ export async function createContext(core: NapCatCore, payload: OB11PostSendMsg,
// This function determines the type of message by the existence of user_id / group_id, // This function determines the type of message by the existence of user_id / group_id,
// not message_type. // not message_type.
// This redundant design of Ob11 here should be blamed. // This redundant design of Ob11 here should be blamed.
const NTQQFriendApi = core.apis.FriendApi;
const NTQQUserApi = core.apis.UserApi;
const NTQQMsgApi = core.apis.MsgApi;
if ((contextMode === ContextMode.Group || contextMode === ContextMode.Normal) && payload.group_id) { if ((contextMode === ContextMode.Group || contextMode === ContextMode.Normal) && payload.group_id) {
return { return {
chatType: ChatType.KCHATTYPEGROUP, chatType: ChatType.KCHATTYPEGROUP,
@@ -44,11 +41,11 @@ export async function createContext(core: NapCatCore, payload: OB11PostSendMsg,
}; };
} }
if ((contextMode === ContextMode.Private || contextMode === ContextMode.Normal) && payload.user_id) { if ((contextMode === ContextMode.Private || contextMode === ContextMode.Normal) && payload.user_id) {
const Uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const Uid = await core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!Uid) throw new Error('无法获取用户信息'); if (!Uid) throw new Error('无法获取用户信息');
const isBuddy = await NTQQFriendApi.isBuddy(Uid); const isBuddy = await core.apis.FriendApi.isBuddy(Uid);
if (!isBuddy) { if (!isBuddy) {
const ret = await NTQQMsgApi.getTempChatInfo(ChatType.KCHATTYPETEMPC2CFROMGROUP, Uid); const ret = await core.apis.MsgApi.getTempChatInfo(ChatType.KCHATTYPETEMPC2CFROMGROUP, Uid);
if (ret.tmpChatInfo?.groupCode) { if (ret.tmpChatInfo?.groupCode) {
return { return {
chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP, chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP,
@@ -139,7 +136,6 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
} }
private async handleForwardedNodes(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<RawMessage | null> { private async handleForwardedNodes(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<RawMessage | null> {
const NTQQMsgApi = this.core.apis.MsgApi;
const selfPeer = { const selfPeer = {
chatType: ChatType.KCHATTYPEC2C, chatType: ChatType.KCHATTYPEC2C,
peerUid: this.core.selfInfo.uid, peerUid: this.core.selfInfo.uid,
@@ -206,7 +202,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
logger.logError('转发消息失败,未找到消息', msgId); logger.logError('转发消息失败,未找到消息', msgId);
continue; continue;
} }
const nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0]; const nodeMsg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid }; srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid };
if (srcPeer.peerUid !== nodeMsg.peerUid) { if (srcPeer.peerUid !== nodeMsg.peerUid) {
needSendSelf = true; needSendSelf = true;
@@ -230,7 +226,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
if (retMsgIds.length === 0) throw Error('转发消息失败,生成节点为空'); if (retMsgIds.length === 0) throw Error('转发消息失败,生成节点为空');
try { try {
logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds); logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds); return await this.core.apis.MsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds);
} catch (e) { } catch (e) {
logger.logError('forward failed', e); logger.logError('forward failed', e);
return null; return null;
@@ -243,9 +239,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
peerUid: this.core.selfInfo.uid, peerUid: this.core.selfInfo.uid,
}; };
const logger = this.core.context.logger; const logger = this.core.context.logger;
const NTQQMsgApi = this.core.apis.MsgApi;
//msg 为待克隆消息 //msg 为待克隆消息
const sendElements: SendMessageElement[] = []; const sendElements: SendMessageElement[] = [];
for (const element of msg.elements) { for (const element of msg.elements) {
@@ -256,7 +250,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
logger.logDebug('需要clone的消息无法解析将会忽略掉', msg); logger.logDebug('需要clone的消息无法解析将会忽略掉', msg);
} }
try { try {
return await NTQQMsgApi.sendMsg(selfPeer, sendElements, true); return await this.core.apis.MsgApi.sendMsg(selfPeer, sendElements, true);
} catch (e) { } catch (e) {
logger.logError(e, '克隆转发消息失败,将忽略本条消息', msg); logger.logError(e, '克隆转发消息失败,将忽略本条消息', msg);
} }

View File

@@ -19,7 +19,6 @@ export class SetMsgEmojiLike extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQMsgApi = this.core.apis.MsgApi;
const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
if (!msg) { if (!msg) {
throw new Error('msg not found'); throw new Error('msg not found');
@@ -27,10 +26,10 @@ export class SetMsgEmojiLike extends BaseAction<Payload, any> {
if (!payload.emoji_id) { if (!payload.emoji_id) {
throw new Error('emojiId not found'); throw new Error('emojiId not found');
} }
const msgData = (await NTQQMsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId])).msgList; const msgData = (await this.core.apis.MsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId])).msgList;
if (!msgData || msgData.length == 0 || !msgData[0].msgSeq) { if (!msgData || msgData.length == 0 || !msgData[0].msgSeq) {
throw new Error('find msg by msgid error'); throw new Error('find msg by msgid error');
} }
return await NTQQMsgApi.setEmojiLike(msg.Peer, msgData[0].msgSeq, payload.emoji_id.toString(), true); return await this.core.apis.MsgApi.setEmojiLike(msg.Peer, msgData[0].msgSeq, payload.emoji_id.toString(), true);
} }
} }

View File

@@ -22,52 +22,10 @@ export class GetCookies extends BaseAction<Payload, Response> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQUserApi = this.core.apis.UserApi; const cookiesObject = await this.core.apis.UserApi.getCookies(payload.domain);
const NTQQWebApi = this.core.apis.WebApi;
// if (!payload.domain) {
// throw new Error('缺少参数 domain');
// }
// if (payload.domain.endsWith('qzone.qq.com')) {
// // 兼容整个 *.qzone.qq.com
// const data = (await NTQQUserApi.getQzoneCookies());
// const Bkn = WebApi.genBkn(data.p_skey);
// const CookieValue = 'p_skey=' + data.p_skey + '; skey=' + data.skey + '; p_uin=o' + selfInfo.uin + '; uin=o' + selfInfo.uin;
// return { cookies: CookieValue };
// }
// // 取Skey
// // 先NodeIKernelTicketService.forceFetchClientKey('')
// // 返回值
// // {
// // result: 0,
// // errMsg: '',
// // url: '',
// // keyIndex: '19',
// // clientKey: 'clientKey',
// // expireTime: '7200'
// // }
// // request https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=1627126029&clientkey=key
// // &u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=keyIndex
// const _PSkey = (await NTQQUserApi.getPSkey([payload.domain]))[payload.domain];
// // 取Pskey
// // NodeIKernelTipOffService.getPskey([ 'qun.qq.com' ], true )
// // {
// // domainPskeyMap: 0,
// // errMsg: 'success',
// // domainPskeyMap: Map(1) {
// // 'qun.qq.com' => 'pskey'
// // }
// // }
// if (!_PSkey || !_Skey) {
// throw new Error('获取Cookies失败');
// }
// const cookies = `p_skey=${_PSkey}; skey=${_Skey}; p_uin=o${selfInfo.uin}; uin=o${selfInfo.uin}`;
// return {
// cookies
// };
const cookiesObject = await NTQQUserApi.getCookies(payload.domain);
//把获取到的cookiesObject转换成 k=v; 格式字符串拼接在一起 //把获取到的cookiesObject转换成 k=v; 格式字符串拼接在一起
const cookies = Object.entries(cookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); const cookies = Object.entries(cookiesObject).map(([key, value]) => `${key}=${value}`).join('; ');
const bkn = cookiesObject?.skey ? NTQQWebApi.getBknFromCookie(cookiesObject) : ''; const bkn = cookiesObject?.skey ? this.core.apis.WebApi.getBknFromCookie(cookiesObject) : '';
return { cookies, bkn }; return { cookies, bkn };
} }
} }

View File

@@ -19,7 +19,6 @@ export default class GetFriendList extends BaseAction<Payload, OB11User[]> {
async _handle(payload: Payload) { async _handle(payload: Payload) {
//全新逻辑 //全新逻辑
const NTQQFriendApi = this.core.apis.FriendApi; return OB11Entities.friendsV2(await this.core.apis.FriendApi.getBuddyV2(typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache));
return OB11Entities.friendsV2(await NTQQFriendApi.getBuddyV2(typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache));
} }
} }

View File

@@ -16,11 +16,9 @@ export default class GetRecentContact extends BaseAction<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQUserApi = this.core.apis.UserApi; const ret = await this.core.apis.UserApi.getRecentContactListSnapShot(+(payload.count || 10));
const NTQQMsgApi = this.core.apis.MsgApi;
const ret = await NTQQUserApi.getRecentContactListSnapShot(+(payload.count || 10));
return await Promise.all(ret.info.changedList.map(async (t) => { return await Promise.all(ret.info.changedList.map(async (t) => {
const FastMsg = await NTQQMsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]); const FastMsg = await this.core.apis.MsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]);
if (FastMsg.msgList.length > 0) { if (FastMsg.msgList.length > 0) {
//扩展ret.info.changedList //扩展ret.info.changedList
const lastestMsg = await this.obContext.apis.MsgApi.parseMessage(FastMsg.msgList[0], 'array'); const lastestMsg = await this.obContext.apis.MsgApi.parseMessage(FastMsg.msgList[0], 'array');

View File

@@ -18,11 +18,10 @@ export default class SendLike extends BaseAction<Payload, null> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQUserApi = this.core.apis.UserApi;
//logDebug('点赞参数', payload); //logDebug('点赞参数', payload);
const qq = payload.user_id.toString(); const qq = payload.user_id.toString();
const uid: string = await NTQQUserApi.getUidByUinV2(qq) || ''; const uid: string = await this.core.apis.UserApi.getUidByUinV2(qq) || '';
const result = await NTQQUserApi.like(uid, parseInt(payload.times?.toString()) || 1); const result = await this.core.apis.UserApi.like(uid, parseInt(payload.times?.toString()) || 1);
//logDebug('点赞结果', result); //logDebug('点赞结果', result);
if (result.result !== 0) { if (result.result !== 0) {
throw `点赞失败 ${result.errMsg}`; throw `点赞失败 ${result.errMsg}`;

View File

@@ -19,9 +19,8 @@ export default class SetFriendAddRequest extends BaseAction<Payload, null> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const NTQQFriendApi = this.core.apis.FriendApi;
const approve = payload.approve?.toString() !== 'false'; const approve = payload.approve?.toString() !== 'false';
await NTQQFriendApi.handleFriendRequest(payload.flag, approve); await this.core.apis.FriendApi.handleFriendRequest(payload.flag, approve);
return null; return null;
} }
} }

View File

@@ -14,7 +14,6 @@ export class OneBotFriendApi {
//使用前预先判断 busiId 1061 //使用前预先判断 busiId 1061
async parsePrivatePokeEvent(grayTipElement: GrayTipElement) { async parsePrivatePokeEvent(grayTipElement: GrayTipElement) {
const NTQQUserApi = this.core.apis.UserApi;
const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr); const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr);
let pokedetail: any[] = json.items; let pokedetail: any[] = json.items;
//筛选item带有uid的元素 //筛选item带有uid的元素
@@ -23,8 +22,8 @@ export class OneBotFriendApi {
if (pokedetail.length == 2) { if (pokedetail.length == 2) {
return new OB11FriendPokeEvent( return new OB11FriendPokeEvent(
this.core, this.core,
parseInt((await NTQQUserApi.getUinByUidV2(pokedetail[0].uid))!), parseInt((await this.core.apis.UserApi.getUinByUidV2(pokedetail[0].uid))!),
parseInt((await NTQQUserApi.getUinByUidV2(pokedetail[1].uid))!), parseInt((await this.core.apis.UserApi.getUinByUidV2(pokedetail[1].uid))!),
pokedetail, pokedetail,
); );
} }

View File

@@ -30,16 +30,13 @@ export class OneBotGroupApi {
} }
async parseGroupEvent(msg: RawMessage) { async parseGroupEvent(msg: RawMessage) {
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQMsgApi = this.core.apis.MsgApi;
const logger = this.core.context.logger; const logger = this.core.context.logger;
if (msg.chatType !== ChatType.KCHATTYPEGROUP) { if (msg.chatType !== ChatType.KCHATTYPEGROUP) {
return; return;
} }
//log("group msg", msg); //log("group msg", msg);
if (msg.senderUin && msg.senderUin !== '0') { if (msg.senderUin && msg.senderUin !== '0') {
const member = await NTQQGroupApi.getGroupMember(msg.peerUid, msg.senderUin); const member = await this.core.apis.GroupApi.getGroupMember(msg.peerUid, msg.senderUin);
if (member && member.cardName !== msg.sendMemberName) { if (member && member.cardName !== msg.sendMemberName) {
const newCardName = msg.sendMemberName || ''; const newCardName = msg.sendMemberName || '';
const event = new OB11GroupCardEvent(this.core, parseInt(msg.peerUid), parseInt(msg.senderUin), newCardName, member.cardName); const event = new OB11GroupCardEvent(this.core, parseInt(msg.peerUid), parseInt(msg.senderUin), newCardName, member.cardName);
@@ -58,7 +55,7 @@ export class OneBotGroupApi {
const BanEvent = await this.obContext.apis.GroupApi.parseGroupBanEvent(msg.peerUid, element.grayTipElement); const BanEvent = await this.obContext.apis.GroupApi.parseGroupBanEvent(msg.peerUid, element.grayTipElement);
if (BanEvent) return BanEvent; if (BanEvent) return BanEvent;
} else if (groupElement.type == TipGroupElementType.kicked) { } else if (groupElement.type == TipGroupElementType.kicked) {
NTQQGroupApi.quitGroup(msg.peerUid).then(); this.core.apis.GroupApi.quitGroup(msg.peerUid).then();
try { try {
const KickEvent = await this.obContext.apis.GroupApi.parseGroupKickEvent(msg.peerUid, element.grayTipElement); const KickEvent = await this.obContext.apis.GroupApi.parseGroupKickEvent(msg.peerUid, element.grayTipElement);
if (KickEvent) return KickEvent; if (KickEvent) return KickEvent;
@@ -110,8 +107,8 @@ export class OneBotGroupApi {
return new OB11GroupPokeEvent( return new OB11GroupPokeEvent(
this.core, this.core,
parseInt(msg.peerUid), parseInt(msg.peerUid),
parseInt((await NTQQUserApi.getUinByUidV2(poke_uid[0].uid))!), parseInt((await this.core.apis.UserApi.getUinByUidV2(poke_uid[0].uid))!),
parseInt((await NTQQUserApi.getUinByUidV2(poke_uid[1].uid))!), parseInt((await this.core.apis.UserApi.getUinByUidV2(poke_uid[1].uid))!),
pokedetail, pokedetail,
); );
} }
@@ -127,7 +124,7 @@ export class OneBotGroupApi {
chatType: ChatType.KCHATTYPEGROUP, chatType: ChatType.KCHATTYPEGROUP,
peerUid: Group, peerUid: Group,
}; };
const msgData = await NTQQMsgApi.getMsgsBySeqAndCount(Peer, msgSeq.toString(), 1, true, true); const msgData = await this.core.apis.MsgApi.getMsgsBySeqAndCount(Peer, msgSeq.toString(), 1, true, true);
const msgList = (await this.core.apis.WebApi.getGroupEssenceMsgAll(Group)).flatMap((e) => e.data.msg_list); const msgList = (await this.core.apis.WebApi.getGroupEssenceMsgAll(Group)).flatMap((e) => e.data.msg_list);
const realMsg = msgList.find((e) => e.msg_seq.toString() == msgSeq); const realMsg = msgList.find((e) => e.msg_seq.toString() == msgSeq);
return new OB11GroupEssenceEvent( return new OB11GroupEssenceEvent(
@@ -158,7 +155,6 @@ export class OneBotGroupApi {
async parseGroupBanEvent(GroupCode: string, grayTipElement: GrayTipElement) { async parseGroupBanEvent(GroupCode: string, grayTipElement: GrayTipElement) {
const groupElement = grayTipElement?.groupElement; const groupElement = grayTipElement?.groupElement;
const NTQQGroupApi = this.core.apis.GroupApi;
if (!groupElement?.shutUp) return undefined; if (!groupElement?.shutUp) return undefined;
const memberUid = groupElement.shutUp!.member.uid; const memberUid = groupElement.shutUp!.member.uid;
const adminUid = groupElement.shutUp!.admin.uid; const adminUid = groupElement.shutUp!.admin.uid;
@@ -166,14 +162,14 @@ export class OneBotGroupApi {
let duration = parseInt(groupElement.shutUp!.duration); let duration = parseInt(groupElement.shutUp!.duration);
const subType: 'ban' | 'lift_ban' = duration > 0 ? 'ban' : 'lift_ban'; const subType: 'ban' | 'lift_ban' = duration > 0 ? 'ban' : 'lift_ban';
if (memberUid) { if (memberUid) {
memberUin = (await NTQQGroupApi.getGroupMember(GroupCode, memberUid))?.uin || ''; memberUin = (await this.core.apis.GroupApi.getGroupMember(GroupCode, memberUid))?.uin || '';
} else { } else {
memberUin = '0'; // 0表示全员禁言 memberUin = '0'; // 0表示全员禁言
if (duration > 0) { if (duration > 0) {
duration = -1; duration = -1;
} }
} }
const adminUin = (await NTQQGroupApi.getGroupMember(GroupCode, adminUid))?.uin; const adminUin = (await this.core.apis.GroupApi.getGroupMember(GroupCode, adminUid))?.uin;
if (memberUin && adminUin) { if (memberUin && adminUin) {
return new OB11GroupBanEvent( return new OB11GroupBanEvent(
this.core, this.core,
@@ -215,12 +211,11 @@ export class OneBotGroupApi {
} }
async parseGroupMemberIncreaseEvent(GroupCode: string, grayTipElement: GrayTipElement) { async parseGroupMemberIncreaseEvent(GroupCode: string, grayTipElement: GrayTipElement) {
const NTQQGroupApi = this.core.apis.GroupApi;
const groupElement = grayTipElement?.groupElement; const groupElement = grayTipElement?.groupElement;
if (!groupElement) return undefined; if (!groupElement) return undefined;
const member = await NTQQGroupApi.getGroupMember(GroupCode, groupElement.memberUid); const member = await this.core.apis.UserApi.getUserDetailInfo(groupElement.memberUid);
const memberUin = member?.uin; const memberUin = member?.uin;
const adminMember = await NTQQGroupApi.getGroupMember(GroupCode, groupElement.adminUid); const adminMember = await this.core.apis.GroupApi.getGroupMember(GroupCode, groupElement.adminUid);
if (memberUin) { if (memberUin) {
const operatorUin = adminMember?.uin || memberUin; const operatorUin = adminMember?.uin || memberUin;
return new OB11GroupIncreaseEvent( return new OB11GroupIncreaseEvent(
@@ -235,11 +230,9 @@ export class OneBotGroupApi {
} }
async parseGroupKickEvent(GroupCode: string, grayTipElement: GrayTipElement) { async parseGroupKickEvent(GroupCode: string, grayTipElement: GrayTipElement) {
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const groupElement = grayTipElement?.groupElement; const groupElement = grayTipElement?.groupElement;
if (!groupElement) return undefined; if (!groupElement) return undefined;
const adminUin = (await NTQQGroupApi.getGroupMember(GroupCode, groupElement.adminUid))?.uin || (await NTQQUserApi.getUidByUinV2(groupElement.adminUid)); const adminUin = (await this.core.apis.GroupApi.getGroupMember(GroupCode, groupElement.adminUid))?.uin || (await this.core.apis.UserApi.getUidByUinV2(groupElement.adminUid));
if (adminUin) { if (adminUin) {
return new OB11GroupDecreaseEvent( return new OB11GroupDecreaseEvent(
this.core, this.core,
@@ -278,14 +271,11 @@ export class OneBotGroupApi {
guildId: '', guildId: '',
peerUid: groupCode, peerUid: groupCode,
}; };
const replyMsgList = (await this.core.apis.MsgApi.getMsgExBySeq(peer, msgSeq)).msgList; const replyMsgList = (await this.core.apis.MsgApi.queryFirstMsgBySeq(peer, msgSeq)).msgList;
if (replyMsgList.length < 1) { if (replyMsgList.length < 1) {
return; return;
} }
const replyMsg = replyMsgList const replyMsg = replyMsgList[0];
.filter(e => e.msgSeq == msgSeq)
.sort((a, b) => parseInt(a.msgTime) - parseInt(b.msgTime))[0];
//console.log("表情回应消息长度检测", msgSeq, replyMsg.elements);
if (!replyMsg) { if (!replyMsg) {
this.core.context.logger.logError('解析表情回应消息失败: 未找到回应消息'); this.core.context.logger.logError('解析表情回应消息失败: 未找到回应消息');
return undefined; return undefined;

View File

@@ -106,12 +106,13 @@ export class OneBotMsgApi {
peerUid: msg.peerUid, peerUid: msg.peerUid,
guildId: '', guildId: '',
}; };
const encodedFileId = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId);
return { return {
type: OB11MessageDataType.image, type: OB11MessageDataType.image,
data: { data: {
file: element.fileName, file: encodedFileId,
sub_type: element.picSubType, sub_type: element.picSubType,
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId), file_id: encodedFileId,
url: await this.core.apis.FileApi.getImageUrl(element), url: await this.core.apis.FileApi.getImageUrl(element),
file_size: element.fileSize, file_size: element.fileSize,
}, },
@@ -212,14 +213,13 @@ export class OneBotMsgApi {
}, },
replyElement: async (element, msg) => { replyElement: async (element, msg) => {
const NTQQMsgApi = this.core.apis.MsgApi;
const records = msg.records.find(msgRecord => msgRecord.msgId === element?.sourceMsgIdInRecords); const records = msg.records.find(msgRecord => msgRecord.msgId === element?.sourceMsgIdInRecords);
const peer = { const peer = {
chatType: msg.chatType, chatType: msg.chatType,
peerUid: msg.peerUid, peerUid: msg.peerUid,
guildId: '', guildId: '',
}; };
if (!records) { if (!records || !element.replyMsgTime || !element.senderUidStr) {
this.core.context.logger.logError('获取不到引用的消息', element.replayMsgSeq); this.core.context.logger.logError('获取不到引用的消息', element.replayMsgSeq);
return null; return null;
} }
@@ -234,47 +234,30 @@ export class OneBotMsgApi {
if (records.peerUin === '284840486') { if (records.peerUin === '284840486') {
return createReplyData(records.msgId); return createReplyData(records.msgId);
} }
let replyMsg = (await this.core.apis.MsgApi.queryMsgsWithFilterExWithSeqV2(peer, element.replayMsgSeq, element.replyMsgTime, [element.senderUidStr]))
let replyMsg: RawMessage | undefined; .msgList.find(msg => msg.msgRandom === records.msgRandom);
// Attempt 1
replyMsg = (await NTQQMsgApi.getMsgsBySeqAndCount(peer,element.replayMsgSeq, 1, true, true))
.msgList
.find(msg => msg.msgRandom === records.msgRandom);
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) { if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
// Attempt 2 this.core.context.logger.logError('获取不到引用的消息', element.replayMsgSeq);
replyMsg = (await NTQQMsgApi.getSingleMsg(peer, element.replayMsgSeq)).msgList[0]; return null;
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
// Attempt 3
const replyMsgList = (await NTQQMsgApi.getMsgExBySeq(peer, records.msgSeq)).msgList;
if (replyMsgList.length < 1) {
this.core.context.logger.logError('回复消息消息验证失败', element.replayMsgSeq);
return null;
}
replyMsg = replyMsgList.filter(e => e.msgSeq == records.msgSeq)
.sort((a, b) => parseInt(a.msgTime) - parseInt(b.msgTime))[0];
}
} }
return createReplyData(replyMsg.msgId); return createReplyData(replyMsg.msgId);
}, },
videoElement: async (element, msg, elementWrapper) => { videoElement: async (element, msg, elementWrapper) => {
const NTQQFileApi = this.core.apis.FileApi;
const peer = { const peer = {
chatType: msg.chatType, chatType: msg.chatType,
peerUid: msg.peerUid, peerUid: msg.peerUid,
guildId: '', guildId: '',
}; };
//读取视频链接并兜底 //读取视频链接并兜底
let videoUrlWrappers: Awaited<ReturnType<typeof NTQQFileApi.getVideoUrl>> | undefined; let videoUrlWrappers: Awaited<ReturnType<typeof this.core.apis.FileApi.getVideoUrl>> | undefined;
if (msg.peerUin === '284840486') { if (msg.peerUin === '284840486') {
//TODO: 合并消息内部 应该进行特殊处理 可能需要重写peer 待测试与研究 Mlikiowa Tagged //TODO: 合并消息内部 应该进行特殊处理 可能需要重写peer 待测试与研究 Mlikiowa Tagged
} }
try { try {
videoUrlWrappers = await NTQQFileApi.getVideoUrl({ videoUrlWrappers = await this.core.apis.FileApi.getVideoUrl({
chatType: msg.chatType, chatType: msg.chatType,
peerUid: msg.peerUid, peerUid: msg.peerUid,
guildId: '0', guildId: '0',
@@ -300,7 +283,7 @@ export class OneBotMsgApi {
videoDownUrl = element.filePath; videoDownUrl = element.filePath;
} }
await NTQQFileApi.addFileCache( await this.core.apis.FileApi.addFileCache(
{ {
peerUid: msg.peerUid, peerUid: msg.peerUid,
chatType: msg.chatType, chatType: msg.chatType,
@@ -359,7 +342,6 @@ export class OneBotMsgApi {
}, },
multiForwardMsgElement: async (_, msg) => { multiForwardMsgElement: async (_, msg) => {
const NTQQMsgApi = this.core.apis.MsgApi;
const message_data: OB11MessageForward = { const message_data: OB11MessageForward = {
data: {} as any, data: {} as any,
type: OB11MessageDataType.forward, type: OB11MessageDataType.forward,
@@ -376,7 +358,7 @@ export class OneBotMsgApi {
msg.parentMsgIdList.push(msg.msgId); msg.parentMsgIdList.push(msg.msgId);
//let parentMsgId = msg.parentMsgIdList[msg.parentMsgIdList.length - 2 < 0 ? 0 : msg.parentMsgIdList.length - 2]; //let parentMsgId = msg.parentMsgIdList[msg.parentMsgIdList.length - 2 < 0 ? 0 : msg.parentMsgIdList.length - 2];
//加入自身MsgId //加入自身MsgId
const multiMsgs = (await NTQQMsgApi.getMultiMsg(parentMsgPeer, msg.parentMsgIdList[0], msg.msgId))?.msgList; const multiMsgs = (await this.core.apis.MsgApi.getMultiMsg(parentMsgPeer, msg.parentMsgIdList[0], msg.msgId))?.msgList;
//拉取下级消息 //拉取下级消息
if (!multiMsgs) return null; if (!multiMsgs) return null;
//拉取失败则跳过 //拉取失败则跳过
@@ -446,15 +428,13 @@ export class OneBotMsgApi {
if (!context.peer || context.peer.chatType == ChatType.KCHATTYPEC2C) return undefined; if (!context.peer || context.peer.chatType == ChatType.KCHATTYPEC2C) return undefined;
if (atQQ === 'all') return at(atQQ, atQQ, AtType.atAll, '全体成员'); if (atQQ === 'all') return at(atQQ, atQQ, AtType.atAll, '全体成员');
const NTQQGroupApi = this.core.apis.GroupApi; const atMember = await this.core.apis.GroupApi.getGroupMember(context.peer.peerUid, atQQ);
const NTQQUserApi = this.core.apis.UserApi;
const atMember = await NTQQGroupApi.getGroupMember(context.peer.peerUid, atQQ);
if (atMember) { if (atMember) {
return at(atQQ, atMember.uid, AtType.atUser, atMember.nick || atMember.cardName); return at(atQQ, atMember.uid, AtType.atUser, atMember.nick || atMember.cardName);
} }
const uid = await NTQQUserApi.getUidByUinV2(`${atQQ}`); const uid = await this.core.apis.UserApi.getUidByUinV2(`${atQQ}`);
if (!uid) throw new Error('Get Uid Error'); if (!uid) throw new Error('Get Uid Error');
const info = await NTQQUserApi.getUserDetailInfo(uid); const info = await this.core.apis.UserApi.getUserDetailInfo(uid);
return at(atQQ, uid, AtType.atUser, info.nick || ''); return at(atQQ, uid, AtType.atUser, info.nick || '');
}, },
@@ -464,8 +444,7 @@ export class OneBotMsgApi {
this.core.context.logger.logWarn('回复消息不存在', id); this.core.context.logger.logWarn('回复消息不存在', id);
return undefined; return undefined;
} }
const NTQQMsgApi = this.core.apis.MsgApi; const replyMsg = (await this.core.apis.MsgApi.getMsgsByMsgId(
const replyMsg = (await NTQQMsgApi.getMsgsByMsgId(
replyMsgM.Peer, [replyMsgM.MsgId])).msgList[0]; replyMsgM.Peer, [replyMsgM.MsgId])).msgList[0];
return replyMsg ? return replyMsg ?
{ {
@@ -710,9 +689,6 @@ export class OneBotMsgApi {
if (msg.senderUin == '0' || msg.senderUin == '') return; if (msg.senderUin == '0' || msg.senderUin == '') return;
if (msg.peerUin == '0' || msg.peerUin == '') return; if (msg.peerUin == '0' || msg.peerUin == '') return;
//跳过空消息 //跳过空消息
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQMsgApi = this.core.apis.MsgApi;
const resMsg: OB11Message = { const resMsg: OB11Message = {
self_id: parseInt(this.core.selfInfo.uin), self_id: parseInt(this.core.selfInfo.uin),
user_id: parseInt(msg.senderUin!), user_id: parseInt(msg.senderUin!),
@@ -733,21 +709,24 @@ export class OneBotMsgApi {
message_format: messagePostFormat === 'string' ? 'string' : 'array', message_format: messagePostFormat === 'string' ? 'string' : 'array',
post_type: this.core.selfInfo.uin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE, post_type: this.core.selfInfo.uin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE,
}; };
if (this.core.selfInfo.uin == msg.senderUin) {
resMsg.message_sent_type = 'self';
}
if (msg.chatType == ChatType.KCHATTYPEGROUP) { if (msg.chatType == ChatType.KCHATTYPEGROUP) {
resMsg.sub_type = 'normal'; // 这里go-cqhttp是group而onebot11标准是normal, 蛋疼 resMsg.sub_type = 'normal'; // 这里go-cqhttp是group而onebot11标准是normal, 蛋疼
resMsg.group_id = parseInt(msg.peerUin); resMsg.group_id = parseInt(msg.peerUin);
let member = await NTQQGroupApi.getGroupMember(msg.peerUin, msg.senderUin); let member = await this.core.apis.GroupApi.getGroupMember(msg.peerUin, msg.senderUin);
if (!member) member = await NTQQGroupApi.getGroupMember(msg.peerUin, msg.senderUin); if (!member) member = await this.core.apis.GroupApi.getGroupMember(msg.peerUin, msg.senderUin);
if (member) { if (member) {
resMsg.sender.role = OB11Entities.groupMemberRole(member.role); resMsg.sender.role = OB11Entities.groupMemberRole(member.role);
resMsg.sender.nickname = member.nick; resMsg.sender.nickname = member.nick;
} }
} else if (msg.chatType == ChatType.KCHATTYPEC2C) { } else if (msg.chatType == ChatType.KCHATTYPEC2C) {
resMsg.sub_type = 'friend'; resMsg.sub_type = 'friend';
resMsg.sender.nickname = (await NTQQUserApi.getUserDetailInfo(msg.senderUid)).nick; resMsg.sender.nickname = (await this.core.apis.UserApi.getUserDetailInfo(msg.senderUid)).nick;
} else if (msg.chatType == ChatType.KCHATTYPETEMPC2CFROMGROUP) { } else if (msg.chatType == ChatType.KCHATTYPETEMPC2CFROMGROUP) {
resMsg.sub_type = 'group'; resMsg.sub_type = 'group';
const ret = await NTQQMsgApi.getTempChatInfo(ChatType.KCHATTYPETEMPC2CFROMGROUP, msg.senderUid); const ret = await this.core.apis.MsgApi.getTempChatInfo(ChatType.KCHATTYPETEMPC2CFROMGROUP, msg.senderUid);
if (ret.result === 0) { if (ret.result === 0) {
resMsg.group_id = parseInt(ret.tmpChatInfo!.groupCode); resMsg.group_id = parseInt(ret.tmpChatInfo!.groupCode);
resMsg.sender.nickname = ret.tmpChatInfo!.fromNick; resMsg.sender.nickname = ret.tmpChatInfo!.fromNick;

View File

@@ -24,7 +24,7 @@ export class OB11Entities {
...rawFriend.coreInfo, ...rawFriend.coreInfo,
user_id: parseInt(rawFriend.coreInfo.uin), user_id: parseInt(rawFriend.coreInfo.uin),
nickname: rawFriend.coreInfo.nick, nickname: rawFriend.coreInfo.nick,
remark: rawFriend.coreInfo.nick, remark: rawFriend.coreInfo.remark ?? rawFriend.coreInfo.nick,
sex: this.sex(rawFriend.baseInfo.sex!), sex: this.sex(rawFriend.baseInfo.sex!),
level: 0, level: 0,
})); }));
@@ -109,7 +109,7 @@ export class OB11Entities {
static file(peerId: string, file: Exclude<GroupFileInfoUpdateParamType['item'][0]['fileInfo'], undefined>): OB11GroupFile { static file(peerId: string, file: Exclude<GroupFileInfoUpdateParamType['item'][0]['fileInfo'], undefined>): OB11GroupFile {
return { return {
group_id: parseInt(peerId), group_id: parseInt(peerId),
file_id: FileNapCatOneBotUUID.encodeModelId({ chatType: 2, peerUid: peerId }, file.fileModelId), file_id: FileNapCatOneBotUUID.encodeModelId({ chatType: 2, peerUid: peerId }, file.fileModelId, file.fileId),
file_name: file.fileName, file_name: file.fileName,
busid: file.busId, busid: file.busId,
size: parseInt(file.fileSize), size: parseInt(file.fileSize),

View File

@@ -77,7 +77,6 @@ export class NapCatOneBot11Adapter {
} }
async InitOneBot() { async InitOneBot() {
const NTQQUserApi = this.core.apis.UserApi;
const selfInfo = this.core.selfInfo; const selfInfo = this.core.selfInfo;
const ob11Config = this.configLoader.configData; const ob11Config = this.configLoader.configData;
@@ -87,7 +86,7 @@ export class NapCatOneBot11Adapter {
WebSocket服务 ${ob11Config.ws.enable ? '已启动' : '未启动'}, ${ob11Config.ws.host}:${ob11Config.ws.port} WebSocket服务 ${ob11Config.ws.enable ? '已启动' : '未启动'}, ${ob11Config.ws.host}:${ob11Config.ws.port}
WebSocket反向服务 ${ob11Config.reverseWs.enable ? '已启动' : '未启动'}, 反向地址: ${ob11Config.reverseWs.urls}`; WebSocket反向服务 ${ob11Config.reverseWs.enable ? '已启动' : '未启动'}, 反向地址: ${ob11Config.reverseWs.urls}`;
NTQQUserApi.getUserDetailInfo(selfInfo.uid).then(user => { this.core.apis.UserApi.getUserDetailInfo(selfInfo.uid).then(user => {
selfInfo.nick = user.nick; selfInfo.nick = user.nick;
this.context.logger.setLogSelfInfo(selfInfo); this.context.logger.setLogSelfInfo(selfInfo);
}).catch(this.context.logger.logError); }).catch(this.context.logger.logError);
@@ -243,31 +242,31 @@ export class NapCatOneBot11Adapter {
const msgListener = new NodeIKernelMsgListener(); const msgListener = new NodeIKernelMsgListener();
msgListener.onRecvSysMsg = async msg => { msgListener.onRecvSysMsg = async msg => {
const sysMsg = SysMessage.fromBinary(Uint8Array.from(msg)); // const sysMsg = SysMessage.fromBinary(Uint8Array.from(msg));
if (sysMsg.msgSpec.length === 0) { // if (sysMsg.msgSpec.length === 0) {
return; // return;
} // }
const { msgType, subType, subSubType } = sysMsg.msgSpec[0]; // const { msgType, subType, subSubType } = sysMsg.msgSpec[0];
if (msgType === 732 && subType === 16 && subSubType === 16) { // if (msgType === 732 && subType === 16 && subSubType === 16) {
const greyTip = GreyTipWrapper.fromBinary(Uint8Array.from(sysMsg.bodyWrapper!.wrappedBody.slice(7))); // const greyTip = GreyTipWrapper.fromBinary(Uint8Array.from(sysMsg.bodyWrapper!.wrappedBody.slice(7)));
if (greyTip.subTypeId === 36) { // if (greyTip.subTypeId === 36) {
const emojiLikeToOthers = EmojiLikeToOthersWrapper1 // const emojiLikeToOthers = EmojiLikeToOthersWrapper1
.fromBinary(greyTip.rest) // .fromBinary(greyTip.rest)
.wrapper! // .wrapper!
.body!; // .body!;
if (emojiLikeToOthers.attributes?.operation !== 1) { // Un-like // if (emojiLikeToOthers.attributes?.operation !== 1) { // Un-like
return; // return;
} // }
const eventOrEmpty = await this.apis.GroupApi.createGroupEmojiLikeEvent( // const eventOrEmpty = await this.apis.GroupApi.createGroupEmojiLikeEvent(
greyTip.groupCode.toString(), // greyTip.groupCode.toString(),
await this.core.apis.UserApi.getUinByUidV2(emojiLikeToOthers.attributes!.senderUid), // await this.core.apis.UserApi.getUinByUidV2(emojiLikeToOthers.attributes!.senderUid),
emojiLikeToOthers.msgSpec!.msgSeq.toString(), // emojiLikeToOthers.msgSpec!.msgSeq.toString(),
emojiLikeToOthers.attributes!.emojiId, // emojiLikeToOthers.attributes!.emojiId,
); // );
// eslint-disable-next-line @typescript-eslint/no-unused-expressions // // eslint-disable-next-line @typescript-eslint/no-unused-expressions
eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty); // eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty);
} // }
} // }
}; };
msgListener.onInputStatusPush = async data => { msgListener.onInputStatusPush = async data => {
@@ -341,12 +340,6 @@ export class NapCatOneBot11Adapter {
this.core.apis.FriendApi.clearBuddyReqUnreadCnt(); this.core.apis.FriendApi.clearBuddyReqUnreadCnt();
for (let i = 0; i < reqs.unreadNums; i++) { for (let i = 0; i < reqs.unreadNums; i++) {
const req = reqs.buddyReqs[i]; const req = reqs.buddyReqs[i];
//req.isBuddy === false是单向好友 null为常规情况
// if (req.isBuddy === false && ) {
// const NTQQFriendApi = this.core.apis.FriendApi;
// await NTQQFriendApi.handleFriendRequest(req.friendUid + '|' + req.reqTime, true);
// }
if (!!req.isInitiator || (req.isDecide && req.reqType !== BuddyReqType.KMEINITIATORWAITPEERCONFIRM)) { if (!!req.isInitiator || (req.isDecide && req.reqType !== BuddyReqType.KMEINITIATORWAITPEERCONFIRM)) {
continue; continue;
} }

View File

@@ -131,23 +131,24 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
private async handleMessage(message: any) { private async handleMessage(message: any) {
let receiveData: { action: ActionName, params?: any, echo?: any } = { action: ActionName.Unknown, params: {} }; let receiveData: { action: ActionName, params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
let echo = undefined; let echo = undefined;
try { try {
try { receiveData = JSON.parse(message.toString());
receiveData = JSON.parse(message.toString()); echo = receiveData.echo;
echo = receiveData.echo; this.logger.logDebug('[OneBot] [WebSocket Client] 收到正向Websocket消息', receiveData);
this.logger.logDebug('[OneBot] [WebSocket Client] 收到正向Websocket消息', receiveData);
} catch (e) {
this.checkStateAndReply<any>(OB11Response.error('json解析失败,请检查数据格式', 1400, echo));
return;
}
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
const retdata = await this.actions.get(receiveData.action)
?.websocketHandle(receiveData.params, echo ?? '');
const packet = Object.assign({}, retdata);
this.checkStateAndReply<any>(packet);
} catch (e) { } catch (e) {
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', e); this.checkStateAndReply<any>(OB11Response.error('json解析失败,请检查数据格式', 1400, echo));
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo)); return;
} }
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
const action = this.actions.get(receiveData.action);
if (!action) {
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo));
return;
}
const retdata = await action?.websocketHandle(receiveData.params, echo ?? '');
const packet = Object.assign({}, retdata);
this.checkStateAndReply<any>(packet);
} }
} }

View File

@@ -146,22 +146,23 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
let receiveData: { action: ActionName, params?: any, echo?: any } = { action: ActionName.Unknown, params: {} }; let receiveData: { action: ActionName, params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
let echo = undefined; let echo = undefined;
try { try {
try { receiveData = JSON.parse(message.toString());
receiveData = JSON.parse(message.toString()); echo = receiveData.echo;
echo = receiveData.echo; //this.logger.logDebug('收到正向Websocket消息', receiveData);
//this.logger.logDebug('收到正向Websocket消息', receiveData);
} catch (e) {
this.checkStateAndReply<any>(OB11Response.error('json解析失败,请检查数据格式', 1400, echo), wsClient);
return;
}
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
const retdata = await this.actions.get(receiveData.action)?.websocketHandle(receiveData.params, echo ?? '');
const packet = Object.assign({}, retdata);
this.checkStateAndReply<any>(packet, wsClient);
} catch (e) { } catch (e) {
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo), wsClient); this.checkStateAndReply<any>(OB11Response.error('json解析失败,请检查数据格式', 1400, echo), wsClient);
return;
} }
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
const action = this.actions.get(receiveData.action);
if (!action) {
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo), wsClient);
return;
}
const retdata = await action.websocketHandle(receiveData.params, echo ?? '');
const packet = Object.assign({}, retdata);
this.checkStateAndReply<any>(packet, wsClient);
} }
} }

View File

@@ -8,6 +8,7 @@ export enum OB11MessageType {
} }
export interface OB11Message { export interface OB11Message {
message_sent_type?: string;
target_id?: number; // 自己发送的消息才有此字段 target_id?: number; // 自己发送的消息才有此字段
self_id?: number, self_id?: number,
time: number, time: number,

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.2.29', 'napcat-update-button', 'secondary'), SettingButton('V2.2.41', '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.2.29", "napcat-update-button", "secondary") SettingButton("V2.2.41", "napcat-update-button", "secondary")
) )
]), ]),
SettingList([ SettingList([