mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9c34f558d3 | ||
![]() |
3e2da3b490 | ||
![]() |
fb4a4f50be | ||
![]() |
6596e9cab6 | ||
![]() |
f1b137f2e1 | ||
![]() |
535720d0fe | ||
![]() |
f063cf4a16 | ||
![]() |
90bbdbf2fe | ||
![]() |
5f1d8fb99d | ||
![]() |
5486ffcdcc | ||
![]() |
adfd123970 | ||
![]() |
f1a364bfa2 | ||
![]() |
9da714bf15 | ||
![]() |
fc73295520 | ||
![]() |
ab955e41fb | ||
![]() |
c64367335c | ||
![]() |
edc787eb3e | ||
![]() |
f2c69fc68b | ||
![]() |
d947fe743b | ||
![]() |
5b37ae9026 | ||
![]() |
ec9e042b29 | ||
![]() |
337ac0eab9 | ||
![]() |
f6a1b784c4 | ||
![]() |
332fcecb78 | ||
![]() |
18590be1e7 | ||
![]() |
b76edcaf1d | ||
![]() |
96457bbec3 | ||
![]() |
a20a6bc8bb | ||
![]() |
f81b1926fb | ||
![]() |
670d4108e6 | ||
![]() |
a5c7b88a40 | ||
![]() |
e52b2e6d69 | ||
![]() |
e4066fb8df | ||
![]() |
f7a0fb22b4 | ||
![]() |
cad2ae723c | ||
![]() |
889a8c6093 | ||
![]() |
573418914f | ||
![]() |
d7fb6f9c05 | ||
![]() |
d5ff2d7099 | ||
![]() |
2a7f8d0c99 |
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "2.2.8",
|
"version": "2.2.11",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.2.8",
|
"version": "2.2.11",
|
||||||
"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",
|
||||||
|
@@ -68,7 +68,7 @@ export class LegacyNTEventWrapper {
|
|||||||
const existListener = this.listenerManager.get(listenerMainName + uniqueCode);
|
const existListener = this.listenerManager.get(listenerMainName + uniqueCode);
|
||||||
if (!existListener) {
|
if (!existListener) {
|
||||||
const Listener = this.createProxyDispatch(listenerMainName);
|
const Listener = this.createProxyDispatch(listenerMainName);
|
||||||
const ServiceSubName = listenerMainName.match(/^NodeIKernel(.*?)Listener$/)![1];
|
const ServiceSubName = /^NodeIKernel(.*?)Listener$/.exec(listenerMainName)![1];
|
||||||
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
|
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
|
||||||
const addfunc = this.createEventFunction<(listener: T) => number>(Service);
|
const addfunc = this.createEventFunction<(listener: T) => number>(Service);
|
||||||
addfunc!(Listener as T);
|
addfunc!(Listener as T);
|
||||||
@@ -95,21 +95,10 @@ export class LegacyNTEventWrapper {
|
|||||||
|
|
||||||
async callNoListenerEvent<EventType extends (...args: any[]) => Promise<any> | any>(
|
async callNoListenerEvent<EventType extends (...args: any[]) => Promise<any> | any>(
|
||||||
EventName = '',
|
EventName = '',
|
||||||
timeout: number = 3000,
|
|
||||||
...args: Parameters<EventType>
|
...args: Parameters<EventType>
|
||||||
) {
|
): Promise<Awaited<ReturnType<EventType>>> {
|
||||||
return new Promise<Awaited<ReturnType<EventType>>>(async (resolve, reject) => {
|
const EventFunc = this.createEventFunction<EventType>(EventName);
|
||||||
const EventFunc = this.createEventFunction<EventType>(EventName);
|
return EventFunc!(...args);
|
||||||
let complete = false;
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!complete) {
|
|
||||||
reject(new Error('NTEvent EventName:' + EventName + ' timeout'));
|
|
||||||
}
|
|
||||||
}, timeout);
|
|
||||||
const retData = await EventFunc!(...args);
|
|
||||||
complete = true;
|
|
||||||
resolve(retData);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async RegisterListen<ListenerType extends (...args: any[]) => void>(
|
async RegisterListen<ListenerType extends (...args: any[]) => void>(
|
||||||
|
@@ -6,6 +6,7 @@ export type ListenerClassBase = Record<string, string>;
|
|||||||
export interface ListenerIBase {
|
export interface ListenerIBase {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||||
new(listener: any): ListenerClassBase;
|
new(listener: any): ListenerClassBase;
|
||||||
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NTEventChannel extends EventEmitter {
|
export class NTEventChannel extends EventEmitter {
|
||||||
@@ -26,12 +27,11 @@ export class NTEventChannel extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createProxyDispatch(ListenerMainName: string) {
|
createProxyDispatch(ListenerMainName: string) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
const dispatcherListener = this.dispatcherListener.bind(this);
|
||||||
const current = this;
|
|
||||||
return new Proxy({}, {
|
return new Proxy({}, {
|
||||||
get(_target: any, prop: any, _receiver: any) {
|
get(_target: any, prop: any, _receiver: any) {
|
||||||
return (...args: any[]) => {
|
return (...args: any[]) => {
|
||||||
current.dispatcherListener.apply(current, [ListenerMainName + '/' + prop, ...args]);
|
dispatcherListener(ListenerMainName + '/' + prop, ...args);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -47,7 +47,7 @@ export class NTEventChannel extends EventEmitter {
|
|||||||
Listener = new ListenerType(this.createProxyDispatch(listenerMainName));
|
Listener = new ListenerType(this.createProxyDispatch(listenerMainName));
|
||||||
if (!Listener) throw new Error('Init Listener failed');
|
if (!Listener) throw new Error('Init Listener failed');
|
||||||
//实例化NTQQ Listener外包装
|
//实例化NTQQ Listener外包装
|
||||||
const ServiceSubName = listenerMainName.match(/^NodeIKernel(.*?)Listener$/)![1];
|
const ServiceSubName = /^NodeIKernel(.*?)Listener$/.exec(listenerMainName)![1];
|
||||||
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
|
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
|
||||||
const addfunc = this.createEventFunction<(listener: T) => number>(Service);
|
const addfunc = this.createEventFunction<(listener: T) => number>(Service);
|
||||||
//添加Listener到NTQQ
|
//添加Listener到NTQQ
|
||||||
|
@@ -2,7 +2,7 @@ import path, { dirname } from 'path';
|
|||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
export const napcat_version = '2.2.8';
|
export const napcat_version = '2.2.11';
|
||||||
|
|
||||||
export class NapCatPathWrapper {
|
export class NapCatPathWrapper {
|
||||||
binaryPath: string;
|
binaryPath: string;
|
||||||
|
@@ -15,23 +15,13 @@ export class LimitedHashTable<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set(key: K, value: V): void {
|
set(key: K, value: V): void {
|
||||||
// const isExist = this.keyToValue.get(key);
|
|
||||||
// if (isExist && isExist === value) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
this.keyToValue.set(key, value);
|
this.keyToValue.set(key, value);
|
||||||
this.valueToKey.set(value, key);
|
this.valueToKey.set(value, key);
|
||||||
while (this.keyToValue.size !== this.valueToKey.size) {
|
while (this.keyToValue.size !== this.valueToKey.size) {
|
||||||
//console.log('keyToValue.size !== valueToKey.size Error Atom');
|
|
||||||
this.keyToValue.clear();
|
this.keyToValue.clear();
|
||||||
this.valueToKey.clear();
|
this.valueToKey.clear();
|
||||||
}
|
}
|
||||||
// console.log('---------------');
|
|
||||||
// console.log(this.keyToValue);
|
|
||||||
// console.log(this.valueToKey);
|
|
||||||
// console.log('---------------');
|
|
||||||
while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) {
|
while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) {
|
||||||
//console.log(this.keyToValue.size > this.maxSize, this.valueToKey.size > this.maxSize);
|
|
||||||
const oldestKey = this.keyToValue.keys().next().value;
|
const oldestKey = this.keyToValue.keys().next().value;
|
||||||
this.valueToKey.delete(this.keyToValue.get(oldestKey)!);
|
this.valueToKey.delete(this.keyToValue.get(oldestKey)!);
|
||||||
this.keyToValue.delete(oldestKey);
|
this.keyToValue.delete(oldestKey);
|
||||||
@@ -101,17 +91,13 @@ class MessageUniqueWrapper {
|
|||||||
return ret.map((t) => t?.MsgId).filter((t) => t !== undefined);
|
return ret.map((t) => t?.MsgId).filter((t) => t !== undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
createMsg(peer: Peer, msgId: string): number | undefined {
|
createMsg(peer: Peer, msgId: string) {
|
||||||
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
||||||
const hash = crypto.createHash('md5').update(key).digest();
|
const hash = crypto.createHash('md5').update(key).digest();
|
||||||
//设置第一个bit为0 保证shortId为正数
|
//设置第一个bit为0 保证shortId为正数
|
||||||
hash[0] &= 0x7f;
|
hash[0] &= 0x7f;
|
||||||
const shortId = hash.readInt32BE(0);
|
const shortId = hash.readInt32BE(0);
|
||||||
//减少性能损耗
|
//减少性能损耗
|
||||||
// const isExist = this.msgIdMap.getKey(shortId);
|
|
||||||
// if (isExist && isExist === msgId) {
|
|
||||||
// return shortId;
|
|
||||||
// }
|
|
||||||
this.msgIdMap.set(msgId, shortId);
|
this.msgIdMap.set(msgId, shortId);
|
||||||
this.msgDataMap.set(key, shortId);
|
this.msgDataMap.set(key, shortId);
|
||||||
return shortId;
|
return shortId;
|
||||||
|
@@ -4,7 +4,7 @@ import crypto, { randomUUID } from 'crypto';
|
|||||||
import util from 'util';
|
import util from 'util';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import * as fileType from 'file-type';
|
import * as fileType from 'file-type';
|
||||||
import { solveAsyncProblem, solveProblem } from './helper';
|
import { solveProblem } from './helper';
|
||||||
|
|
||||||
export function isGIF(path: string) {
|
export function isGIF(path: string) {
|
||||||
const buffer = Buffer.alloc(4);
|
const buffer = Buffer.alloc(4);
|
||||||
@@ -194,7 +194,7 @@ export async function checkUriType(Uri: string) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}, Uri);
|
}, Uri);
|
||||||
if (LocalFileRet) return LocalFileRet;
|
if (LocalFileRet) return LocalFileRet;
|
||||||
|
|
||||||
const OtherFileRet = await solveProblem((uri: string) => {
|
const OtherFileRet = await solveProblem((uri: string) => {
|
||||||
//再判断是否是Http
|
//再判断是否是Http
|
||||||
if (uri.startsWith('http://') || uri.startsWith('https://')) {
|
if (uri.startsWith('http://') || uri.startsWith('https://')) {
|
||||||
@@ -217,7 +217,7 @@ export async function checkUriType(Uri: string) {
|
|||||||
}
|
}
|
||||||
}, Uri);
|
}, Uri);
|
||||||
if (OtherFileRet) return OtherFileRet;
|
if (OtherFileRet) return OtherFileRet;
|
||||||
|
|
||||||
return { Uri: Uri, Type: FileUriType.Unknown };
|
return { Uri: Uri, Type: FileUriType.Unknown };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,13 +15,12 @@ export async function solveProblem<T extends (...arg: any[]) => any>(func: T, ..
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function solveAsyncProblem<T extends (...args: any[]) => Promise<any>>(func: T, ...args: Parameters<T>): Promise<Awaited<ReturnType<T>> | undefined> {
|
export async function solveAsyncProblem<T extends (...args: any[]) => Promise<any>>(func: T, ...args: Parameters<T>): Promise<Awaited<ReturnType<T>> | undefined> {
|
||||||
return new Promise<Awaited<ReturnType<T>> | undefined>(async (resolve) => {
|
return new Promise<Awaited<ReturnType<T>> | undefined>((resolve) => {
|
||||||
try {
|
func(...args).then((result) => {
|
||||||
const result = await func(...args);
|
|
||||||
resolve(result);
|
resolve(result);
|
||||||
} catch (e) {
|
}).catch((e) => {
|
||||||
resolve(undefined);
|
resolve(undefined);
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//下面这个类是用于将uid+msgid合并的类
|
//下面这个类是用于将uid+msgid合并的类
|
||||||
|
@@ -30,7 +30,7 @@ export async function getMachineId(): Promise<string> {
|
|||||||
if (!machineId) {
|
if (!machineId) {
|
||||||
machineId = (async () => {
|
machineId = (async () => {
|
||||||
const id = await getMacMachineId();
|
const id = await getMacMachineId();
|
||||||
return id || randomUUID(); // fallback, generate a UUID
|
return id ?? randomUUID(); // fallback, generate a UUID
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,11 +24,11 @@ export async function getVideoInfo(filePath: string, logger: LogWrapper) {
|
|||||||
if (videoStream) {
|
if (videoStream) {
|
||||||
logger.log(`视频尺寸: ${videoStream.width}x${videoStream.height}`);
|
logger.log(`视频尺寸: ${videoStream.width}x${videoStream.height}`);
|
||||||
} else {
|
} else {
|
||||||
return reject('未找到视频流信息。');
|
return reject(new Error('未找到视频流信息。'));
|
||||||
}
|
}
|
||||||
resolve({
|
resolve({
|
||||||
width: videoStream.width!, height: videoStream.height!,
|
width: videoStream.width!, height: videoStream.height!,
|
||||||
time: parseInt(videoStream.duration!),
|
time: +(videoStream.duration ?? 10),
|
||||||
format: metadata.format.format_name!,
|
format: metadata.format.format_name!,
|
||||||
size,
|
size,
|
||||||
filePath,
|
filePath,
|
||||||
@@ -38,7 +38,7 @@ export async function getVideoInfo(filePath: string, logger: LogWrapper) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkFfmpeg(newPath: string | null = null, logger: LogWrapper): Promise<boolean> {
|
export function checkFfmpeg(logger: LogWrapper,newPath: string | null = null): Promise<boolean> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
logger.log('开始检查ffmpeg', newPath);
|
logger.log('开始检查ffmpeg', newPath);
|
||||||
if (newPath) {
|
if (newPath) {
|
||||||
|
@@ -1,17 +1,4 @@
|
|||||||
interface IDependsAdapter {
|
export class NodeIDependsAdapter {
|
||||||
onMSFStatusChange(arg1: number, arg2: number): void;
|
|
||||||
|
|
||||||
onMSFSsoError(args: unknown): void;
|
|
||||||
|
|
||||||
getGroupCode(args: unknown): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIDependsAdapter extends IDependsAdapter {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IDependsAdapter): NodeIDependsAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DependsAdapter implements IDependsAdapter {
|
|
||||||
onMSFStatusChange(arg1: number, arg2: number) {
|
onMSFStatusChange(arg1: number, arg2: number) {
|
||||||
// console.log(arg1, arg2);
|
// console.log(arg1, arg2);
|
||||||
// if (arg1 == 2 && arg2 == 2) {
|
// if (arg1 == 2 && arg2 == 2) {
|
||||||
|
@@ -1,17 +1,4 @@
|
|||||||
interface IDispatcherAdapter {
|
export class NodeIDispatcherAdapter {
|
||||||
dispatchRequest(arg: unknown): void;
|
|
||||||
|
|
||||||
dispatchCall(arg: unknown): void;
|
|
||||||
|
|
||||||
dispatchCallWithJson(arg: unknown): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIDispatcherAdapter extends IDispatcherAdapter {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IDispatcherAdapter): NodeIDispatcherAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DispatcherAdapter implements IDispatcherAdapter {
|
|
||||||
dispatchRequest(arg: unknown) {
|
dispatchRequest(arg: unknown) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,27 +1,4 @@
|
|||||||
interface IGlobalAdapter {
|
export class NodeIGlobalAdapter {
|
||||||
onLog(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGetSrvCalTime(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onShowErrUITips(...args: unknown[]): void;
|
|
||||||
|
|
||||||
fixPicImgType(...args: unknown[]): void;
|
|
||||||
|
|
||||||
getAppSetting(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onInstallFinished(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onUpdateGeneralFlag(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGetOfflineMsg(...args: unknown[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIGlobalAdapter extends IGlobalAdapter {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IGlobalAdapter): NodeIGlobalAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GlobalAdapter implements IGlobalAdapter {
|
|
||||||
onLog(...args: unknown[]) {
|
onLog(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,6 +8,11 @@ import {
|
|||||||
IMAGE_HTTP_HOST_NT,
|
IMAGE_HTTP_HOST_NT,
|
||||||
Peer,
|
Peer,
|
||||||
PicElement,
|
PicElement,
|
||||||
|
PicType,
|
||||||
|
SendFileElement,
|
||||||
|
SendPicElement,
|
||||||
|
SendPttElement,
|
||||||
|
SendVideoElement,
|
||||||
} from '@/core/entities';
|
} from '@/core/entities';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
@@ -18,7 +23,12 @@ import imageSize from 'image-size';
|
|||||||
import { ISizeCalculationResult } from 'image-size/dist/types/interface';
|
import { ISizeCalculationResult } from 'image-size/dist/types/interface';
|
||||||
import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService';
|
import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService';
|
||||||
import { RkeyManager } from '../helper/rkey';
|
import { RkeyManager } from '../helper/rkey';
|
||||||
import { calculateFileMD5 } from '@/common/utils/file';
|
import { calculateFileMD5, isGIF } from '@/common/utils/file';
|
||||||
|
import pathLib from 'node:path';
|
||||||
|
import { defaultVideoThumbB64, getVideoInfo } from '@/common/utils/video';
|
||||||
|
import ffmpeg from 'fluent-ffmpeg';
|
||||||
|
import fsnormal from 'node:fs';
|
||||||
|
import { encodeSilk } from '@/common/utils/audio';
|
||||||
|
|
||||||
|
|
||||||
export class NTQQFileApi {
|
export class NTQQFileApi {
|
||||||
@@ -84,6 +94,198 @@ export class NTQQFileApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createValidSendFileElement(
|
||||||
|
filePath: string,
|
||||||
|
fileName: string = '',
|
||||||
|
folderId: string = ''
|
||||||
|
): Promise<SendFileElement> {
|
||||||
|
const { fileName: _fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.FILE);
|
||||||
|
if (fileSize === 0) {
|
||||||
|
throw new Error('文件异常,大小为0');
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
elementType: ElementType.FILE,
|
||||||
|
elementId: '',
|
||||||
|
fileElement: {
|
||||||
|
fileName: fileName || _fileName,
|
||||||
|
folderId: folderId,
|
||||||
|
filePath: path,
|
||||||
|
fileSize: (fileSize).toString(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async createValidSendPicElement(
|
||||||
|
picPath: string,
|
||||||
|
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) {
|
||||||
|
throw new Error('文件异常,大小为0');
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
elementType: ElementType.PIC,
|
||||||
|
elementId: '',
|
||||||
|
picElement,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async createValidSendVideoElement(
|
||||||
|
filePath: string,
|
||||||
|
fileName: string = '',
|
||||||
|
diyThumbPath: string = '',
|
||||||
|
): Promise<SendVideoElement> {
|
||||||
|
const logger = this.core.context.logger;
|
||||||
|
const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
|
||||||
|
if (fileSize === 0) {
|
||||||
|
throw new Error('文件异常,大小为0');
|
||||||
|
}
|
||||||
|
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
|
||||||
|
thumb = pathLib.dirname(thumb);
|
||||||
|
let videoInfo = {
|
||||||
|
width: 1920, height: 1080,
|
||||||
|
time: 15,
|
||||||
|
format: 'mp4',
|
||||||
|
size: fileSize,
|
||||||
|
filePath,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
videoInfo = await getVideoInfo(path, logger);
|
||||||
|
} catch (e) {
|
||||||
|
logger.logError('获取视频信息失败', e);
|
||||||
|
}
|
||||||
|
const createThumb = new Promise<string | undefined>((resolve, reject) => {
|
||||||
|
const thumbFileName = `${md5}_0.png`;
|
||||||
|
const thumbPath = pathLib.join(thumb, thumbFileName);
|
||||||
|
ffmpeg(filePath)
|
||||||
|
.on('error', (err) => {
|
||||||
|
logger.logDebug('获取视频封面失败,使用默认封面', err);
|
||||||
|
if (diyThumbPath) {
|
||||||
|
fsPromises.copyFile(diyThumbPath, thumbPath).then(() => {
|
||||||
|
resolve(thumbPath);
|
||||||
|
}).catch(reject);
|
||||||
|
} else {
|
||||||
|
fsnormal.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64'));
|
||||||
|
resolve(thumbPath);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.screenshots({
|
||||||
|
timestamps: [0],
|
||||||
|
filename: thumbFileName,
|
||||||
|
folder: thumb,
|
||||||
|
size: videoInfo.width + 'x' + videoInfo.height,
|
||||||
|
}).on('end', () => {
|
||||||
|
resolve(thumbPath);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const thumbPath = new Map();
|
||||||
|
const _thumbPath = await createThumb;
|
||||||
|
const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0;
|
||||||
|
// log("生成缩略图", _thumbPath)
|
||||||
|
thumbPath.set(0, _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 {
|
||||||
|
elementType: ElementType.VIDEO,
|
||||||
|
elementId: '',
|
||||||
|
videoElement: {
|
||||||
|
fileName: fileName || _fileName,
|
||||||
|
filePath: path,
|
||||||
|
videoMd5: md5,
|
||||||
|
thumbMd5,
|
||||||
|
fileTime: videoInfo.time,
|
||||||
|
thumbPath: thumbPath,
|
||||||
|
thumbSize,
|
||||||
|
thumbWidth: videoInfo.width,
|
||||||
|
thumbHeight: videoInfo.height,
|
||||||
|
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> {
|
||||||
|
const {
|
||||||
|
converted,
|
||||||
|
path: silkPath,
|
||||||
|
duration,
|
||||||
|
} = await encodeSilk(pttPath, this.core.NapCatTempPath, this.core.context.logger);
|
||||||
|
// 生成语音 Path: silkPath Time: duration
|
||||||
|
if (!silkPath) {
|
||||||
|
throw new Error('语音转换失败, 请检查语音文件是否正常');
|
||||||
|
}
|
||||||
|
const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(silkPath, ElementType.PTT);
|
||||||
|
if (fileSize === 0) {
|
||||||
|
throw new Error('文件异常,大小为0');
|
||||||
|
}
|
||||||
|
if (converted) {
|
||||||
|
fsPromises.unlink(silkPath);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
elementType: ElementType.PTT,
|
||||||
|
elementId: '',
|
||||||
|
pttElement: {
|
||||||
|
fileName: fileName,
|
||||||
|
filePath: path,
|
||||||
|
md5HexStr: md5,
|
||||||
|
fileSize: fileSize,
|
||||||
|
// duration: Math.max(1, Math.round(fileSize / 1024 / 3)), // 一秒钟大概是3kb大小, 小于1秒的按1秒算
|
||||||
|
duration: duration ?? 1,
|
||||||
|
formatType: 1,
|
||||||
|
voiceType: 1,
|
||||||
|
voiceChangeType: 0,
|
||||||
|
canConvert2Text: true,
|
||||||
|
waveAmplitudes: [
|
||||||
|
0, 18, 9, 23, 16, 17, 16, 15, 44, 17, 24, 20, 14, 15, 17,
|
||||||
|
],
|
||||||
|
fileSubId: '',
|
||||||
|
playState: 1,
|
||||||
|
autoConvertText: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async downloadMediaByUuid() {
|
async downloadMediaByUuid() {
|
||||||
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
|
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
|
||||||
}
|
}
|
||||||
@@ -157,9 +359,9 @@ export class NTQQFileApi {
|
|||||||
}
|
}
|
||||||
//从原始消息获取文件路径
|
//从原始消息获取文件路径
|
||||||
const filePath =
|
const filePath =
|
||||||
FileElements?.fileElement?.filePath ||
|
FileElements?.fileElement?.filePath ??
|
||||||
FileElements?.pttElement?.filePath ||
|
FileElements?.pttElement?.filePath ??
|
||||||
FileElements?.videoElement?.filePath ||
|
FileElements?.videoElement?.filePath ??
|
||||||
FileElements?.picElement?.sourcePath;
|
FileElements?.picElement?.sourcePath;
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
@@ -317,7 +519,7 @@ export class NTQQFileApi {
|
|||||||
}
|
}
|
||||||
} else if (fileMd5 || md5HexStr) {
|
} else if (fileMd5 || md5HexStr) {
|
||||||
// 没有url,需要自己拼接
|
// 没有url,需要自己拼接
|
||||||
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 || md5HexStr)!.toUpperCase()}/0`;
|
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`;
|
||||||
}
|
}
|
||||||
this.context.logger.logDebug('图片url获取失败', element);
|
this.context.logger.logDebug('图片url获取失败', element);
|
||||||
return '';
|
return '';
|
||||||
|
@@ -21,7 +21,7 @@ export class NTQQFriendApi {
|
|||||||
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));
|
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids));
|
||||||
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
||||||
'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids,
|
'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids,
|
||||||
);
|
);
|
||||||
return Array.from(data.values());
|
return Array.from(data.values());
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ export class NTQQFriendApi {
|
|||||||
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));
|
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids));
|
||||||
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
||||||
'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids,
|
'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids,
|
||||||
);
|
);
|
||||||
data.forEach((value, key) => {
|
data.forEach((value, key) => {
|
||||||
retMap.set(value.uin!, value.uid!);
|
retMap.set(value.uin!, value.uid!);
|
||||||
@@ -55,7 +55,7 @@ export class NTQQFriendApi {
|
|||||||
return item.buddyUids;
|
return item.buddyUids;
|
||||||
}));
|
}));
|
||||||
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
||||||
'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids,
|
'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids,
|
||||||
);
|
);
|
||||||
return buddyListV2.map(category => ({
|
return buddyListV2.map(category => ({
|
||||||
categoryId: category.categoryId,
|
categoryId: category.categoryId,
|
||||||
|
@@ -7,8 +7,7 @@ import {
|
|||||||
GroupNotify,
|
GroupNotify,
|
||||||
GroupRequestOperateTypes,
|
GroupRequestOperateTypes,
|
||||||
InstanceContext,
|
InstanceContext,
|
||||||
KickMemberInfo,
|
KickMemberV2Req,
|
||||||
kickMemberV2Req,
|
|
||||||
MemberExtSourceType,
|
MemberExtSourceType,
|
||||||
NapCatCore,
|
NapCatCore,
|
||||||
NodeIKernelGroupListener,
|
NodeIKernelGroupListener,
|
||||||
@@ -223,7 +222,7 @@ export class NTQQGroupApi {
|
|||||||
// GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
|
// GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
|
||||||
return this.context.session.getGroupService().addGroupEssence(param);
|
return this.context.session.getGroupService().addGroupEssence(param);
|
||||||
}
|
}
|
||||||
async kickMemberV2Inner(param: kickMemberV2Req) {
|
async kickMemberV2Inner(param: KickMemberV2Req) {
|
||||||
return this.context.session.getGroupService().kickMemberV2(param);
|
return this.context.session.getGroupService().kickMemberV2(param);
|
||||||
}
|
}
|
||||||
async deleteGroupBulletin(GroupCode: string, feedId: string) {
|
async deleteGroupBulletin(GroupCode: string, feedId: string) {
|
||||||
@@ -332,7 +331,6 @@ export class NTQQGroupApi {
|
|||||||
arkJson: string
|
arkJson: string
|
||||||
}>>(
|
}>>(
|
||||||
'NodeIKernelGroupService/getGroupRecommendContactArkJson',
|
'NodeIKernelGroupService/getGroupRecommendContactArkJson',
|
||||||
5000,
|
|
||||||
GroupCode,
|
GroupCode,
|
||||||
);
|
);
|
||||||
return ret.arkJson;
|
return ret.arkJson;
|
||||||
@@ -358,7 +356,7 @@ export class NTQQGroupApi {
|
|||||||
'seq': seq, // 通知序列号
|
'seq': seq, // 通知序列号
|
||||||
'type': type,
|
'type': type,
|
||||||
'groupCode': groupCode,
|
'groupCode': groupCode,
|
||||||
'postscript': reason || ' ', // 仅传空值可能导致处理失败,故默认给个空格
|
'postscript': reason ?? ' ', // 仅传空值可能导致处理失败,故默认给个空格
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement, SendStatusType } from '@/core/entities';
|
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement, SendStatusType } from '@/core/entities';
|
||||||
import { InstanceContext, NapCatCore } from '@/core';
|
import { InstanceContext, NapCatCore } from '@/core';
|
||||||
import { onGroupFileInfoUpdateParamType } from '@/core/listeners';
|
import { GroupFileInfoUpdateParamType } from '@/core/listeners';
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
|
|
||||||
export class NTQQMsgApi {
|
export class NTQQMsgApi {
|
||||||
@@ -119,13 +119,13 @@ export class NTQQMsgApi {
|
|||||||
async getGroupFileList(GroupCode: string, params: GetFileListParam) {
|
async getGroupFileList(GroupCode: string, params: GetFileListParam) {
|
||||||
const data = await this.core.eventWrapper.CallNormalEvent<
|
const data = await this.core.eventWrapper.CallNormalEvent<
|
||||||
(GroupCode: string, params: GetFileListParam) => Promise<unknown>,
|
(GroupCode: string, params: GetFileListParam) => Promise<unknown>,
|
||||||
(groupFileListResult: onGroupFileInfoUpdateParamType) => void
|
(groupFileListResult: GroupFileInfoUpdateParamType) => void
|
||||||
>(
|
>(
|
||||||
'NodeIKernelRichMediaService/getGroupFileList',
|
'NodeIKernelRichMediaService/getGroupFileList',
|
||||||
'NodeIKernelMsgListener/onGroupFileInfoUpdate',
|
'NodeIKernelMsgListener/onGroupFileInfoUpdate',
|
||||||
1,
|
1,
|
||||||
5000,
|
5000,
|
||||||
(groupFileListResult: onGroupFileInfoUpdateParamType) => {
|
(groupFileListResult: GroupFileInfoUpdateParamType) => {
|
||||||
//Developer Mlikiowa Todo: 此处有问题 无法判断是否成功
|
//Developer Mlikiowa Todo: 此处有问题 无法判断是否成功
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
@@ -251,7 +251,7 @@ export class NTQQMsgApi {
|
|||||||
if (!arkElement) {
|
if (!arkElement) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const forwardData: any = JSON.parse(arkElement.arkElement?.bytesData || "");
|
const forwardData: any = JSON.parse(arkElement.arkElement?.bytesData ?? "");
|
||||||
if (forwardData.app != 'com.tencent.multimsg') {
|
if (forwardData.app != 'com.tencent.multimsg') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@@ -2,77 +2,6 @@ import { RequestUtil } from '@/common/utils/request';
|
|||||||
import { MiniAppLuaJsonType } from '@/core';
|
import { MiniAppLuaJsonType } from '@/core';
|
||||||
import { InstanceContext, NapCatCore } from '..';
|
import { InstanceContext, NapCatCore } from '..';
|
||||||
|
|
||||||
// let t = await napCatCore.session.getGroupService().shareDigest({
|
|
||||||
// appId: "100497308",
|
|
||||||
// appType: 1,
|
|
||||||
// msgStyle: 0,
|
|
||||||
// recvUin: "726067488",
|
|
||||||
// sendType: 1,
|
|
||||||
// clientInfo: {
|
|
||||||
// platform: 1
|
|
||||||
// },
|
|
||||||
// richMsg: {
|
|
||||||
// usingArk: true,
|
|
||||||
// title: "Bot测试title",
|
|
||||||
// summary: "Bot测试summary",
|
|
||||||
// url: "https://www.bilibili.com",
|
|
||||||
// pictureUrl: "https://y.qq.com/music/photo_new/T002R300x300M0000035DC6W4ZpSqf_1.jpg?max_age=2592000",
|
|
||||||
// brief: "Bot测试brief",
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// {
|
|
||||||
// errCode: 0,
|
|
||||||
// errMsg: '',
|
|
||||||
// rsp: {
|
|
||||||
// sendType: 1,
|
|
||||||
// recvUin: '726067488',
|
|
||||||
// recvOpenId: '',
|
|
||||||
// errCode: 901501,
|
|
||||||
// errMsg: 'imagent service_error:150_OIDB_NO_PRIV',
|
|
||||||
// extInfo: {
|
|
||||||
// wording: '消息下发失败(错误码:901501)',
|
|
||||||
// jumpResult: 0,
|
|
||||||
// jumpUrl: '',
|
|
||||||
// level: 0,
|
|
||||||
// subLevel: 0,
|
|
||||||
// developMsg: 'imagent error'
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export class MusicSign {
|
|
||||||
// private readonly url: string;
|
|
||||||
|
|
||||||
// constructor(url: string) {
|
|
||||||
// this.url = url;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// sign(postData: CustomMusicSignPostData | IdMusicSignPostData): Promise<any> {
|
|
||||||
// return new Promise((resolve, reject) => {
|
|
||||||
// fetch(this.url, {
|
|
||||||
// method: 'POST', // 指定请求方法为 POST
|
|
||||||
// headers: {
|
|
||||||
// 'Content-Type': 'application/json' // 设置请求头,指明发送的数据类型为 JSON
|
|
||||||
// },
|
|
||||||
// body: JSON.stringify(postData) // 将 JavaScript 对象转换为 JSON 字符串作为请求体
|
|
||||||
// })
|
|
||||||
// .then(response => {
|
|
||||||
// if (!response.ok) {
|
|
||||||
// reject(response.statusText); // 请求失败,返回错误信息
|
|
||||||
// }
|
|
||||||
// return response.json(); // 解析 JSON 格式的响应体
|
|
||||||
// })
|
|
||||||
// .then(data => {
|
|
||||||
// logDebug('音乐消息生成成功', data);
|
|
||||||
// resolve(data);
|
|
||||||
// })
|
|
||||||
// .catch(error => {
|
|
||||||
// reject(error);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
export class NTQQMusicSignApi {
|
export class NTQQMusicSignApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
core: NapCatCore;
|
core: NapCatCore;
|
||||||
|
@@ -32,7 +32,6 @@ export class NTQQSystemApi {
|
|||||||
arkJson: string
|
arkJson: string
|
||||||
}>>(
|
}>>(
|
||||||
'NodeIKernelCollectionService/collectionArkShare',
|
'NodeIKernelCollectionService/collectionArkShare',
|
||||||
5000,
|
|
||||||
'1717662698058',
|
'1717662698058',
|
||||||
);
|
);
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -129,7 +129,7 @@ export class NTQQUserApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getUserDetailInfo(uid: string): Promise<User> {
|
async getUserDetailInfo(uid: string): Promise<User> {
|
||||||
const retUser = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, UserDetailSource.KDB));
|
const retUser = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, UserDetailSource.KDB), uid);
|
||||||
if (retUser && retUser.uin !== '0') {
|
if (retUser && retUser.uin !== '0') {
|
||||||
return retUser;
|
return retUser;
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ export class NTQQUserApi {
|
|||||||
|
|
||||||
async getUserDetailInfoByUinV2(Uin: string) {
|
async getUserDetailInfoByUinV2(Uin: string) {
|
||||||
return await this.core.eventWrapper.callNoListenerEvent<(Uin: string) => Promise<UserDetailInfoByUinV2>>
|
return await this.core.eventWrapper.callNoListenerEvent<(Uin: string) => Promise<UserDetailInfoByUinV2>>
|
||||||
('NodeIKernelProfileService/getUserDetailInfoByUin', 5000, Uin);
|
('NodeIKernelProfileService/getUserDetailInfoByUin', Uin);
|
||||||
}
|
}
|
||||||
|
|
||||||
async forceFetchClientKey() {
|
async forceFetchClientKey() {
|
||||||
|
@@ -166,7 +166,7 @@ export class NTQQWebApi {
|
|||||||
let resJson;
|
let resJson;
|
||||||
try {
|
try {
|
||||||
const res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
const res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
||||||
const match = res.match(/window\.__INITIAL_STATE__=(.*?);/);
|
const match = /window\.__INITIAL_STATE__=(.*?);/.exec(res);
|
||||||
if (match) {
|
if (match) {
|
||||||
resJson = JSON.parse(match[1].trim());
|
resJson = JSON.parse(match[1].trim());
|
||||||
}
|
}
|
||||||
|
@@ -3,8 +3,8 @@ import path from 'node:path';
|
|||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import { InstanceContext } from './wrapper';
|
import { InstanceContext } from './wrapper';
|
||||||
import { proxiedListenerOf } from '@/common/utils/proxy-handler';
|
import { proxiedListenerOf } from '@/common/utils/proxy-handler';
|
||||||
import { GroupListener, MsgListener, ProfileListener } from './listeners';
|
import { NodeIKernelMsgListener, NodeIKernelGroupListener, NodeIKernelProfileListener } from './listeners';
|
||||||
import { GroupMember, SelfInfo } from './entities';
|
import { DataSource, GroupMember, SelfInfo } from './entities';
|
||||||
import { LegacyNTEventWrapper } from '@/common/framework/event-legacy';
|
import { LegacyNTEventWrapper } from '@/common/framework/event-legacy';
|
||||||
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from './apis';
|
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from './apis';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
@@ -89,7 +89,7 @@ export class NapCatCore {
|
|||||||
|
|
||||||
// Renamed from 'InitDataListener'
|
// Renamed from 'InitDataListener'
|
||||||
async initNapCatCoreListeners() {
|
async initNapCatCoreListeners() {
|
||||||
const msgListener = new MsgListener();
|
const msgListener = new NodeIKernelMsgListener();
|
||||||
msgListener.onRecvMsg = (msgs) => {
|
msgListener.onRecvMsg = (msgs) => {
|
||||||
msgs.forEach(msg => this.context.logger.logMessage(msg, this.selfInfo));
|
msgs.forEach(msg => this.context.logger.logMessage(msg, this.selfInfo));
|
||||||
};
|
};
|
||||||
@@ -101,7 +101,7 @@ export class NapCatCore {
|
|||||||
proxiedListenerOf(msgListener, this.context.logger) as any
|
proxiedListenerOf(msgListener, this.context.logger) as any
|
||||||
);
|
);
|
||||||
|
|
||||||
const profileListener = new ProfileListener();
|
const profileListener = new NodeIKernelProfileListener();
|
||||||
profileListener.onProfileDetailInfoChanged = (profile) => {
|
profileListener.onProfileDetailInfoChanged = (profile) => {
|
||||||
if (profile.uid === this.selfInfo.uid) {
|
if (profile.uid === this.selfInfo.uid) {
|
||||||
Object.assign(this.selfInfo, profile);
|
Object.assign(this.selfInfo, profile);
|
||||||
@@ -117,7 +117,7 @@ export class NapCatCore {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 群相关
|
// 群相关
|
||||||
const groupListener = new GroupListener();
|
const groupListener = new NodeIKernelGroupListener();
|
||||||
groupListener.onGroupListUpdate = (updateType, groupList) => {
|
groupListener.onGroupListUpdate = (updateType, groupList) => {
|
||||||
// console.log("onGroupListUpdate", updateType, groupList)
|
// console.log("onGroupListUpdate", updateType, groupList)
|
||||||
groupList.map(g => {
|
groupList.map(g => {
|
||||||
@@ -164,9 +164,9 @@ export class NapCatCore {
|
|||||||
}
|
}
|
||||||
// console.log('onMemberListChange', groupCode, arg);
|
// console.log('onMemberListChange', groupCode, arg);
|
||||||
};
|
};
|
||||||
groupListener.onMemberInfoChange = (groupCode, changeType, members) => {
|
groupListener.onMemberInfoChange = (groupCode, dataSource, members) => {
|
||||||
//console.log('onMemberInfoChange', groupCode, changeType, members);
|
//console.log('onMemberInfoChange', groupCode, changeType, members);
|
||||||
if (changeType === 0 && members.get(this.selfInfo.uid)?.isDelete) {
|
if (dataSource === DataSource.LOCAL && members.get(this.selfInfo.uid)?.isDelete) {
|
||||||
// 自身退群或者被踢退群 5s用于Api操作 之后不再出现
|
// 自身退群或者被踢退群 5s用于Api操作 之后不再出现
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.apis.GroupApi.groupCache.delete(groupCode);
|
this.apis.GroupApi.groupCache.delete(groupCode);
|
||||||
|
@@ -5,13 +5,17 @@ export interface KickMemberInfo {
|
|||||||
optMemberUid: string,
|
optMemberUid: string,
|
||||||
optBytesMsg: string,
|
optBytesMsg: string,
|
||||||
}
|
}
|
||||||
export interface kickMemberV2Req{
|
export interface KickMemberV2Req{
|
||||||
groupCode: string,
|
groupCode: string,
|
||||||
kickFlag: number,
|
kickFlag: number,
|
||||||
kickList: Array<KickMemberInfo>,
|
kickList: Array<KickMemberInfo>,
|
||||||
kickListUids: Array<string>,
|
kickListUids: Array<string>,
|
||||||
kickMsg: string
|
kickMsg: string
|
||||||
}
|
}
|
||||||
|
export enum DataSource {
|
||||||
|
LOCAL,
|
||||||
|
REMOTE
|
||||||
|
}
|
||||||
export enum GroupListUpdateType {
|
export enum GroupListUpdateType {
|
||||||
REFRESHALL,
|
REFRESHALL,
|
||||||
GETALL,
|
GETALL,
|
||||||
|
@@ -411,7 +411,7 @@ export interface ShareLocationElement {
|
|||||||
ext: string;
|
ext: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface sendShareLocationElement {
|
export interface SendShareLocationElement {
|
||||||
elementType: ElementType.SHARELOCATION;
|
elementType: ElementType.SHARELOCATION;
|
||||||
elementId: string;
|
elementId: string;
|
||||||
shareLocationElement?: ShareLocationElement;
|
shareLocationElement?: ShareLocationElement;
|
||||||
@@ -461,7 +461,7 @@ export interface SendMarkdownElement {
|
|||||||
|
|
||||||
export type SendMessageElement = SendTextElement | SendPttElement |
|
export type SendMessageElement = SendTextElement | SendPttElement |
|
||||||
SendPicElement | SendReplyElement | SendFaceElement | SendMarketFaceElement | SendFileElement |
|
SendPicElement | SendReplyElement | SendFaceElement | SendMarketFaceElement | SendFileElement |
|
||||||
SendVideoElement | SendArkElement | SendMarkdownElement | sendShareLocationElement;
|
SendVideoElement | SendArkElement | SendMarkdownElement | SendShareLocationElement;
|
||||||
|
|
||||||
export interface TextElement {
|
export interface TextElement {
|
||||||
content: string;
|
content: string;
|
||||||
|
@@ -1,53 +1,9 @@
|
|||||||
import { BuddyCategoryType, FriendRequestNotify } from '@/core/entities';
|
import { BuddyCategoryType, FriendRequestNotify } from '@/core/entities';
|
||||||
|
|
||||||
export type OnBuddyChangeParams = BuddyCategoryType[]
|
export type OnBuddyChangeParams = BuddyCategoryType[];
|
||||||
|
|
||||||
interface IBuddyListener {
|
export class NodeIKernelBuddyListener {
|
||||||
onBuddyListChangedV2(arg: unknown): void,//V2版本 还没兼容
|
|
||||||
|
|
||||||
onBuddyListChange(arg: OnBuddyChangeParams): void,
|
|
||||||
|
|
||||||
onBuddyInfoChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onBuddyDetailInfoChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onNickUpdated(arg: unknown): void,
|
|
||||||
|
|
||||||
onBuddyRemarkUpdated(arg: unknown): void,
|
|
||||||
|
|
||||||
onAvatarUrlUpdated(arg: unknown): void,
|
|
||||||
|
|
||||||
onBuddyReqChange(arg: FriendRequestNotify): void,
|
|
||||||
|
|
||||||
onBuddyReqUnreadCntChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onCheckBuddySettingResult(arg: unknown): void,
|
|
||||||
|
|
||||||
onAddBuddyNeedVerify(arg: unknown): void,
|
|
||||||
|
|
||||||
onSmartInfos(arg: unknown): void,
|
|
||||||
|
|
||||||
onSpacePermissionInfos(arg: unknown): void,
|
|
||||||
|
|
||||||
onDoubtBuddyReqChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onDoubtBuddyReqUnreadNumChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onBlockChanged(arg: unknown): void,
|
|
||||||
|
|
||||||
onAddMeSettingChanged(arg: unknown): void,
|
|
||||||
|
|
||||||
onDelBatchBuddyInfos(arg: unknown): void
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelBuddyListener extends IBuddyListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IBuddyListener): NodeIKernelBuddyListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class BuddyListener implements IBuddyListener {
|
|
||||||
onBuddyListChangedV2(arg: unknown): void {
|
onBuddyListChangedV2(arg: unknown): void {
|
||||||
//throw new Error('Method not implemented.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onAddBuddyNeedVerify(arg: unknown) {
|
onAddBuddyNeedVerify(arg: unknown) {
|
||||||
|
@@ -1,21 +1,5 @@
|
|||||||
export interface IKernelFileAssistantListener {
|
|
||||||
onFileStatusChanged(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onSessionListChanged(...args: unknown[]): unknown;
|
export class NodeIKernelFileAssistantListener {
|
||||||
|
|
||||||
onSessionChanged(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onFileListChanged(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onFileSearch(...args: unknown[]): unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelFileAssistantListener extends IKernelFileAssistantListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IKernelFileAssistantListener): NodeIKernelFileAssistantListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class KernelFileAssistantListener implements IKernelFileAssistantListener {
|
|
||||||
onFileStatusChanged(...args: unknown[]) {
|
onFileStatusChanged(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,68 +1,6 @@
|
|||||||
import { Group, GroupListUpdateType, GroupMember, GroupNotify } from '@/core/entities';
|
import { DataSource, Group, GroupListUpdateType, GroupMember, GroupNotify } from '@/core/entities';
|
||||||
|
|
||||||
export interface IGroupListener {
|
export class NodeIKernelGroupListener {
|
||||||
onGroupListUpdate(updateType: GroupListUpdateType, groupList: Group[]): void;
|
|
||||||
|
|
||||||
onGroupExtListUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]): void;
|
|
||||||
|
|
||||||
onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]): void;
|
|
||||||
|
|
||||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupDetailInfoChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupAllInfoChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupsMsgMaskResult(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupConfMemberChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupBulletinChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGetGroupBulletinListResult(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onMemberListChange(arg: {
|
|
||||||
sceneId: string,
|
|
||||||
ids: string[],
|
|
||||||
infos: Map<string, GroupMember>,
|
|
||||||
finish: boolean,
|
|
||||||
hasRobot: boolean
|
|
||||||
}): void;
|
|
||||||
|
|
||||||
onMemberInfoChange(groupCode: string, changeType: number, members: Map<string, GroupMember>): void;
|
|
||||||
|
|
||||||
onSearchMemberChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupBulletinRichMediaDownloadComplete(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupBulletinRichMediaProgressUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupStatisticInfoChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onJoinGroupNotify(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onShutUpMemberListChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupBulletinRemindNotify(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupFirstBulletinNotify(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onJoinGroupNoVerifyFlag(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupArkInviteStateResult(...args: unknown[]): void;
|
|
||||||
|
|
||||||
// 发现于Win 9.9.9 23159
|
|
||||||
onGroupMemberLevelInfoChange(...args: unknown[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelGroupListener extends IGroupListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IGroupListener): NodeIKernelGroupListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GroupListener implements IGroupListener {
|
|
||||||
// 发现于Win 9.9.9 23159
|
// 发现于Win 9.9.9 23159
|
||||||
onGroupMemberLevelInfoChange(...args: unknown[]): void {
|
onGroupMemberLevelInfoChange(...args: unknown[]): void {
|
||||||
|
|
||||||
@@ -125,7 +63,7 @@ export class GroupListener implements IGroupListener {
|
|||||||
onJoinGroupNoVerifyFlag(...args: unknown[]) {
|
onJoinGroupNoVerifyFlag(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onMemberInfoChange(groupCode: string, changeType: number, members: Map<string, GroupMember>) {
|
onMemberInfoChange(groupCode: string, dateSource: DataSource, members: Map<string, GroupMember>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onMemberListChange(arg: {
|
onMemberListChange(arg: {
|
||||||
@@ -142,102 +80,4 @@ export class GroupListener implements IGroupListener {
|
|||||||
|
|
||||||
onShutUpMemberListChanged(...args: unknown[]) {
|
onShutUpMemberListChanged(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DebugGroupListener implements IGroupListener {
|
|
||||||
onGroupMemberLevelInfoChange(...args: unknown[]): void {
|
|
||||||
console.log('onGroupMemberLevelInfoChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGetGroupBulletinListResult(...args: unknown[]) {
|
|
||||||
console.log('onGetGroupBulletinListResult:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupAllInfoChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupAllInfoChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupBulletinChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupBulletinChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupBulletinRemindNotify(...args: unknown[]) {
|
|
||||||
console.log('onGroupBulletinRemindNotify:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupArkInviteStateResult(...args: unknown[]) {
|
|
||||||
console.log('onGroupArkInviteStateResult:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupBulletinRichMediaDownloadComplete(...args: unknown[]) {
|
|
||||||
console.log('onGroupBulletinRichMediaDownloadComplete:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupConfMemberChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupConfMemberChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupDetailInfoChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupDetailInfoChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupExtListUpdate(...args: unknown[]) {
|
|
||||||
console.log('onGroupExtListUpdate:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupFirstBulletinNotify(...args: unknown[]) {
|
|
||||||
console.log('onGroupFirstBulletinNotify:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupListUpdate(...args: unknown[]) {
|
|
||||||
console.log('onGroupListUpdate:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupNotifiesUpdated(...args: unknown[]) {
|
|
||||||
console.log('onGroupNotifiesUpdated:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupBulletinRichMediaProgressUpdate(...args: unknown[]) {
|
|
||||||
console.log('onGroupBulletinRichMediaProgressUpdate:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]) {
|
|
||||||
console.log('onGroupNotifiesUnreadCountUpdated:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]) {
|
|
||||||
console.log('onGroupSingleScreenNotifies:');
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupsMsgMaskResult(...args: unknown[]) {
|
|
||||||
console.log('onGroupsMsgMaskResult:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupStatisticInfoChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupStatisticInfoChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onJoinGroupNotify(...args: unknown[]) {
|
|
||||||
console.log('onJoinGroupNotify:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onJoinGroupNoVerifyFlag(...args: unknown[]) {
|
|
||||||
console.log('onJoinGroupNoVerifyFlag:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMemberInfoChange(groupCode: string, changeType: number, members: Map<string, GroupMember>) {
|
|
||||||
console.log('onMemberInfoChange:', groupCode, changeType, members);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMemberListChange(...args: unknown[]) {
|
|
||||||
console.log('onMemberListChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onSearchMemberChange(...args: unknown[]) {
|
|
||||||
console.log('onSearchMemberChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onShutUpMemberListChanged(...args: unknown[]) {
|
|
||||||
console.log('onShutUpMemberListChanged:', ...args);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,45 +1,5 @@
|
|||||||
export interface IKernelLoginListener {
|
|
||||||
onLoginConnected(...args: any[]): void;
|
|
||||||
|
|
||||||
onLoginDisConnected(...args: any[]): void;
|
export class NodeIKernelLoginListener {
|
||||||
|
|
||||||
onLoginConnecting(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeGetPicture(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeLoginPollingStarted(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeSessionUserScaned(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeLoginSucceed(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeSessionFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onLoginFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onLogoutSucceed(...args: any[]): void;
|
|
||||||
|
|
||||||
onLogoutFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onUserLoggedIn(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeSessionQuickLoginFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onPasswordLoginFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
OnConfirmUnusualDeviceFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onQQLoginNumLimited(...args: any[]): void;
|
|
||||||
|
|
||||||
onLoginState(...args: any[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelLoginListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IKernelLoginListener): NodeIKernelLoginListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LoginListener implements IKernelLoginListener {
|
|
||||||
onLoginConnected(...args: any[]): void {
|
onLoginConnected(...args: any[]): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ export interface OnRichMediaDownloadCompleteParams {
|
|||||||
userUsedSpacePerDay: unknown | null
|
userUsedSpacePerDay: unknown | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface onGroupFileInfoUpdateParamType {
|
export interface GroupFileInfoUpdateParamType {
|
||||||
retCode: number;
|
retCode: number;
|
||||||
retMsg: string;
|
retMsg: string;
|
||||||
clientWording: string;
|
clientWording: string;
|
||||||
@@ -52,199 +52,7 @@ export interface TempOnRecvParams {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IKernelMsgListener {
|
export class NodeIKernelMsgListener {
|
||||||
onAddSendMsg(msgRecord: RawMessage): void;
|
|
||||||
|
|
||||||
onBroadcastHelperDownloadComplete(broadcastHelperTransNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onBroadcastHelperProgressUpdate(broadcastHelperTransNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onChannelFreqLimitInfoUpdate(contact: unknown, z: unknown, freqLimitInfo: unknown): void;
|
|
||||||
|
|
||||||
onContactUnreadCntUpdate(hashMap: unknown): void;
|
|
||||||
|
|
||||||
onCustomWithdrawConfigUpdate(customWithdrawConfig: unknown): void;
|
|
||||||
|
|
||||||
onDraftUpdate(contact: unknown, arrayList: unknown, j2: unknown): void;
|
|
||||||
|
|
||||||
onEmojiDownloadComplete(emojiNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onEmojiResourceUpdate(emojiResourceInfo: unknown): void;
|
|
||||||
|
|
||||||
onFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onFileMsgCome(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onFirstViewDirectMsgUpdate(firstViewDirectMsgNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onFirstViewGroupGuildMapping(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onGrabPasswordRedBag(i2: unknown, str: unknown, i3: unknown, recvdOrder: unknown, msgRecord: unknown): void;
|
|
||||||
|
|
||||||
onGroupFileInfoAdd(groupItem: unknown): void;
|
|
||||||
|
|
||||||
onGroupFileInfoUpdate(groupFileListResult: onGroupFileInfoUpdateParamType): void;
|
|
||||||
|
|
||||||
onGroupGuildUpdate(groupGuildNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onGroupTransferInfoAdd(groupItem: unknown): void;
|
|
||||||
|
|
||||||
onGroupTransferInfoUpdate(groupFileListResult: unknown): void;
|
|
||||||
|
|
||||||
onGuildInteractiveUpdate(guildInteractiveNotificationItem: unknown): void;
|
|
||||||
|
|
||||||
onGuildMsgAbFlagChanged(guildMsgAbFlag: unknown): void;
|
|
||||||
|
|
||||||
onGuildNotificationAbstractUpdate(guildNotificationAbstractInfo: unknown): void;
|
|
||||||
|
|
||||||
onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: unknown): void;
|
|
||||||
|
|
||||||
onHitEmojiKeywordResult(hitRelatedEmojiWordsResult: unknown): void;
|
|
||||||
|
|
||||||
onHitRelatedEmojiResult(relatedWordEmojiInfo: unknown): void;
|
|
||||||
|
|
||||||
onImportOldDbProgressUpdate(importOldDbMsgNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onInputStatusPush(inputStatusInfo: {
|
|
||||||
chatType: number;
|
|
||||||
eventType: number;
|
|
||||||
fromUin: string;
|
|
||||||
interval: string;
|
|
||||||
showTime: string;
|
|
||||||
statusText: string;
|
|
||||||
timestamp: string;
|
|
||||||
toUin: string;
|
|
||||||
}): void;
|
|
||||||
|
|
||||||
onKickedOffLine(kickedInfo: unknown): void;
|
|
||||||
|
|
||||||
onLineDev(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onLogLevelChanged(j2: unknown): void;
|
|
||||||
|
|
||||||
onMsgAbstractUpdate(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onMsgBoxChanged(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onMsgDelete(contact: unknown, arrayList: unknown): void;
|
|
||||||
|
|
||||||
onMsgEventListUpdate(hashMap: unknown): void;
|
|
||||||
|
|
||||||
onMsgInfoListAdd(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onMsgInfoListUpdate(msgList: RawMessage[]): void;
|
|
||||||
|
|
||||||
onMsgQRCodeStatusChanged(i2: unknown): void;
|
|
||||||
|
|
||||||
onMsgRecall(i2: unknown, str: unknown, j2: unknown): void;
|
|
||||||
|
|
||||||
onMsgSecurityNotify(msgRecord: unknown): void;
|
|
||||||
|
|
||||||
onMsgSettingUpdate(msgSetting: unknown): void;
|
|
||||||
|
|
||||||
onNtFirstViewMsgSyncEnd(): void;
|
|
||||||
|
|
||||||
onNtMsgSyncEnd(): void;
|
|
||||||
|
|
||||||
onNtMsgSyncStart(): void;
|
|
||||||
|
|
||||||
onReadFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onRecvGroupGuildFlag(i2: unknown): void;
|
|
||||||
|
|
||||||
onRecvMsg(...arrayList: unknown[]): void;
|
|
||||||
|
|
||||||
onRecvMsgSvrRspTransInfo(j2: unknown, contact: unknown, i2: unknown, i3: unknown, str: unknown, bArr: unknown): void;
|
|
||||||
|
|
||||||
onRecvOnlineFileMsg(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onRecvS2CMsg(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onRecvSysMsg(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onRecvUDCFlag(i2: unknown): void;
|
|
||||||
|
|
||||||
onRichMediaDownloadComplete(fileTransNotifyInfo: OnRichMediaDownloadCompleteParams): void;
|
|
||||||
|
|
||||||
onRichMediaProgerssUpdate(fileTransNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onRichMediaUploadComplete(fileTransNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onSearchGroupFileInfoUpdate(searchGroupFileResult:
|
|
||||||
{
|
|
||||||
result: {
|
|
||||||
retCode: number,
|
|
||||||
retMsg: string,
|
|
||||||
clientWording: string
|
|
||||||
},
|
|
||||||
syncCookie: string,
|
|
||||||
totalMatchCount: number,
|
|
||||||
ownerMatchCount: number,
|
|
||||||
isEnd: boolean,
|
|
||||||
reqId: number,
|
|
||||||
item: Array<{
|
|
||||||
groupCode: string,
|
|
||||||
groupName: string,
|
|
||||||
uploaderUin: string,
|
|
||||||
uploaderName: string,
|
|
||||||
matchUin: string,
|
|
||||||
matchWords: Array<unknown>,
|
|
||||||
fileNameHits: Array<{
|
|
||||||
start: number,
|
|
||||||
end: number
|
|
||||||
}>,
|
|
||||||
fileModelId: string,
|
|
||||||
fileId: string,
|
|
||||||
fileName: string,
|
|
||||||
fileSize: string,
|
|
||||||
busId: number,
|
|
||||||
uploadTime: number,
|
|
||||||
modifyTime: number,
|
|
||||||
deadTime: number,
|
|
||||||
downloadTimes: number,
|
|
||||||
localPath: string
|
|
||||||
}>
|
|
||||||
}): void;
|
|
||||||
|
|
||||||
onSendMsgError(j2: unknown, contact: unknown, i2: unknown, str: unknown): void;
|
|
||||||
|
|
||||||
onSysMsgNotification(i2: unknown, j2: unknown, j3: unknown, arrayList: unknown): void;
|
|
||||||
|
|
||||||
onTempChatInfoUpdate(tempChatInfo: TempOnRecvParams): void;
|
|
||||||
|
|
||||||
onUnreadCntAfterFirstView(hashMap: unknown): void;
|
|
||||||
|
|
||||||
onUnreadCntUpdate(hashMap: unknown): void;
|
|
||||||
|
|
||||||
onUserChannelTabStatusChanged(z: unknown): void;
|
|
||||||
|
|
||||||
onUserOnlineStatusChanged(z: unknown): void;
|
|
||||||
|
|
||||||
onUserTabStatusChanged(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onlineStatusBigIconDownloadPush(i2: unknown, j2: unknown, str: unknown): void;
|
|
||||||
|
|
||||||
onlineStatusSmallIconDownloadPush(i2: unknown, j2: unknown, str: unknown): void;
|
|
||||||
|
|
||||||
// 第一次发现于Linux
|
|
||||||
onUserSecQualityChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onMsgWithRichLinkInfoUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onRedTouchChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
// 第一次发现于Win 9.9.9 23159
|
|
||||||
onBroadcastHelperProgerssUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelMsgListener extends IKernelMsgListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IKernelMsgListener): NodeIKernelMsgListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export class MsgListener implements IKernelMsgListener {
|
|
||||||
onAddSendMsg(msgRecord: RawMessage) {
|
onAddSendMsg(msgRecord: RawMessage) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -305,7 +113,7 @@ export class MsgListener implements IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupFileInfoUpdate(groupFileListResult: onGroupFileInfoUpdateParamType) {
|
onGroupFileInfoUpdate(groupFileListResult: GroupFileInfoUpdateParamType) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,25 +1,6 @@
|
|||||||
import { User, UserDetailInfoListenerArg } from '@/core/entities';
|
import { User, UserDetailInfoListenerArg } from '@/core/entities';
|
||||||
|
|
||||||
interface IProfileListener {
|
export class NodeIKernelProfileListener {
|
||||||
onProfileSimpleChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void;
|
|
||||||
|
|
||||||
onProfileDetailInfoChanged(profile: User): void;
|
|
||||||
|
|
||||||
onStatusUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onSelfStatusChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onStrangerRemarkChanged(...args: unknown[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelProfileListener extends IProfileListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IProfileListener): NodeIKernelProfileListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ProfileListener implements IProfileListener {
|
|
||||||
onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void {
|
onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,47 +25,47 @@ export class ProfileListener implements IProfileListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMemberListChange(...args: unknown[]){
|
onMemberListChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMemberInfoChange(...args: unknown[]){
|
onMemberInfoChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupListUpdate(...args: unknown[]){
|
onGroupListUpdate(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupAllInfoChange(...args: unknown[]){
|
onGroupAllInfoChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupDetailInfoChange(...args: unknown[]){
|
onGroupDetailInfoChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupConfMemberChange(...args: unknown[]){
|
onGroupConfMemberChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupExtListUpdate(...args: unknown[]){
|
onGroupExtListUpdate(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupNotifiesUpdated(...args: unknown[]){
|
onGroupNotifiesUpdated(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]){
|
onGroupNotifiesUnreadCountUpdated(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupMemberLevelInfoChange(...args: unknown[]){
|
onGroupMemberLevelInfoChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupBulletinChange(...args: unknown[]){
|
onGroupBulletinChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,23 +1,4 @@
|
|||||||
interface IKernelRecentContactListener {
|
export class NodeIKernelRecentContactListener {
|
||||||
onDeletedContactsNotify(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onRecentContactNotification(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onMsgUnreadCountUpdate(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onGuildDisplayRecentContactListChanged(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onRecentContactListChanged(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onRecentContactListChangedVer2(...args: unknown[]): unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelRecentContactListener extends IKernelRecentContactListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IKernelRecentContactListener): NodeIKernelRecentContactListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class KernelRecentContactListener implements IKernelRecentContactListener {
|
|
||||||
onDeletedContactsNotify(...args: unknown[]) {
|
onDeletedContactsNotify(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +1,4 @@
|
|||||||
export interface IKernelRobotListener {
|
export class NodeIKernelRobotListener{
|
||||||
onRobotFriendListChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onRobotListChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onRobotProfileChanged(...args: unknown[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelRobotListener extends IKernelRobotListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IKernelRobotListener): NodeIKernelRobotListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class KernelRobotListener implements IKernelRobotListener {
|
|
||||||
onRobotFriendListChanged(...args: unknown[]) {
|
onRobotFriendListChanged(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,23 +1,4 @@
|
|||||||
export interface ISessionListener {
|
export class NodeIKernelSessionListener {
|
||||||
onNTSessionCreate(args: unknown): void;
|
|
||||||
|
|
||||||
onGProSessionCreate(args: unknown): void;
|
|
||||||
|
|
||||||
onSessionInitComplete(args: unknown): void;
|
|
||||||
|
|
||||||
onOpentelemetryInit(args: unknown): void;
|
|
||||||
|
|
||||||
onUserOnlineResult(args: unknown): void;
|
|
||||||
|
|
||||||
onGetSelfTinyId(args: unknown): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelSessionListener extends ISessionListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: ISessionListener): NodeIKernelSessionListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SessionListener implements ISessionListener {
|
|
||||||
onNTSessionCreate(args: unknown) {
|
onNTSessionCreate(args: unknown) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,22 +1,4 @@
|
|||||||
export interface IStorageCleanListener {
|
export class NodeIKernelStorageCleanListener {
|
||||||
onCleanCacheProgressChanged(args: unknown): void;
|
|
||||||
|
|
||||||
onScanCacheProgressChanged(args: unknown): void;
|
|
||||||
|
|
||||||
onCleanCacheStorageChanged(args: unknown): void;
|
|
||||||
|
|
||||||
onFinishScan(args: unknown): void;
|
|
||||||
|
|
||||||
onChatCleanDone(args: unknown): void;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelStorageCleanListener extends IStorageCleanListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IStorageCleanListener): NodeIKernelStorageCleanListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StorageCleanListener implements IStorageCleanListener {
|
|
||||||
onCleanCacheProgressChanged(args: unknown) {
|
onCleanCacheProgressChanged(args: unknown) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,2 @@
|
|||||||
export interface IKernelTicketListener {
|
export class NodeIKernelTicketListener {
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelTicketListener extends IKernelTicketListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IKernelTicketListener): NodeIKernelTicketListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class KernelTicketListener implements IKernelTicketListener {
|
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
import { IGroupListener, NodeIKernelGroupListener } from '@/core/listeners/NodeIKernelGroupListener';
|
import { IGroupListener } from '@/core/listeners/NodeIKernelGroupListener';
|
||||||
import {
|
import {
|
||||||
GroupExtParam,
|
GroupExtParam,
|
||||||
GroupMember,
|
GroupMember,
|
||||||
GroupMemberRole,
|
GroupMemberRole,
|
||||||
GroupNotifyMsgType,
|
GroupNotifyMsgType,
|
||||||
GroupRequestOperateTypes,
|
GroupRequestOperateTypes,
|
||||||
kickMemberV2Req,
|
KickMemberV2Req
|
||||||
} from '@/core/entities';
|
} from '@/core/entities';
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
|
|
||||||
//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底
|
//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底
|
||||||
|
|
||||||
export interface NodeIKernelGroupService {
|
export interface NodeIKernelGroupService {
|
||||||
kickMemberV2(param: kickMemberV2Req): Promise<GeneralCallResult>;
|
kickMemberV2(param: KickMemberV2Req): Promise<GeneralCallResult>;
|
||||||
quitGroupV2(param: { groupCode: string; needDeleteLocalMsg: boolean; }): Promise<GeneralCallResult>;
|
quitGroupV2(param: { groupCode: string; needDeleteLocalMsg: boolean; }): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
getMemberCommonInfo(Req: {
|
getMemberCommonInfo(Req: {
|
||||||
|
@@ -9,7 +9,7 @@ export interface LoginInitConfig {
|
|||||||
hostName: string;
|
hostName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface passwordLoginRetType {
|
export interface PasswordLoginRetType {
|
||||||
result: string,
|
result: string,
|
||||||
loginErrorInfo: {
|
loginErrorInfo: {
|
||||||
step: number;
|
step: number;
|
||||||
@@ -23,7 +23,7 @@ export interface passwordLoginRetType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface passwordLoginArgType {
|
export interface PasswordLoginArgType {
|
||||||
uin: string;
|
uin: string;
|
||||||
passwordMd5: string;//passwMD5
|
passwordMd5: string;//passwMD5
|
||||||
step: number;//猜测是需要二次认证 参数 一次为0
|
step: number;//猜测是需要二次认证 参数 一次为0
|
||||||
@@ -77,7 +77,7 @@ export interface NodeIKernelLoginService {
|
|||||||
|
|
||||||
quickLoginWithUin(uin: string): Promise<QuickLoginResult>;
|
quickLoginWithUin(uin: string): Promise<QuickLoginResult>;
|
||||||
|
|
||||||
passwordLogin(param: passwordLoginArgType): Promise<any>;
|
passwordLogin(param: PasswordLoginArgType): Promise<any>;
|
||||||
|
|
||||||
getQRCodePicture(): boolean;
|
getQRCodePicture(): boolean;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { AnyCnameRecord } from 'node:dns';
|
import { AnyCnameRecord } from 'node:dns';
|
||||||
import { BizKey, ModifyProfileParams, SimpleInfo, UserDetailInfoByUin } from '../entities';
|
import { BizKey, ModifyProfileParams, SimpleInfo, UserDetailInfoByUin } from '../entities';
|
||||||
import { NodeIKernelProfileListener, ProfileListener } from '../listeners';
|
import { NodeIKernelProfileListener } from '../listeners';
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
|
|
||||||
export enum UserDetailSource {
|
export enum UserDetailSource {
|
||||||
@@ -35,7 +35,7 @@ export interface NodeIKernelProfileService {
|
|||||||
|
|
||||||
fetchUserDetailInfo(trace: string, uids: string[], arg2: number, arg3: number[]): Promise<unknown>;
|
fetchUserDetailInfo(trace: string, uids: string[], arg2: number, arg3: number[]): Promise<unknown>;
|
||||||
|
|
||||||
addKernelProfileListener(listener: ProfileListener): number;
|
addKernelProfileListener(listener: NodeIKernelProfileListener): number;
|
||||||
|
|
||||||
removeKernelProfileListener(listenerId: number): void;
|
removeKernelProfileListener(listenerId: number): void;
|
||||||
|
|
||||||
|
@@ -1,11 +1,6 @@
|
|||||||
import { NodeIDependsAdapter, NodeIDispatcherAdapter, NodeIGlobalAdapter } from '../adapters';
|
import { NodeIDependsAdapter, NodeIDispatcherAdapter, NodeIGlobalAdapter } from '../adapters';
|
||||||
import {
|
import {
|
||||||
NodeIKernelBuddyListener,
|
NodeIKernelSessionListener
|
||||||
NodeIKernelGroupListener,
|
|
||||||
NodeIKernelLoginListener,
|
|
||||||
NodeIKernelMsgListener,
|
|
||||||
NodeIKernelProfileListener,
|
|
||||||
NodeIKernelSessionListener,
|
|
||||||
} from '../listeners';
|
} from '../listeners';
|
||||||
import {
|
import {
|
||||||
NodeIKernelAvatarService,
|
NodeIKernelAvatarService,
|
||||||
@@ -278,20 +273,11 @@ export interface NodeIQQNTWrapperEngine {
|
|||||||
export interface WrapperNodeApi {
|
export interface WrapperNodeApi {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
|
||||||
NodeIKernelBuddyListener: NodeIKernelBuddyListener;
|
|
||||||
NodeIKernelGroupListener: NodeIKernelGroupListener;
|
|
||||||
NodeQQNTWrapperUtil: NodeQQNTWrapperUtil;
|
NodeQQNTWrapperUtil: NodeQQNTWrapperUtil;
|
||||||
NodeIQQNTWrapperSession: NodeIQQNTWrapperSession;
|
NodeIQQNTWrapperSession: NodeIQQNTWrapperSession;
|
||||||
NodeIKernelMsgListener: NodeIKernelMsgListener;
|
|
||||||
NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine;
|
NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine;
|
||||||
NodeIGlobalAdapter: NodeIGlobalAdapter;
|
|
||||||
NodeIDependsAdapter: NodeIDependsAdapter;
|
|
||||||
NodeIDispatcherAdapter: NodeIDispatcherAdapter;
|
|
||||||
NodeIKernelSessionListener: NodeIKernelSessionListener;
|
|
||||||
NodeIKernelLoginService: NodeIKernelLoginService;
|
NodeIKernelLoginService: NodeIKernelLoginService;
|
||||||
NodeIKernelLoginListener: NodeIKernelLoginListener;
|
|
||||||
NodeIKernelProfileService: NodeIKernelProfileService;
|
NodeIKernelProfileService: NodeIKernelProfileService;
|
||||||
NodeIKernelProfileListener: NodeIKernelProfileListener;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PlatformType {
|
export enum PlatformType {
|
||||||
|
@@ -5,7 +5,7 @@ import { QQBasicInfoWrapper } from '@/common/utils/QQBasicInfo';
|
|||||||
import { loadQQWrapper, NapCatCore, NapCatCoreWorkingEnv } from '@/core/core';
|
import { loadQQWrapper, NapCatCore, NapCatCoreWorkingEnv } from '@/core/core';
|
||||||
import { InstanceContext } from '@/core';
|
import { InstanceContext } from '@/core';
|
||||||
import { SelfInfo } from '@/core/entities';
|
import { SelfInfo } from '@/core/entities';
|
||||||
import { LoginListener } from '@/core/listeners';
|
import { NodeIKernelLoginListener } from '@/core/listeners';
|
||||||
import { NodeIKernelLoginService } from '@/core/services';
|
import { NodeIKernelLoginService } from '@/core/services';
|
||||||
import { NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core/wrapper/wrapper';
|
import { NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core/wrapper/wrapper';
|
||||||
import { InitWebUi, WebUiConfig } from '@/webui';
|
import { InitWebUi, WebUiConfig } from '@/webui';
|
||||||
@@ -29,7 +29,7 @@ export async function NCoreInitFramework(
|
|||||||
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
||||||
//直到登录成功后,执行下一步
|
//直到登录成功后,执行下一步
|
||||||
const selfInfo = await new Promise<SelfInfo>((resolveSelfInfo) => {
|
const selfInfo = await new Promise<SelfInfo>((resolveSelfInfo) => {
|
||||||
const loginListener = new LoginListener();
|
const loginListener = new NodeIKernelLoginListener();
|
||||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
||||||
await new Promise<void>(resolvePendingInit => {
|
await new Promise<void>(resolvePendingInit => {
|
||||||
registerInitCallback(() => resolvePendingInit());
|
registerInitCallback(() => resolvePendingInit());
|
||||||
|
@@ -17,7 +17,7 @@ export class FetchCustomFace extends BaseAction<Payload, string[]> {
|
|||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
//48 可能正好是QQ需要的一个页面的数量 Tagged Mlikiowa
|
//48 可能正好是QQ需要的一个页面的数量 Tagged Mlikiowa
|
||||||
const ret = await this.CoreContext.apis.MsgApi.fetchFavEmojiList(parseInt((payload.count || '0').toString()) || 48);
|
const ret = await this.CoreContext.apis.MsgApi.fetchFavEmojiList(+(payload.count ?? 48));
|
||||||
return ret.emojiInfoList.map(e => e.url);
|
return ret.emojiInfoList.map(e => e.url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,6 @@ export class FetchEmojiLike extends BaseAction<Payload, any> {
|
|||||||
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 NTQQMsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0];
|
||||||
return await NTQQMsgApi.getMsgEmojiLikesList(msgIdPeer.Peer, msg.msgSeq, payload.emojiId, payload.emojiType, parseInt((payload.count || '0').toString()) || 20);
|
return await NTQQMsgApi.getMsgEmojiLikesList(msgIdPeer.Peer, msg.msgSeq, payload.emojiId, payload.emojiType, +(payload.count ?? 20));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,6 @@ export class GetCollectionList extends BaseAction<Payload, any> {
|
|||||||
PayloadSchema = SchemaData;
|
PayloadSchema = SchemaData;
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQCollectionApi = this.CoreContext.apis.CollectionApi;
|
const NTQQCollectionApi = this.CoreContext.apis.CollectionApi;
|
||||||
return await NTQQCollectionApi.getAllCollection(parseInt(payload.category.toString()), parseInt(payload.count.toString()));
|
return await NTQQCollectionApi.getAllCollection(parseInt(payload.category.toString()), +(payload.count ?? 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,7 @@ const SchemaData = {
|
|||||||
properties: {
|
properties: {
|
||||||
user_id: { type: ['number', 'string'] },
|
user_id: { type: ['number', 'string'] },
|
||||||
message_seq: { type: 'number' },
|
message_seq: { type: 'number' },
|
||||||
count: { type: 'number' },
|
count: { type: ['number', 'string'] },
|
||||||
reverseOrder: { type: 'boolean' },
|
reverseOrder: { type: 'boolean' },
|
||||||
},
|
},
|
||||||
required: ['user_id'],
|
required: ['user_id'],
|
||||||
@@ -32,7 +32,7 @@ export default class GetFriendMsgHistory extends BaseAction<Payload, Response> {
|
|||||||
const NTQQFriendApi = this.CoreContext.apis.FriendApi;
|
const NTQQFriendApi = this.CoreContext.apis.FriendApi;
|
||||||
//处理参数
|
//处理参数
|
||||||
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
|
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
|
||||||
const MsgCount = payload.count || 20;
|
const MsgCount = +(payload.count ?? 20);
|
||||||
const isReverseOrder = payload.reverseOrder || true;
|
const isReverseOrder = payload.reverseOrder || true;
|
||||||
if (!uid) throw `记录${payload.user_id}不存在`;
|
if (!uid) throw `记录${payload.user_id}不存在`;
|
||||||
const friend = await NTQQFriendApi.isBuddy(uid);
|
const friend = await NTQQFriendApi.isBuddy(uid);
|
||||||
|
@@ -14,7 +14,7 @@ const SchemaData = {
|
|||||||
properties: {
|
properties: {
|
||||||
group_id: { type: ['number', 'string'] },
|
group_id: { type: ['number', 'string'] },
|
||||||
message_seq: { type: 'number' },
|
message_seq: { type: 'number' },
|
||||||
count: { type: 'number' },
|
count: { type: ['number', 'string'] },
|
||||||
reverseOrder: { type: 'boolean' },
|
reverseOrder: { type: 'boolean' },
|
||||||
},
|
},
|
||||||
required: ['group_id'],
|
required: ['group_id'],
|
||||||
@@ -30,7 +30,7 @@ export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Resp
|
|||||||
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
|
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
|
||||||
//处理参数
|
//处理参数
|
||||||
const isReverseOrder = payload.reverseOrder || true;
|
const isReverseOrder = payload.reverseOrder || true;
|
||||||
const MsgCount = payload.count || 20;
|
const MsgCount = +(payload.count ?? 20);
|
||||||
const peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: payload.group_id.toString() };
|
const peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: payload.group_id.toString() };
|
||||||
//拉取消息
|
//拉取消息
|
||||||
let msgList: RawMessage[];
|
let msgList: RawMessage[];
|
||||||
|
@@ -62,8 +62,6 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
|||||||
if (PublishGroupBulletinResult.result != 0) {
|
if (PublishGroupBulletinResult.result != 0) {
|
||||||
throw `设置群公告失败,错误信息:${PublishGroupBulletinResult.errMsg}`;
|
throw `设置群公告失败,错误信息:${PublishGroupBulletinResult.errMsg}`;
|
||||||
}
|
}
|
||||||
// 下面实现扬了
|
|
||||||
//await WebApi.setGroupNotice(payload.group_id, payload.content) ;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { ChatType, SendFileElement } from '@/core/entities';
|
import { ChatType } from '@/core/entities';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { sendMsg } from '@/onebot/action/msg/SendMsg';
|
import { sendMsg } from '@/onebot/action/msg/SendMsg';
|
||||||
import { uri2local } from '@/common/utils/file';
|
import { uri2local } from '@/common/utils/file';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { SendMsgElementConstructor } from '@/onebot/helper/genMessage';
|
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -34,7 +33,7 @@ export default class GoCQHTTPUploadGroupFile extends BaseAction<Payload, null> {
|
|||||||
if (!downloadResult.success) {
|
if (!downloadResult.success) {
|
||||||
throw new Error(downloadResult.errMsg);
|
throw new Error(downloadResult.errMsg);
|
||||||
}
|
}
|
||||||
const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(this.CoreContext, downloadResult.path, payload.name, payload.folder_id);
|
const sendFileEle = await this.CoreContext.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name, payload.folder_id);
|
||||||
await sendMsg(this.CoreContext, {
|
await sendMsg(this.CoreContext, {
|
||||||
chatType: ChatType.KCHATTYPEGROUP,
|
chatType: ChatType.KCHATTYPEGROUP,
|
||||||
peerUid: payload.group_id.toString(),
|
peerUid: payload.group_id.toString(),
|
||||||
|
@@ -5,7 +5,6 @@ import fs from 'fs';
|
|||||||
import { sendMsg } from '@/onebot/action/msg/SendMsg';
|
import { sendMsg } from '@/onebot/action/msg/SendMsg';
|
||||||
import { uri2local } from '@/common/utils/file';
|
import { uri2local } from '@/common/utils/file';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { SendMsgElementConstructor } from '@/onebot/helper/genMessage';
|
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -34,7 +33,7 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
|
|||||||
const isBuddy = await NTQQFriendApi.isBuddy(peerUid);
|
const isBuddy = await NTQQFriendApi.isBuddy(peerUid);
|
||||||
return { chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid };
|
return { chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid };
|
||||||
}
|
}
|
||||||
throw '缺少参数 user_id';
|
throw new Error( '缺少参数 user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<null> {
|
async _handle(payload: Payload): Promise<null> {
|
||||||
@@ -47,7 +46,7 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
|
|||||||
if (!downloadResult.success) {
|
if (!downloadResult.success) {
|
||||||
throw new Error(downloadResult.errMsg);
|
throw new Error(downloadResult.errMsg);
|
||||||
}
|
}
|
||||||
const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(this.CoreContext, downloadResult.path, payload.name);
|
const sendFileEle: SendFileElement = await this.CoreContext.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name);
|
||||||
await sendMsg(this.CoreContext, peer, [sendFileEle], [], true);
|
await sendMsg(this.CoreContext, peer, [sendFileEle], [], true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
@@ -6,6 +6,7 @@ import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
|||||||
interface GroupNotice {
|
interface GroupNotice {
|
||||||
sender_id: number;
|
sender_id: number;
|
||||||
publish_time: number;
|
publish_time: number;
|
||||||
|
feed_id: string;
|
||||||
message: {
|
message: {
|
||||||
text: string
|
text: string
|
||||||
image: Array<{
|
image: Array<{
|
||||||
@@ -44,7 +45,8 @@ export class GetGroupNotice extends BaseAction<Payload, GroupNotice[]> {
|
|||||||
for (const key in ret.feeds) {
|
for (const key in ret.feeds) {
|
||||||
const retApiNotice: WebApiGroupNoticeFeed = ret.feeds[key];
|
const retApiNotice: WebApiGroupNoticeFeed = ret.feeds[key];
|
||||||
const retNotice: GroupNotice = {
|
const retNotice: GroupNotice = {
|
||||||
// ...ret.feeds[key],
|
//...ret.feeds[key],
|
||||||
|
feed_id: retApiNotice.fid,
|
||||||
sender_id: retApiNotice.u,
|
sender_id: retApiNotice.u,
|
||||||
publish_time: retApiNotice.pubt,
|
publish_time: retApiNotice.pubt,
|
||||||
message: {
|
message: {
|
||||||
|
@@ -25,7 +25,7 @@ export default class SetGroupAddRequest extends BaseAction<Payload, null> {
|
|||||||
const approve = payload.approve?.toString() !== 'false';
|
const approve = payload.approve?.toString() !== 'false';
|
||||||
await NTQQGroupApi.handleGroupRequest(flag,
|
await NTQQGroupApi.handleGroupRequest(flag,
|
||||||
approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
|
approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
|
||||||
payload.reason || ' ',
|
payload.reason ?? ' ',
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -71,7 +71,7 @@ import GetRecentContact from './user/GetRecentContact';
|
|||||||
import { GetProfileLike } from './extends/GetProfileLike';
|
import { GetProfileLike } from './extends/GetProfileLike';
|
||||||
import SetGroupPortrait from './go-cqhttp/SetGroupPortrait';
|
import SetGroupPortrait from './go-cqhttp/SetGroupPortrait';
|
||||||
import { FetchCustomFace } from './extends/FetchCustomFace';
|
import { FetchCustomFace } from './extends/FetchCustomFace';
|
||||||
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivareFile';
|
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivateFile';
|
||||||
import { FetchEmojiLike } from './extends/FetchEmojiLike';
|
import { FetchEmojiLike } from './extends/FetchEmojiLike';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ class MarkMsgAsRead extends BaseAction<PlayloadType, null> {
|
|||||||
return { chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid };
|
return { chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid };
|
||||||
}
|
}
|
||||||
if (!payload.group_id) {
|
if (!payload.group_id) {
|
||||||
throw '缺少参数 group_id 或 user_id';
|
throw new Error( '缺少参数 group_id 或 user_id');
|
||||||
}
|
}
|
||||||
return { chatType: ChatType.KCHATTYPEGROUP, peerUid: payload.group_id.toString() };
|
return { chatType: ChatType.KCHATTYPEGROUP, peerUid: payload.group_id.toString() };
|
||||||
}
|
}
|
||||||
|
@@ -9,11 +9,9 @@ import { ActionName, BaseCheckResult } from '@/onebot/action/types';
|
|||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import fsPromise from 'node:fs/promises';
|
import fsPromise from 'node:fs/promises';
|
||||||
import { decodeCQCode } from '@/onebot/helper/cqcode';
|
import { decodeCQCode } from '@/onebot/helper/cqcode';
|
||||||
import createSendElements from './create-send-elements';
|
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||||
import { ChatType, ElementType, NapCatCore, Peer, SendMessageElement } from '@/core';
|
import { ChatType, ElementType, NapCatCore, Peer, RawMessage, SendMessageElement } from '@/core';
|
||||||
import BaseAction from '../../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { handleForwardNode } from './handle-forward-node';
|
|
||||||
|
|
||||||
export interface ReturnDataType {
|
export interface ReturnDataType {
|
||||||
message_id: number;
|
message_id: number;
|
||||||
@@ -34,13 +32,11 @@ export function normalize(message: OB11MessageMixType, autoEscape = false): OB11
|
|||||||
) : Array.isArray(message) ? message : [message];
|
) : Array.isArray(message) ? message : [message];
|
||||||
}
|
}
|
||||||
|
|
||||||
export { createSendElements };
|
|
||||||
|
|
||||||
export async function sendMsg(coreContext: NapCatCore, peer: Peer, sendElements: SendMessageElement[], deleteAfterSentFiles: string[], waitComplete = true) {
|
export async function sendMsg(coreContext: NapCatCore, peer: Peer, sendElements: SendMessageElement[], deleteAfterSentFiles: string[], waitComplete = true) {
|
||||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
const NTQQMsgApi = coreContext.apis.MsgApi;
|
||||||
const logger = coreContext.context.logger;
|
const logger = coreContext.context.logger;
|
||||||
if (!sendElements.length) {
|
if (!sendElements.length) {
|
||||||
throw new Error ('消息体无法解析, 请检查是否发送了不支持的消息类型');
|
throw new Error('消息体无法解析, 请检查是否发送了不支持的消息类型');
|
||||||
}
|
}
|
||||||
let totalSize = 0;
|
let totalSize = 0;
|
||||||
let timeout = 10000;
|
let timeout = 10000;
|
||||||
@@ -99,7 +95,7 @@ async function createContext(coreContext: 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 NTQQUserApi.getUidByUinV2(payload.user_id.toString());
|
||||||
if (!Uid) throw '无法获取用户信息';
|
if (!Uid) throw new Error('无法获取用户信息');
|
||||||
const isBuddy = await NTQQFriendApi.isBuddy(Uid);
|
const isBuddy = await NTQQFriendApi.isBuddy(Uid);
|
||||||
if (!isBuddy) {
|
if (!isBuddy) {
|
||||||
const ret = await NTQQMsgApi.getTempChatInfo(ChatType.KCHATTYPETEMPC2CFROMGROUP, Uid);
|
const ret = await NTQQMsgApi.getTempChatInfo(ChatType.KCHATTYPETEMPC2CFROMGROUP, Uid);
|
||||||
@@ -129,7 +125,7 @@ async function createContext(coreContext: NapCatCore, payload: OB11PostSendMsg,
|
|||||||
guildId: '',
|
guildId: '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
throw '请指定 group_id 或 user_id';
|
throw new Error('请指定 group_id 或 user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSpecialMsgNum(payload: OB11PostSendMsg, msgType: OB11MessageDataType): number {
|
function getSpecialMsgNum(payload: OB11PostSendMsg, msgType: OB11MessageDataType): number {
|
||||||
@@ -144,9 +140,6 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
contextMode = ContextMode.Normal;
|
contextMode = ContextMode.Normal;
|
||||||
|
|
||||||
protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
|
protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
|
||||||
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
|
|
||||||
const NTQQFriendApi = this.CoreContext.apis.FriendApi;
|
|
||||||
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
|
||||||
const messages = normalize(payload.message);
|
const messages = normalize(payload.message);
|
||||||
const nodeElementLength = getSpecialMsgNum(payload, OB11MessageDataType.node);
|
const nodeElementLength = getSpecialMsgNum(payload, OB11MessageDataType.node);
|
||||||
if (nodeElementLength > 0 && nodeElementLength != messages.length) {
|
if (nodeElementLength > 0 && nodeElementLength != messages.length) {
|
||||||
@@ -156,9 +149,9 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (payload.user_id && payload.message_type !== 'group') {
|
if (payload.user_id && payload.message_type !== 'group') {
|
||||||
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
|
// const uid = await this.CoreContext.apis.UserApi.getUidByUinV2(payload.user_id.toString());
|
||||||
const isBuddy = await NTQQFriendApi.isBuddy(uid!);
|
// const isBuddy = await NTQQFriendApi.isBuddy(uid!);
|
||||||
//if (!isBuddy) { }
|
// if (!isBuddy) { }
|
||||||
}
|
}
|
||||||
return { valid: true };
|
return { valid: true };
|
||||||
}
|
}
|
||||||
@@ -174,7 +167,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
||||||
const returnMsg = await handleForwardNode(this.CoreContext, this.OneBotContext, peer, messages as OB11MessageNode[]);
|
const returnMsg = await this.handleForwardedNodes(peer, messages as OB11MessageNode[]);
|
||||||
if (returnMsg) {
|
if (returnMsg) {
|
||||||
const msgShortId = MessageUnique.createMsg({
|
const msgShortId = MessageUnique.createMsg({
|
||||||
guildId: '',
|
guildId: '',
|
||||||
@@ -194,11 +187,135 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
}
|
}
|
||||||
// log("send msg:", peer, sendElements)
|
// log("send msg:", peer, sendElements)
|
||||||
|
|
||||||
const { sendElements, deleteAfterSentFiles } = await createSendElements(this.CoreContext, this.OneBotContext, messages, peer);
|
const { sendElements, deleteAfterSentFiles } = await this.OneBotContext.apiContext.MsgApi
|
||||||
//console.log(peer, JSON.stringify(sendElements,null,2));
|
.createSendElements(messages, peer);
|
||||||
const returnMsg = await sendMsg(this.CoreContext, peer, sendElements, deleteAfterSentFiles);
|
const returnMsg = await sendMsg(this.CoreContext, peer, sendElements, deleteAfterSentFiles);
|
||||||
return { message_id: returnMsg!.id! };
|
return { message_id: returnMsg!.id! };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async handleForwardedNodes(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<RawMessage | null> {
|
||||||
|
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
|
||||||
|
const selfPeer = {
|
||||||
|
chatType: ChatType.KCHATTYPEC2C,
|
||||||
|
peerUid: this.CoreContext.selfInfo.uid,
|
||||||
|
};
|
||||||
|
let nodeMsgIds: string[] = [];
|
||||||
|
const logger = this.CoreContext.context.logger;
|
||||||
|
for (const messageNode of messageNodes) {
|
||||||
|
const nodeId = messageNode.data.id;
|
||||||
|
if (nodeId) {
|
||||||
|
//对Mgsid和OB11ID混用情况兜底
|
||||||
|
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
|
||||||
|
if (!nodeMsg) {
|
||||||
|
logger.logError('转发消息失败,未找到消息', nodeId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nodeMsgIds.push(nodeMsg.MsgId);
|
||||||
|
} else {
|
||||||
|
// 自定义的消息
|
||||||
|
try {
|
||||||
|
const OB11Data = normalize(messageNode.data.content);
|
||||||
|
//筛选node消息
|
||||||
|
const isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息
|
||||||
|
if (isNodeMsg !== 0) {
|
||||||
|
if (isNodeMsg !== OB11Data.length) {
|
||||||
|
logger.logError('子消息中包含非node消息 跳过不合法部分');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
||||||
|
if (nodeMsg) {
|
||||||
|
nodeMsgIds.push(nodeMsg.msgId);
|
||||||
|
MessageUnique.createMsg(selfPeer, nodeMsg.msgId);
|
||||||
|
}
|
||||||
|
//完成子卡片生成跳过后续
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const { sendElements } = await this.OneBotContext.apiContext.MsgApi
|
||||||
|
.createSendElements(OB11Data, destPeer);
|
||||||
|
//拆分消息
|
||||||
|
const MixElement = sendElements.filter(element => element.elementType !== ElementType.FILE && element.elementType !== ElementType.VIDEO);
|
||||||
|
const SingleElement = sendElements.filter(element => element.elementType === ElementType.FILE || element.elementType === ElementType.VIDEO).map(e => [e]);
|
||||||
|
const AllElement: SendMessageElement[][] = [MixElement, ...SingleElement].filter(e => e !== undefined && e.length !== 0);
|
||||||
|
const MsgNodeList: Promise<RawMessage | undefined>[] = [];
|
||||||
|
for (const sendElementsSplitElement of AllElement) {
|
||||||
|
MsgNodeList.push(sendMsg(this.CoreContext, selfPeer, sendElementsSplitElement, [], true).catch(_ => undefined));
|
||||||
|
}
|
||||||
|
(await Promise.allSettled(MsgNodeList)).map((result) => {
|
||||||
|
if (result.status === 'fulfilled' && result.value) {
|
||||||
|
nodeMsgIds.push(result.value.msgId);
|
||||||
|
MessageUnique.createMsg(selfPeer, result.value.msgId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
logger.logDebug('生成转发消息节点失败', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const nodeMsgArray: Array<RawMessage> = [];
|
||||||
|
let srcPeer: Peer | undefined = undefined;
|
||||||
|
let needSendSelf = false;
|
||||||
|
//检测是否处于同一个Peer 不在同一个peer则全部消息由自身发送
|
||||||
|
for (const msgId of nodeMsgIds) {
|
||||||
|
const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId);
|
||||||
|
if (!nodeMsgPeer) {
|
||||||
|
logger.logError('转发消息失败,未找到消息', msgId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
|
||||||
|
srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid };
|
||||||
|
if (srcPeer.peerUid !== nodeMsg.peerUid) {
|
||||||
|
needSendSelf = true;
|
||||||
|
}
|
||||||
|
nodeMsgArray.push(nodeMsg);
|
||||||
|
}
|
||||||
|
nodeMsgIds = nodeMsgArray.map(msg => msg.msgId);
|
||||||
|
let retMsgIds: string[] = [];
|
||||||
|
if (needSendSelf) {
|
||||||
|
for (const [, msg] of nodeMsgArray.entries()) {
|
||||||
|
if (msg.peerUid === this.CoreContext.selfInfo.uid) {
|
||||||
|
retMsgIds.push(msg.msgId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const ClonedMsg = await this.cloneMsg(msg);
|
||||||
|
if (ClonedMsg) retMsgIds.push(ClonedMsg.msgId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retMsgIds = nodeMsgIds;
|
||||||
|
}
|
||||||
|
if (retMsgIds.length === 0) throw Error('转发消息失败,生成节点为空');
|
||||||
|
try {
|
||||||
|
logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
|
||||||
|
return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds);
|
||||||
|
} catch (e) {
|
||||||
|
logger.logError('forward failed', e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async cloneMsg(msg: RawMessage): Promise<RawMessage | undefined> {
|
||||||
|
const selfPeer = {
|
||||||
|
chatType: ChatType.KCHATTYPEC2C,
|
||||||
|
peerUid: this.CoreContext.selfInfo.uid,
|
||||||
|
};
|
||||||
|
const logger = this.CoreContext.context.logger;
|
||||||
|
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
|
||||||
|
//msg 为待克隆消息
|
||||||
|
|
||||||
|
const sendElements: SendMessageElement[] = [];
|
||||||
|
|
||||||
|
for (const element of msg.elements) {
|
||||||
|
sendElements.push(element as SendMessageElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendElements.length === 0) {
|
||||||
|
logger.logDebug('需要clone的消息无法解析,将会忽略掉', msg);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return await NTQQMsgApi.sendMsg(selfPeer, sendElements, true);
|
||||||
|
} catch (e) {
|
||||||
|
logger.logError(e, '克隆转发消息失败,将忽略本条消息', msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SendMsg;
|
export default SendMsg;
|
@@ -1,36 +0,0 @@
|
|||||||
import { OB11MessageData } from '@/onebot/types';
|
|
||||||
|
|
||||||
function checkSendMessage(sendMsgList: OB11MessageData[]) {
|
|
||||||
function checkUri(uri: string): boolean {
|
|
||||||
const pattern = /^(file:\/\/|http:\/\/|https:\/\/|base64:\/\/)/;
|
|
||||||
return pattern.test(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const msg of sendMsgList) {
|
|
||||||
if (msg['type'] && msg['data']) {
|
|
||||||
const type = msg['type'];
|
|
||||||
const data = msg['data'];
|
|
||||||
if (type === 'text' && !data['text']) {
|
|
||||||
return 400;
|
|
||||||
} else if (['image', 'voice', 'record'].includes(type)) {
|
|
||||||
if (!data['file']) {
|
|
||||||
return 400;
|
|
||||||
} else {
|
|
||||||
if (checkUri(data['file'])) {
|
|
||||||
return 200;
|
|
||||||
} else {
|
|
||||||
return 400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (type === 'at' && !data['qq']) {
|
|
||||||
return 400;
|
|
||||||
} else if (type === 'reply' && !data['id']) {
|
|
||||||
return 400;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 200;
|
|
||||||
}
|
|
@@ -1,262 +0,0 @@
|
|||||||
import { OB11MessageData, OB11MessageDataType, OB11MessageFileBase } from '@/onebot/types';
|
|
||||||
import { uri2local } from '@/common/utils/file';
|
|
||||||
import { RequestUtil } from '@/common/utils/request';
|
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
|
||||||
import { AtType, ChatType, CustomMusicSignPostData, IdMusicSignPostData, NapCatCore, Peer, SendMessageElement } from '@/core';
|
|
||||||
import { SendMsgElementConstructor } from '@/onebot/helper/genMessage';
|
|
||||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
|
||||||
|
|
||||||
export type MessageContext = {
|
|
||||||
deleteAfterSentFiles: string[],
|
|
||||||
peer: Peer
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleOb11FileLikeMessage(
|
|
||||||
coreContext: NapCatCore,
|
|
||||||
obContext: NapCatOneBot11Adapter,
|
|
||||||
{ data: inputdata }: OB11MessageFileBase,
|
|
||||||
{ deleteAfterSentFiles }: MessageContext,
|
|
||||||
) {
|
|
||||||
//inputdata?.url || inputdata.file
|
|
||||||
const isBlankUrl = !inputdata.url || inputdata.url === '';
|
|
||||||
const isBlankFile = !inputdata.file || inputdata.file === '';
|
|
||||||
if (isBlankUrl && isBlankFile) {
|
|
||||||
coreContext.context.logger.logError('文件消息缺少参数', inputdata);
|
|
||||||
throw Error('文件消息缺少参数');
|
|
||||||
}
|
|
||||||
const fileOrUrl = (isBlankUrl ? inputdata.file : inputdata.url) || "";
|
|
||||||
const {
|
|
||||||
path,
|
|
||||||
isLocal,
|
|
||||||
fileName,
|
|
||||||
errMsg,
|
|
||||||
success,
|
|
||||||
} = (await uri2local(coreContext.NapCatTempPath, fileOrUrl));
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
coreContext.context.logger.logError('文件下载失败', errMsg);
|
|
||||||
throw Error('文件下载失败' + errMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isLocal) { // 只删除http和base64转过来的文件
|
|
||||||
deleteAfterSentFiles.push(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { path, fileName: inputdata.name || fileName };
|
|
||||||
}
|
|
||||||
|
|
||||||
const _handlers: {
|
|
||||||
[Key in OB11MessageDataType]: (
|
|
||||||
CoreContext: NapCatCore,
|
|
||||||
obContext: NapCatOneBot11Adapter,
|
|
||||||
sendMsg: Extract<OB11MessageData, { type: Key }>,
|
|
||||||
// This picks the correct message type out
|
|
||||||
// How great the type system of TypeScript is!
|
|
||||||
context: MessageContext,
|
|
||||||
) => Promise<SendMessageElement | undefined>
|
|
||||||
} = {
|
|
||||||
[OB11MessageDataType.text]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { text } }) => SendMsgElementConstructor.text(coreContext, text),
|
|
||||||
|
|
||||||
[OB11MessageDataType.at]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { qq: atQQ } }, context) => {
|
|
||||||
if (!context.peer || context.peer.chatType == ChatType.KCHATTYPEC2C) return undefined;
|
|
||||||
if (atQQ === 'all') return SendMsgElementConstructor.at(coreContext, atQQ, atQQ, AtType.atAll, '全体成员');
|
|
||||||
const NTQQGroupApi = coreContext.apis.GroupApi;
|
|
||||||
const NTQQUserApi = coreContext.apis.UserApi;
|
|
||||||
const atMember = await NTQQGroupApi.getGroupMember(context.peer.peerUid, atQQ);
|
|
||||||
if (atMember) {
|
|
||||||
return SendMsgElementConstructor.at(coreContext, atQQ, atMember.uid, AtType.atUser, atMember.nick || atMember.cardName);
|
|
||||||
}
|
|
||||||
const uid = await NTQQUserApi.getUidByUinV2(`${atQQ}`);
|
|
||||||
if (!uid) throw new Error('Get Uid Error');
|
|
||||||
const info = await NTQQUserApi.getUserDetailInfo(uid);
|
|
||||||
return SendMsgElementConstructor.at(coreContext, atQQ, uid, AtType.atUser, info.nick || '');
|
|
||||||
},
|
|
||||||
[OB11MessageDataType.reply]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { id } }) => {
|
|
||||||
const replyMsgM = MessageUnique.getMsgIdAndPeerByShortId(parseInt(id));
|
|
||||||
if (!replyMsgM) {
|
|
||||||
coreContext.context.logger.logWarn('回复消息不存在', id);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
|
||||||
const replyMsg = (await NTQQMsgApi.getMsgsByMsgId(
|
|
||||||
replyMsgM.Peer, [replyMsgM.MsgId!])).msgList[0];
|
|
||||||
return replyMsg ?
|
|
||||||
SendMsgElementConstructor.reply(coreContext, replyMsg.msgSeq, replyMsg.msgId, replyMsg.senderUin!, replyMsg.senderUin!) :
|
|
||||||
undefined;
|
|
||||||
},
|
|
||||||
|
|
||||||
[OB11MessageDataType.face]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { id } }) => SendMsgElementConstructor.face(coreContext, parseInt(id)),
|
|
||||||
|
|
||||||
[OB11MessageDataType.mface]: async (coreContext, obContext: NapCatOneBot11Adapter, {
|
|
||||||
data: {
|
|
||||||
emoji_package_id, emoji_id, key, summary,
|
|
||||||
},
|
|
||||||
}) => SendMsgElementConstructor.mface(coreContext, emoji_package_id, emoji_id, key, summary),
|
|
||||||
|
|
||||||
// File service
|
|
||||||
[OB11MessageDataType.image]: async (coreContext, obContext: NapCatOneBot11Adapter, sendMsg, context) => {
|
|
||||||
const PicEle = await SendMsgElementConstructor.pic(
|
|
||||||
coreContext,
|
|
||||||
(await handleOb11FileLikeMessage(coreContext, obContext, sendMsg, context)).path,
|
|
||||||
sendMsg.data.summary || '',
|
|
||||||
sendMsg.data.subType || 0,
|
|
||||||
);
|
|
||||||
context.deleteAfterSentFiles.push(PicEle.picElement.sourcePath);
|
|
||||||
return PicEle;
|
|
||||||
}, // currently not supported
|
|
||||||
[OB11MessageDataType.file]: async (coreContext, obContext: NapCatOneBot11Adapter, sendMsg, context) => {
|
|
||||||
const { path, fileName } = await handleOb11FileLikeMessage(coreContext, obContext, sendMsg, context);
|
|
||||||
//logDebug('发送文件', path, fileName);
|
|
||||||
const FileEle = await SendMsgElementConstructor.file(coreContext, path, fileName);
|
|
||||||
// 清除Upload的应该
|
|
||||||
// context.deleteAfterSentFiles.push(fileName || FileEle.fileElement.filePath);
|
|
||||||
return FileEle;
|
|
||||||
},
|
|
||||||
|
|
||||||
[OB11MessageDataType.video]: async (coreContext, obContext, sendMsg, context) => {
|
|
||||||
const { path, fileName } = await handleOb11FileLikeMessage(coreContext, obContext, sendMsg, context);
|
|
||||||
|
|
||||||
//logDebug('发送视频', path, fileName);
|
|
||||||
let thumb = sendMsg.data.thumb;
|
|
||||||
if (thumb) {
|
|
||||||
const uri2LocalRes = await uri2local(coreContext.NapCatTempPath, thumb);
|
|
||||||
if (uri2LocalRes.success) thumb = uri2LocalRes.path;
|
|
||||||
}
|
|
||||||
const videoEle = await SendMsgElementConstructor.video(coreContext, path, fileName, thumb);
|
|
||||||
//未测试
|
|
||||||
context.deleteAfterSentFiles.push(videoEle.videoElement.filePath);
|
|
||||||
return videoEle;
|
|
||||||
},
|
|
||||||
|
|
||||||
[OB11MessageDataType.voice]: async (coreContext, obContext: NapCatOneBot11Adapter, sendMsg, context) => SendMsgElementConstructor.ptt(coreContext, (await handleOb11FileLikeMessage(coreContext, obContext, sendMsg, context)).path),
|
|
||||||
|
|
||||||
[OB11MessageDataType.json]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { data } }) => SendMsgElementConstructor.ark(coreContext, data),
|
|
||||||
|
|
||||||
[OB11MessageDataType.dice]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { result } }) => SendMsgElementConstructor.dice(coreContext, result),
|
|
||||||
|
|
||||||
[OB11MessageDataType.RPS]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { result } }) => SendMsgElementConstructor.rps(coreContext, result),
|
|
||||||
|
|
||||||
[OB11MessageDataType.markdown]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { content } }) => SendMsgElementConstructor.markdown(coreContext, content),
|
|
||||||
|
|
||||||
[OB11MessageDataType.music]: async (coreContext, obContext: NapCatOneBot11Adapter, { data }) => {
|
|
||||||
// 保留, 直到...找到更好的解决方案
|
|
||||||
if (data.type === 'custom') {
|
|
||||||
if (!data.url) {
|
|
||||||
coreContext.context.logger.logError('自定义音卡缺少参数url');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (!data.audio) {
|
|
||||||
coreContext.context.logger.logError('自定义音卡缺少参数audio');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (!data.title) {
|
|
||||||
coreContext.context.logger.logError('自定义音卡缺少参数title');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!['qq', '163'].includes(data.type)) {
|
|
||||||
coreContext.context.logger.logError('音乐卡片type错误, 只支持qq、163、custom,当前type:', data.type);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (!data.id) {
|
|
||||||
coreContext.context.logger.logError('音乐卡片缺少参数id');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let postData: IdMusicSignPostData | CustomMusicSignPostData;
|
|
||||||
if (data.type === 'custom' && data.content) {
|
|
||||||
const { content, ...others } = data;
|
|
||||||
postData = { singer: content, ...others };
|
|
||||||
} else {
|
|
||||||
postData = data;
|
|
||||||
}
|
|
||||||
// Mlikiowa V2.2.8 Refactor Todo
|
|
||||||
const signUrl = obContext.configLoader.configData.musicSignUrl;
|
|
||||||
if (!signUrl) {
|
|
||||||
if (data.type === 'qq') {
|
|
||||||
//const musicJson = (await SignMusicWrapper(data.id.toString())).data.arkResult.slice(0, -1);
|
|
||||||
//return SendMsgElementConstructor.ark(musicJson);
|
|
||||||
}
|
|
||||||
throw Error('音乐消息签名地址未配置');
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const musicJson = await RequestUtil.HttpGetJson<any>(signUrl, 'POST', postData);
|
|
||||||
return SendMsgElementConstructor.ark(coreContext, musicJson);
|
|
||||||
} catch (e) {
|
|
||||||
coreContext.context.logger.logError('生成音乐消息失败', e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[OB11MessageDataType.node]: async (coreContext, obContext: NapCatOneBot11Adapter) => undefined,
|
|
||||||
|
|
||||||
[OB11MessageDataType.forward]: async (coreContext, obContext: NapCatOneBot11Adapter) => undefined,
|
|
||||||
|
|
||||||
[OB11MessageDataType.xml]: async (coreContext, obContext: NapCatOneBot11Adapter) => undefined,
|
|
||||||
|
|
||||||
[OB11MessageDataType.poke]: async (coreContext, obContext: NapCatOneBot11Adapter) => undefined,
|
|
||||||
|
|
||||||
[OB11MessageDataType.Location]: async (coreContext, obContext: NapCatOneBot11Adapter) => {
|
|
||||||
return SendMsgElementConstructor.location(coreContext);
|
|
||||||
},
|
|
||||||
[OB11MessageDataType.miniapp]: function (CoreContext: NapCatCore, obContext: NapCatOneBot11Adapter, sendMsg: never, context: MessageContext): Promise<SendMessageElement | undefined> {
|
|
||||||
throw new Error('Function not implemented.');
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlers = <{
|
|
||||||
[Key in OB11MessageDataType]: (
|
|
||||||
coreContext: NapCatCore,
|
|
||||||
obContext: NapCatOneBot11Adapter,
|
|
||||||
sendMsg: OB11MessageData,
|
|
||||||
context: MessageContext,
|
|
||||||
) => Promise<SendMessageElement | undefined>
|
|
||||||
}>_handlers;
|
|
||||||
|
|
||||||
export default async function createSendElements(
|
|
||||||
CoreContext: NapCatCore,
|
|
||||||
obContext: NapCatOneBot11Adapter,
|
|
||||||
messageData: OB11MessageData[],
|
|
||||||
peer: Peer,
|
|
||||||
ignoreTypes: OB11MessageDataType[] = [],
|
|
||||||
) {
|
|
||||||
const deleteAfterSentFiles: string[] = [];
|
|
||||||
const callResultList: Array<Promise<SendMessageElement | undefined>> = [];
|
|
||||||
for (const sendMsg of messageData) {
|
|
||||||
if (ignoreTypes.includes(sendMsg.type)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const callResult = handlers[sendMsg.type](
|
|
||||||
CoreContext,
|
|
||||||
obContext,
|
|
||||||
sendMsg,
|
|
||||||
{ peer, deleteAfterSentFiles },
|
|
||||||
)?.catch(undefined);
|
|
||||||
callResultList.push(callResult);
|
|
||||||
}
|
|
||||||
const ret = await Promise.all(callResultList);
|
|
||||||
const sendElements: SendMessageElement[] = ret.filter(ele => !!ele);
|
|
||||||
return { sendElements, deleteAfterSentFiles };
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function createSendElementsParallel(
|
|
||||||
CoreContext: NapCatCore,
|
|
||||||
obContext: NapCatOneBot11Adapter,
|
|
||||||
messageData: OB11MessageData[],
|
|
||||||
peer: Peer,
|
|
||||||
ignoreTypes: OB11MessageDataType[] = [],
|
|
||||||
) {
|
|
||||||
const deleteAfterSentFiles: string[] = [];
|
|
||||||
const sendElements = <SendMessageElement[]>(
|
|
||||||
await Promise.all(
|
|
||||||
messageData.map(async sendMsg => ignoreTypes.includes(sendMsg.type) ?
|
|
||||||
undefined :
|
|
||||||
handlers[sendMsg.type](CoreContext, obContext, sendMsg, { peer, deleteAfterSentFiles })),
|
|
||||||
).then(
|
|
||||||
results => results.filter(
|
|
||||||
element => element !== undefined,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return { sendElements, deleteAfterSentFiles };
|
|
||||||
}
|
|
@@ -1,132 +0,0 @@
|
|||||||
import { ChatType, ElementType, NapCatCore, Peer, RawMessage, SendMessageElement } from '@/core';
|
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
|
||||||
import { OB11MessageDataType, OB11MessageNode } from '@/onebot/types';
|
|
||||||
import createSendElements from './create-send-elements';
|
|
||||||
import { normalize, sendMsg } from '../SendMsg/index';
|
|
||||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
|
||||||
|
|
||||||
async function cloneMsg(coreContext: NapCatCore, msg: RawMessage): Promise<RawMessage | undefined> {
|
|
||||||
const selfPeer = {
|
|
||||||
chatType: ChatType.KCHATTYPEC2C,
|
|
||||||
peerUid: coreContext.selfInfo.uid,
|
|
||||||
};
|
|
||||||
const logger = coreContext.context.logger;
|
|
||||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
|
||||||
//logDebug('克隆的目标消息', msg);
|
|
||||||
|
|
||||||
const sendElements: SendMessageElement[] = [];
|
|
||||||
|
|
||||||
for (const element of msg.elements) {
|
|
||||||
sendElements.push(element as SendMessageElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sendElements.length === 0) {
|
|
||||||
logger.logDebug('需要clone的消息无法解析,将会忽略掉', msg);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const nodeMsg = await NTQQMsgApi.sendMsg(selfPeer, sendElements, true);
|
|
||||||
return nodeMsg;
|
|
||||||
} catch (e) {
|
|
||||||
logger.logError(e, '克隆转发消息失败,将忽略本条消息', msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function handleForwardNode(coreContext: NapCatCore, obContext: NapCatOneBot11Adapter, destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<RawMessage | null> {
|
|
||||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
|
||||||
const selfPeer = {
|
|
||||||
chatType: ChatType.KCHATTYPEC2C,
|
|
||||||
peerUid: coreContext.selfInfo.uid,
|
|
||||||
};
|
|
||||||
let nodeMsgIds: string[] = [];
|
|
||||||
const logger = coreContext.context.logger;
|
|
||||||
for (const messageNode of messageNodes) {
|
|
||||||
const nodeId = messageNode.data.id;
|
|
||||||
if (nodeId) {
|
|
||||||
//对Mgsid和OB11ID混用情况兜底
|
|
||||||
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
|
|
||||||
if (!nodeMsg) {
|
|
||||||
logger.logError('转发消息失败,未找到消息', nodeId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
nodeMsgIds.push(nodeMsg.MsgId);
|
|
||||||
} else {
|
|
||||||
// 自定义的消息
|
|
||||||
try {
|
|
||||||
const OB11Data = normalize(messageNode.data.content);
|
|
||||||
//筛选node消息
|
|
||||||
const isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息
|
|
||||||
if (isNodeMsg !== 0) {
|
|
||||||
if (isNodeMsg !== OB11Data.length) {
|
|
||||||
logger.logError('子消息中包含非node消息 跳过不合法部分');
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const nodeMsg = await handleForwardNode(coreContext, obContext, selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
|
||||||
if (nodeMsg) {
|
|
||||||
nodeMsgIds.push(nodeMsg.msgId);
|
|
||||||
MessageUnique.createMsg(selfPeer, nodeMsg.msgId);
|
|
||||||
}
|
|
||||||
//完成子卡片生成跳过后续
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const { sendElements } = await createSendElements(coreContext, obContext, OB11Data, destPeer);
|
|
||||||
//拆分消息
|
|
||||||
const MixElement = sendElements.filter(element => element.elementType !== ElementType.FILE && element.elementType !== ElementType.VIDEO);
|
|
||||||
const SingleElement = sendElements.filter(element => element.elementType === ElementType.FILE || element.elementType === ElementType.VIDEO).map(e => [e]);
|
|
||||||
const AllElement: SendMessageElement[][] = [MixElement, ...SingleElement].filter(e => e !== undefined && e.length !== 0);
|
|
||||||
const MsgNodeList: Promise<RawMessage | undefined>[] = [];
|
|
||||||
for (const sendElementsSplitElement of AllElement) {
|
|
||||||
MsgNodeList.push(sendMsg(coreContext, selfPeer, sendElementsSplitElement, [], true).catch(e => new Promise((resolve, reject) => {
|
|
||||||
resolve(undefined);
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
(await Promise.allSettled(MsgNodeList)).map((result) => {
|
|
||||||
if (result.status === 'fulfilled' && result.value) {
|
|
||||||
nodeMsgIds.push(result.value.msgId);
|
|
||||||
MessageUnique.createMsg(selfPeer, result.value.msgId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
logger.logDebug('生成转发消息节点失败', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const nodeMsgArray: Array<RawMessage> = [];
|
|
||||||
let srcPeer: Peer | undefined = undefined;
|
|
||||||
let needSendSelf = false;
|
|
||||||
//检测是否处于同一个Peer 不在同一个peer则全部消息由自身发送
|
|
||||||
for (const msgId of nodeMsgIds) {
|
|
||||||
const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId);
|
|
||||||
if (!nodeMsgPeer) {
|
|
||||||
logger.logError('转发消息失败,未找到消息', msgId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const nodeMsg = (await NTQQMsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
|
|
||||||
srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid };
|
|
||||||
if (srcPeer.peerUid !== nodeMsg.peerUid) {
|
|
||||||
needSendSelf = true;
|
|
||||||
}
|
|
||||||
nodeMsgArray.push(nodeMsg);
|
|
||||||
}
|
|
||||||
nodeMsgIds = nodeMsgArray.map(msg => msg.msgId);
|
|
||||||
let retMsgIds: string[] = [];
|
|
||||||
if (needSendSelf) {
|
|
||||||
for (const [, msg] of nodeMsgArray.entries()) {
|
|
||||||
if (msg.peerUid === coreContext.selfInfo.uid){
|
|
||||||
retMsgIds.push(msg.msgId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const ClonedMsg = await cloneMsg(coreContext, msg);
|
|
||||||
if (ClonedMsg) retMsgIds.push(ClonedMsg.msgId);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
retMsgIds = nodeMsgIds;
|
|
||||||
}
|
|
||||||
if (retMsgIds.length === 0) throw Error('转发消息失败,生成节点为空');
|
|
||||||
try {
|
|
||||||
logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
|
|
||||||
return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds);
|
|
||||||
} catch (e) {
|
|
||||||
logger.logError('forward failed', e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -18,7 +18,7 @@ export default class GetRecentContact extends BaseAction<Payload, any> {
|
|||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
||||||
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
|
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
|
||||||
const ret = await NTQQUserApi.getRecentContactListSnapShot(parseInt((payload.count || 10).toString()));
|
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 NTQQMsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]);
|
||||||
if (FastMsg.msgList.length > 0) {
|
if (FastMsg.msgList.length > 0) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,422 +0,0 @@
|
|||||||
import {
|
|
||||||
AtType,
|
|
||||||
ElementType,
|
|
||||||
FaceIndex,
|
|
||||||
FaceType,
|
|
||||||
NapCatCore,
|
|
||||||
PicType,
|
|
||||||
SendArkElement,
|
|
||||||
SendFaceElement,
|
|
||||||
SendFileElement,
|
|
||||||
SendMarkdownElement,
|
|
||||||
SendMarketFaceElement,
|
|
||||||
SendPicElement,
|
|
||||||
SendPttElement,
|
|
||||||
SendReplyElement,
|
|
||||||
sendShareLocationElement,
|
|
||||||
SendTextElement,
|
|
||||||
SendVideoElement,
|
|
||||||
viedo_type,
|
|
||||||
} from '@/core';
|
|
||||||
import * as fsnormal from 'node:fs';
|
|
||||||
import { promises as fs } from 'node:fs';
|
|
||||||
import ffmpeg from 'fluent-ffmpeg';
|
|
||||||
import { calculateFileMD5, isGIF } from '@/common/utils/file';
|
|
||||||
import { defaultVideoThumbB64, getVideoInfo } from '@/common/utils/video';
|
|
||||||
import { encodeSilk } from '@/common/utils/audio';
|
|
||||||
import faceConfig from '@/core/external/face_config.json';
|
|
||||||
import * as pathLib from 'node:path';
|
|
||||||
|
|
||||||
export class SendMsgElementConstructor {
|
|
||||||
static location(CoreContext: NapCatCore): sendShareLocationElement {
|
|
||||||
return {
|
|
||||||
elementType: ElementType.SHARELOCATION,
|
|
||||||
elementId: '',
|
|
||||||
shareLocationElement: {
|
|
||||||
text: '测试',
|
|
||||||
ext: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static text(CoreContext: NapCatCore, content: string): SendTextElement {
|
|
||||||
return {
|
|
||||||
elementType: ElementType.TEXT,
|
|
||||||
elementId: '',
|
|
||||||
textElement: {
|
|
||||||
content,
|
|
||||||
atType: AtType.notAt,
|
|
||||||
atUid: '',
|
|
||||||
atTinyId: '',
|
|
||||||
atNtUid: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static at(CoreContext: NapCatCore, atUid: string, atNtUid: string, atType: AtType, atName: string): SendTextElement {
|
|
||||||
return {
|
|
||||||
elementType: ElementType.TEXT,
|
|
||||||
elementId: '',
|
|
||||||
textElement: {
|
|
||||||
content: `@${atName}`,
|
|
||||||
atType,
|
|
||||||
atUid,
|
|
||||||
atTinyId: '',
|
|
||||||
atNtUid,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static reply(CoreContext: NapCatCore, msgSeq: string, msgId: string, senderUin: string, senderUinStr: string): SendReplyElement {
|
|
||||||
return {
|
|
||||||
elementType: ElementType.REPLY,
|
|
||||||
elementId: '',
|
|
||||||
replyElement: {
|
|
||||||
replayMsgSeq: msgSeq, // raw.msgSeq
|
|
||||||
replayMsgId: msgId, // raw.msgId
|
|
||||||
senderUin: senderUin,
|
|
||||||
senderUinStr: senderUinStr,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static async pic(coreContext: NapCatCore, picPath: string, summary: string = '', subType: 0 | 1 = 0): Promise<SendPicElement> {
|
|
||||||
const NTQQGroupApi = coreContext.apis.GroupApi;
|
|
||||||
const NTQQUserApi = coreContext.apis.UserApi;
|
|
||||||
const NTQQFileApi = coreContext.apis.FileApi;
|
|
||||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
|
||||||
const NTQQFriendApi = coreContext.apis.FriendApi;
|
|
||||||
const logger = coreContext.context.logger;
|
|
||||||
const { md5, fileName, path, fileSize } = await NTQQFileApi.uploadFile(picPath, ElementType.PIC, subType);
|
|
||||||
if (fileSize === 0) {
|
|
||||||
throw '文件异常,大小为0';
|
|
||||||
}
|
|
||||||
const imageSize = await NTQQFileApi.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,
|
|
||||||
};
|
|
||||||
//logDebug('图片信息', picElement);
|
|
||||||
return {
|
|
||||||
elementType: ElementType.PIC,
|
|
||||||
elementId: '',
|
|
||||||
picElement,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static async file(coreContext: NapCatCore, filePath: string, fileName: string = '', folderId: string = ''): Promise<SendFileElement> {
|
|
||||||
const NTQQGroupApi = coreContext.apis.GroupApi;
|
|
||||||
const NTQQUserApi = coreContext.apis.UserApi;
|
|
||||||
const NTQQFileApi = coreContext.apis.FileApi;
|
|
||||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
|
||||||
const NTQQFriendApi = coreContext.apis.FriendApi;
|
|
||||||
const logger = coreContext.context.logger;
|
|
||||||
const { md5, fileName: _fileName, path, fileSize } = await NTQQFileApi.uploadFile(filePath, ElementType.FILE);
|
|
||||||
if (fileSize === 0) {
|
|
||||||
throw '文件异常,大小为0';
|
|
||||||
}
|
|
||||||
const element: SendFileElement = {
|
|
||||||
elementType: ElementType.FILE,
|
|
||||||
elementId: '',
|
|
||||||
fileElement: {
|
|
||||||
fileName: fileName || _fileName,
|
|
||||||
folderId: folderId,
|
|
||||||
'filePath': path!,
|
|
||||||
'fileSize': (fileSize).toString(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async video(coreContext: NapCatCore, filePath: string, fileName: string = '', diyThumbPath: string = '', videotype: viedo_type = viedo_type.VIDEO_FORMAT_MP4): Promise<SendVideoElement> {
|
|
||||||
const NTQQFileApi = coreContext.apis.FileApi;
|
|
||||||
const logger = coreContext.context.logger;
|
|
||||||
const { fileName: _fileName, path, fileSize, md5 } = await NTQQFileApi.uploadFile(filePath, ElementType.VIDEO);
|
|
||||||
if (fileSize === 0) {
|
|
||||||
throw '文件异常,大小为0';
|
|
||||||
}
|
|
||||||
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
|
|
||||||
thumb = pathLib.dirname(thumb);
|
|
||||||
// log("thumb 目录", thumb)
|
|
||||||
let videoInfo = {
|
|
||||||
width: 1920, height: 1080,
|
|
||||||
time: 15,
|
|
||||||
format: 'mp4',
|
|
||||||
size: fileSize,
|
|
||||||
filePath,
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
videoInfo = await getVideoInfo(path, logger);
|
|
||||||
//logDebug('视频信息', videoInfo);
|
|
||||||
} catch (e) {
|
|
||||||
logger.logError('获取视频信息失败', e);
|
|
||||||
}
|
|
||||||
const createThumb = new Promise<string | undefined>((resolve, reject) => {
|
|
||||||
const thumbFileName = `${md5}_0.png`;
|
|
||||||
const thumbPath = pathLib.join(thumb, thumbFileName);
|
|
||||||
ffmpeg(filePath)
|
|
||||||
.on('end', () => {
|
|
||||||
})
|
|
||||||
.on('error', (err) => {
|
|
||||||
logger.logDebug('获取视频封面失败,使用默认封面', err);
|
|
||||||
if (diyThumbPath) {
|
|
||||||
fs.copyFile(diyThumbPath, thumbPath).then(() => {
|
|
||||||
resolve(thumbPath);
|
|
||||||
}).catch(reject);
|
|
||||||
} else {
|
|
||||||
fsnormal.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64'));
|
|
||||||
resolve(thumbPath);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.screenshots({
|
|
||||||
timestamps: [0],
|
|
||||||
filename: thumbFileName,
|
|
||||||
folder: thumb,
|
|
||||||
size: videoInfo.width + 'x' + videoInfo.height,
|
|
||||||
}).on('end', () => {
|
|
||||||
resolve(thumbPath);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const thumbPath = new Map();
|
|
||||||
const _thumbPath = await createThumb;
|
|
||||||
const thumbSize = _thumbPath ? (await fs.stat(_thumbPath)).size : 0;
|
|
||||||
// log("生成缩略图", _thumbPath)
|
|
||||||
thumbPath.set(0, _thumbPath);
|
|
||||||
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : "";
|
|
||||||
const element: SendVideoElement = {
|
|
||||||
elementType: ElementType.VIDEO,
|
|
||||||
elementId: '',
|
|
||||||
videoElement: {
|
|
||||||
fileName: fileName || _fileName,
|
|
||||||
filePath: path,
|
|
||||||
videoMd5: md5,
|
|
||||||
thumbMd5,
|
|
||||||
fileTime: videoInfo.time,
|
|
||||||
thumbPath: thumbPath,
|
|
||||||
thumbSize,
|
|
||||||
thumbWidth: videoInfo.width,
|
|
||||||
thumbHeight: videoInfo.height,
|
|
||||||
fileSize: '' + fileSize,
|
|
||||||
//fileFormat: videotype
|
|
||||||
// fileUuid: "",
|
|
||||||
// transferStatus: 0,
|
|
||||||
// progress: 0,
|
|
||||||
// invalidState: 0,
|
|
||||||
// fileSubId: "",
|
|
||||||
// fileBizId: null,
|
|
||||||
// originVideoMd5: "",
|
|
||||||
// fileFormat: 2,
|
|
||||||
// import_rich_media_context: null,
|
|
||||||
// sourceVideoCodecFormat: 2
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// "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 element;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async ptt(coreContext: NapCatCore, pttPath: string): Promise<SendPttElement> {
|
|
||||||
const NTQQGroupApi = coreContext.apis.GroupApi;
|
|
||||||
const NTQQUserApi = coreContext.apis.UserApi;
|
|
||||||
const NTQQFileApi = coreContext.apis.FileApi;
|
|
||||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
|
||||||
const NTQQFriendApi = coreContext.apis.FriendApi;
|
|
||||||
const logger = coreContext.context.logger;
|
|
||||||
const {
|
|
||||||
converted,
|
|
||||||
path: silkPath,
|
|
||||||
duration,
|
|
||||||
} = await encodeSilk(pttPath, coreContext.NapCatTempPath, coreContext.context.logger);
|
|
||||||
// log("生成语音", silkPath, duration);
|
|
||||||
if (!silkPath) {
|
|
||||||
throw '语音转换失败, 请检查语音文件是否正常';
|
|
||||||
}
|
|
||||||
const { md5, fileName, path, fileSize } = await NTQQFileApi.uploadFile(silkPath!, ElementType.PTT);
|
|
||||||
if (fileSize === 0) {
|
|
||||||
throw '文件异常,大小为0';
|
|
||||||
}
|
|
||||||
if (converted) {
|
|
||||||
fs.unlink(silkPath).then();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
elementType: ElementType.PTT,
|
|
||||||
elementId: '',
|
|
||||||
pttElement: {
|
|
||||||
fileName: fileName,
|
|
||||||
filePath: path,
|
|
||||||
md5HexStr: md5,
|
|
||||||
fileSize: fileSize,
|
|
||||||
// duration: Math.max(1, Math.round(fileSize / 1024 / 3)), // 一秒钟大概是3kb大小, 小于1秒的按1秒算
|
|
||||||
duration: duration || 1,
|
|
||||||
formatType: 1,
|
|
||||||
voiceType: 1,
|
|
||||||
voiceChangeType: 0,
|
|
||||||
canConvert2Text: true,
|
|
||||||
waveAmplitudes: [
|
|
||||||
0, 18, 9, 23, 16, 17, 16, 15, 44, 17, 24, 20, 14, 15, 17,
|
|
||||||
],
|
|
||||||
fileSubId: '',
|
|
||||||
playState: 1,
|
|
||||||
autoConvertText: 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeIQQNTWrapperSession sendMsg [
|
|
||||||
// "0",
|
|
||||||
// {
|
|
||||||
// "peerUid": "u_e_RIxgTs2NaJ68h0PwOPSg",
|
|
||||||
// "chatType": 1,
|
|
||||||
// "guildId": ""
|
|
||||||
// },
|
|
||||||
// [
|
|
||||||
// {
|
|
||||||
// "elementId": "0",
|
|
||||||
// "elementType": 6,
|
|
||||||
// "faceElement": {
|
|
||||||
// "faceIndex": 0,
|
|
||||||
// "faceType": 5,
|
|
||||||
// "msgType": 0,
|
|
||||||
// "pokeType": 1,
|
|
||||||
// "pokeStrength": 0
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ],
|
|
||||||
// {}
|
|
||||||
// ]
|
|
||||||
static face(CoreContext: NapCatCore, faceId: number): SendFaceElement {
|
|
||||||
// 从face_config.json中获取表情名称
|
|
||||||
const sysFaces = faceConfig.sysface;
|
|
||||||
const emojiFaces = faceConfig.emoji;
|
|
||||||
const face: any = sysFaces.find((face) => face.QSid === faceId.toString());
|
|
||||||
faceId = parseInt(faceId.toString());
|
|
||||||
// let faceType = parseInt(faceId.toString().substring(0, 1));
|
|
||||||
let faceType = 1;
|
|
||||||
if (faceId >= 222) {
|
|
||||||
faceType = 2;
|
|
||||||
}
|
|
||||||
if (face.AniStickerType) {
|
|
||||||
faceType = 3;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
elementType: ElementType.FACE,
|
|
||||||
elementId: '',
|
|
||||||
faceElement: {
|
|
||||||
faceIndex: faceId,
|
|
||||||
faceType,
|
|
||||||
faceText: face.QDes,
|
|
||||||
stickerId: face.AniStickerId,
|
|
||||||
stickerType: face.AniStickerType,
|
|
||||||
packId: face.AniStickerPackId,
|
|
||||||
sourceType: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static mface(CoreContext: NapCatCore, emojiPackageId: number, emojiId: string, key: string, faceName: string): SendMarketFaceElement {
|
|
||||||
return {
|
|
||||||
elementType: ElementType.MFACE,
|
|
||||||
marketFaceElement: {
|
|
||||||
emojiPackageId,
|
|
||||||
emojiId,
|
|
||||||
key,
|
|
||||||
faceName: faceName || '[商城表情]',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static dice(CoreContext: NapCatCore, resultId: number | null): SendFaceElement {
|
|
||||||
// 实际测试并不能控制结果
|
|
||||||
|
|
||||||
// 随机1到6
|
|
||||||
// if (isNull(resultId)) resultId = Math.floor(Math.random() * 6) + 1;
|
|
||||||
return {
|
|
||||||
elementType: ElementType.FACE,
|
|
||||||
elementId: '',
|
|
||||||
faceElement: {
|
|
||||||
faceIndex: FaceIndex.dice,
|
|
||||||
faceType: FaceType.dice,
|
|
||||||
'faceText': '[骰子]',
|
|
||||||
'packId': '1',
|
|
||||||
'stickerId': '33',
|
|
||||||
'sourceType': 1,
|
|
||||||
'stickerType': 2,
|
|
||||||
// resultId: resultId.toString(),
|
|
||||||
'surpriseId': '',
|
|
||||||
// "randomType": 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 猜拳(石头剪刀布)表情
|
|
||||||
static rps(CoreContext: NapCatCore, resultId: number | null): SendFaceElement {
|
|
||||||
// 实际测试并不能控制结果
|
|
||||||
// if (isNull(resultId)) resultId = Math.floor(Math.random() * 3) + 1;
|
|
||||||
return {
|
|
||||||
elementType: ElementType.FACE,
|
|
||||||
elementId: '',
|
|
||||||
faceElement: {
|
|
||||||
'faceIndex': FaceIndex.RPS,
|
|
||||||
'faceText': '[包剪锤]',
|
|
||||||
'faceType': 3,
|
|
||||||
'packId': '1',
|
|
||||||
'stickerId': '34',
|
|
||||||
'sourceType': 1,
|
|
||||||
'stickerType': 2,
|
|
||||||
// 'resultId': resultId.toString(),
|
|
||||||
'surpriseId': '',
|
|
||||||
// "randomType": 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static ark(CoreContext: NapCatCore, data: any): SendArkElement {
|
|
||||||
if (typeof data !== 'string') {
|
|
||||||
data = JSON.stringify(data);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
elementType: ElementType.ARK,
|
|
||||||
elementId: '',
|
|
||||||
arkElement: {
|
|
||||||
bytesData: data,
|
|
||||||
linkInfo: null,
|
|
||||||
subElementType: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static markdown(CoreContext: NapCatCore, content: string): SendMarkdownElement {
|
|
||||||
return {
|
|
||||||
elementType: ElementType.MARKDOWN,
|
|
||||||
elementId: '',
|
|
||||||
markdownElement: {
|
|
||||||
content,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,5 +1,4 @@
|
|||||||
export * from './config';
|
export * from './config';
|
||||||
export * from './converter';
|
export * from './converter';
|
||||||
export * from './quick';
|
export * from './quick';
|
||||||
export * from './genMessage';
|
|
||||||
export * from './event';
|
export * from './event';
|
||||||
|
@@ -13,7 +13,7 @@ import {
|
|||||||
QuickActionGroupRequest,
|
QuickActionGroupRequest,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { isNull } from '@/common/utils/helper';
|
import { isNull } from '@/common/utils/helper';
|
||||||
import { createSendElements, normalize, sendMsg } from '../action/msg/SendMsg';
|
import { normalize, sendMsg } from '../action/msg/SendMsg';
|
||||||
import { NapCatOneBot11Adapter } from '..';
|
import { NapCatOneBot11Adapter } from '..';
|
||||||
|
|
||||||
async function handleMsg(coreContext: NapCatCore, obContext: NapCatOneBot11Adapter, msg: OB11Message, quickAction: QuickAction) {
|
async function handleMsg(coreContext: NapCatCore, obContext: NapCatOneBot11Adapter, msg: OB11Message, quickAction: QuickAction) {
|
||||||
@@ -53,7 +53,7 @@ async function handleMsg(coreContext: NapCatCore, obContext: NapCatOneBot11Adapt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
replyMessage = replyMessage.concat(normalize(reply, quickAction.auto_escape));
|
replyMessage = replyMessage.concat(normalize(reply, quickAction.auto_escape));
|
||||||
const { sendElements, deleteAfterSentFiles } = await createSendElements(coreContext, obContext, replyMessage, peer);
|
const { sendElements, deleteAfterSentFiles } = await obContext.apiContext.MsgApi.createSendElements(replyMessage, peer);
|
||||||
sendMsg(coreContext, peer, sendElements, deleteAfterSentFiles, false).then().catch(coreContext.context.logger.logError);
|
sendMsg(coreContext, peer, sendElements, deleteAfterSentFiles, false).then().catch(coreContext.context.logger.logError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,16 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
BuddyListener,
|
NodeIKernelBuddyListener,
|
||||||
BuddyReqType,
|
BuddyReqType,
|
||||||
ChatType,
|
ChatType,
|
||||||
GroupListener,
|
|
||||||
InstanceContext,
|
InstanceContext,
|
||||||
MsgListener,
|
NodeIKernelMsgListener,
|
||||||
NapCatCore,
|
NapCatCore,
|
||||||
RawMessage,
|
RawMessage,
|
||||||
SendStatusType,
|
SendStatusType,
|
||||||
GroupMemberRole,
|
GroupMemberRole,
|
||||||
GroupNotifyMsgType,
|
GroupNotifyMsgType,
|
||||||
GroupNotifyMsgStatus,
|
GroupNotifyMsgStatus,
|
||||||
|
DataSource,
|
||||||
|
NodeIKernelGroupListener,
|
||||||
} from '@/core';
|
} from '@/core';
|
||||||
import { OB11Config, OB11ConfigLoader } from '@/onebot/helper/config';
|
import { OB11Config, OB11ConfigLoader } from '@/onebot/helper/config';
|
||||||
import { OneBotApiContextType } from '@/onebot/types';
|
import { OneBotApiContextType } from '@/onebot/types';
|
||||||
@@ -218,7 +219,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initMsgListener() {
|
private initMsgListener() {
|
||||||
const msgListener = new MsgListener();
|
const msgListener = new NodeIKernelMsgListener();
|
||||||
msgListener.onInputStatusPush = async data => {
|
msgListener.onInputStatusPush = async data => {
|
||||||
const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin);
|
const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin);
|
||||||
this.context.logger.log(`[Notice] [输入状态] ${uin} ${data.statusText}`);
|
this.context.logger.log(`[Notice] [输入状态] ${uin} ${data.statusText}`);
|
||||||
@@ -283,7 +284,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initBuddyListener() {
|
private initBuddyListener() {
|
||||||
const buddyListener = new BuddyListener();
|
const buddyListener = new NodeIKernelBuddyListener();
|
||||||
|
|
||||||
buddyListener.onBuddyReqChange = async reqs => {
|
buddyListener.onBuddyReqChange = async reqs => {
|
||||||
this.core.apis.FriendApi.clearBuddyReqUnreadCnt();
|
this.core.apis.FriendApi.clearBuddyReqUnreadCnt();
|
||||||
@@ -318,7 +319,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initGroupListener() {
|
private initGroupListener() {
|
||||||
const groupListener = new GroupListener();
|
const groupListener = new NodeIKernelGroupListener();
|
||||||
|
|
||||||
groupListener.onGroupNotifiesUpdated = async (_, notifies) => {
|
groupListener.onGroupNotifiesUpdated = async (_, notifies) => {
|
||||||
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
|
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
|
||||||
@@ -425,9 +426,9 @@ export class NapCatOneBot11Adapter {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
groupListener.onMemberInfoChange = async (groupCode, changeType, members) => {
|
groupListener.onMemberInfoChange = async (groupCode, dataSource, members) => {
|
||||||
//this.context.logger.logDebug('收到群成员信息变动通知', groupCode, changeType);
|
//this.context.logger.logDebug('收到群成员信息变动通知', groupCode, changeType);
|
||||||
if (changeType === 0) {
|
if (dataSource === DataSource.LOCAL) {
|
||||||
const existMembers = this.core.apis.GroupApi.groupMemberCache.get(groupCode);
|
const existMembers = this.core.apis.GroupApi.groupMemberCache.get(groupCode);
|
||||||
if (!existMembers) return;
|
if (!existMembers) return;
|
||||||
members.forEach((member) => {
|
members.forEach((member) => {
|
||||||
|
@@ -94,7 +94,7 @@ export interface OB11MessageImage extends OB11MessageFileBase {
|
|||||||
type: OB11MessageDataType.image
|
type: OB11MessageDataType.image
|
||||||
data: OB11MessageFileBase['data'] & {
|
data: OB11MessageFileBase['data'] & {
|
||||||
summary?: string; // 图片摘要
|
summary?: string; // 图片摘要
|
||||||
subType?: PicSubType
|
sub_type?: PicSubType
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ export interface OB11MessageVideo extends OB11MessageFileBase {
|
|||||||
export interface OB11MessageAt {
|
export interface OB11MessageAt {
|
||||||
type: OB11MessageDataType.at;
|
type: OB11MessageDataType.at;
|
||||||
data: {
|
data: {
|
||||||
qq: `${number}` | 'all'
|
qq: string, // `${number}` | 'all'
|
||||||
name?: string
|
name?: string
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -156,20 +156,20 @@ export interface OB11MessageCustomMusic {
|
|||||||
|
|
||||||
export interface OB11MessageJson {
|
export interface OB11MessageJson {
|
||||||
type: OB11MessageDataType.json;
|
type: OB11MessageDataType.json;
|
||||||
data: { config: { token: string }, data: string };
|
data: { config?: { token: string }, data: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OB11MessageDice {
|
export interface OB11MessageDice {
|
||||||
type: OB11MessageDataType.dice,
|
type: OB11MessageDataType.dice,
|
||||||
data: {
|
data: {
|
||||||
result: number
|
result: number /* intended */ | string /* in fact */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OB11MessageRPS {
|
export interface OB11MessageRPS {
|
||||||
type: OB11MessageDataType.RPS,
|
type: OB11MessageDataType.RPS,
|
||||||
data: {
|
data: {
|
||||||
result: number
|
result: number | string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import type { SelfInfo } from '@/core/entities';
|
import type { SelfInfo } from '@/core/entities';
|
||||||
|
|
||||||
import { LogWrapper } from '@/common/utils/log';
|
import { LogWrapper } from '@/common/utils/log';
|
||||||
import { LoginListener, SessionListener } from '@/core/listeners';
|
import { NodeIKernelLoginListener, NodeIKernelSessionListener } from '@/core/listeners';
|
||||||
import { DependsAdapter, DispatcherAdapter, GlobalAdapter } from '@/core/adapters';
|
import { NodeIDispatcherAdapter, NodeIDependsAdapter, NodeIGlobalAdapter } from '@/core/adapters';
|
||||||
import { NapCatPathWrapper } from '@/common/framework/napcat';
|
import { NapCatPathWrapper } from '@/common/framework/napcat';
|
||||||
import {
|
import {
|
||||||
InstanceContext,
|
InstanceContext,
|
||||||
@@ -70,7 +70,7 @@ export async function NCoreInitShell() {
|
|||||||
},
|
},
|
||||||
thumb_config: { maxSide: 324, minSide: 48, longLimit: 6, density: 2 },
|
thumb_config: { maxSide: 324, minSide: 48, longLimit: 6, density: 2 },
|
||||||
},
|
},
|
||||||
new GlobalAdapter() as any,
|
new NodeIGlobalAdapter(),
|
||||||
);
|
);
|
||||||
loginService.initConfig({
|
loginService.initConfig({
|
||||||
machineId: '',
|
machineId: '',
|
||||||
@@ -93,7 +93,7 @@ export async function NCoreInitShell() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selfInfo = await new Promise<SelfInfo>((resolve, reject) => {
|
const selfInfo = await new Promise<SelfInfo>((resolve, reject) => {
|
||||||
const loginListener = new LoginListener();
|
const loginListener = new NodeIKernelLoginListener();
|
||||||
|
|
||||||
// from constructor
|
// from constructor
|
||||||
loginListener.onUserLoggedIn = (userid: string) => {
|
loginListener.onUserLoggedIn = (userid: string) => {
|
||||||
@@ -208,7 +208,7 @@ export async function NCoreInitShell() {
|
|||||||
selfInfo.uid,
|
selfInfo.uid,
|
||||||
dataPath,
|
dataPath,
|
||||||
);
|
);
|
||||||
const sessionListener = new SessionListener();
|
const sessionListener = new NodeIKernelSessionListener();
|
||||||
sessionListener.onSessionInitComplete = (r: unknown) => {
|
sessionListener.onSessionInitComplete = (r: unknown) => {
|
||||||
if (r === 0) {
|
if (r === 0) {
|
||||||
resolve();
|
resolve();
|
||||||
@@ -218,8 +218,8 @@ export async function NCoreInitShell() {
|
|||||||
};
|
};
|
||||||
session.init(
|
session.init(
|
||||||
sessionConfig,
|
sessionConfig,
|
||||||
new DependsAdapter() as any,
|
new NodeIDependsAdapter(),
|
||||||
new DispatcherAdapter() as any,
|
new NodeIDispatcherAdapter(),
|
||||||
sessionListener as any,
|
sessionListener as any,
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
|
@@ -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.8', 'napcat-update-button', 'secondary'),
|
SettingButton('V2.2.11', 'napcat-update-button', 'secondary'),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
void 0,
|
void 0,
|
||||||
SettingButton("V2.2.8", "napcat-update-button", "secondary")
|
SettingButton("V2.2.11", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
Reference in New Issue
Block a user