mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
79 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
67fb74d3c2 | ||
![]() |
dc04cfc1b3 | ||
![]() |
6b346ee1de | ||
![]() |
73b6d3be84 | ||
![]() |
1ff6ce2343 | ||
![]() |
c145935d46 | ||
![]() |
e9ede6924e | ||
![]() |
515a21761d | ||
![]() |
8d6397028b | ||
![]() |
7e74578312 | ||
![]() |
166c30fe2c | ||
![]() |
66c1bab629 | ||
![]() |
7ae8fd60c4 | ||
![]() |
96b5bec5ab | ||
![]() |
d9851493df | ||
![]() |
5548644aeb | ||
![]() |
e3fcd91b2d | ||
![]() |
58cd38c4a8 | ||
![]() |
f0e376d06b | ||
![]() |
3dc529edf4 | ||
![]() |
afcdd01c0d | ||
![]() |
1164877e9a | ||
![]() |
fe92a449ba | ||
![]() |
401b0e2bd0 | ||
![]() |
cf9c71fcc1 | ||
![]() |
15a2400069 | ||
![]() |
d68a39b49e | ||
![]() |
066ca22e24 | ||
![]() |
0418b926fe | ||
![]() |
be40bbdf40 | ||
![]() |
df4f42e79e | ||
![]() |
5f80058f70 | ||
![]() |
0cbe59052d | ||
![]() |
af28a26e37 | ||
![]() |
70c596df93 | ||
![]() |
748b51428c | ||
![]() |
8ad746397c | ||
![]() |
45baed2f9a | ||
![]() |
74185f2d33 | ||
![]() |
90a91e4105 | ||
![]() |
11aa3a0315 | ||
![]() |
0c2e39214f | ||
![]() |
d89620d7a6 | ||
![]() |
edf80775b7 | ||
![]() |
46e56ac726 | ||
![]() |
40b2f6bfd6 | ||
![]() |
911e4921e2 | ||
![]() |
1db9bb419d | ||
![]() |
c6241a94e3 | ||
![]() |
1cbf75ca36 | ||
![]() |
8f85c897c8 | ||
![]() |
29c31b7aba | ||
![]() |
402919d6f2 | ||
![]() |
82608dd5ff | ||
![]() |
f312368df2 | ||
![]() |
374fc64427 | ||
![]() |
95bd74bb0d | ||
![]() |
a9f5069649 | ||
![]() |
957f7ffd8d | ||
![]() |
336dd3ce10 | ||
![]() |
47a7295477 | ||
![]() |
341a0e1c2a | ||
![]() |
c4f73d0eb8 | ||
![]() |
bd9258bae4 | ||
![]() |
e3b3260aa0 | ||
![]() |
676766c99e | ||
![]() |
1025a07593 | ||
![]() |
00c3fcd033 | ||
![]() |
b8457d4aff | ||
![]() |
a2ecf10d19 | ||
![]() |
1e63a2a7e7 | ||
![]() |
964014fc5c | ||
![]() |
fc2bb6d8c3 | ||
![]() |
1b10252d76 | ||
![]() |
ad8af12a10 | ||
![]() |
b040c9b118 | ||
![]() |
f6da7da90b | ||
![]() |
a745185408 | ||
![]() |
d3336f9027 |
@@ -5,7 +5,7 @@ if %errorLevel% == 0 (
|
||||
echo Administrator mode detected.
|
||||
) else (
|
||||
echo Please run this script in administrator mode.
|
||||
powershell -Command "Start-Process 'cmd.exe' -ArgumentList '/c cd /d \"%cd%\" && \"%~f0\"' -Verb runAs"
|
||||
powershell -Command "Start-Process 'cmd.exe' -ArgumentList '/c cd /d \"%cd%\" && \"%~f0\" %1' -Verb runAs"
|
||||
exit
|
||||
)
|
||||
|
||||
@@ -35,6 +35,6 @@ if not exist "%QQpath%" (
|
||||
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
||||
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
|
||||
|
||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%"
|
||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %1
|
||||
|
||||
REM "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" 123456
|
@@ -5,7 +5,7 @@ if %errorLevel% == 0 (
|
||||
echo Administrator mode detected.
|
||||
) else (
|
||||
echo Please run this script in administrator mode.
|
||||
powershell -Command "Start-Process 'wt.exe' -ArgumentList 'cmd /c cd /d \"%cd%\" && \"%~f0\"' -Verb runAs"
|
||||
powershell -Command "Start-Process 'wt.exe' -ArgumentList 'cmd /c cd /d \"%cd%\" && \"%~f0\" %1' -Verb runAs"
|
||||
exit
|
||||
)
|
||||
|
||||
@@ -36,6 +36,4 @@ if not exist "%QQpath%" (
|
||||
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
||||
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
|
||||
|
||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%"
|
||||
|
||||
REM "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" 123456
|
||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %1
|
4
launcher/quickLoginExample.bat
Normal file
4
launcher/quickLoginExample.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
REM ./launcher.bat 123456
|
||||
REM ./launcher-win10.bat 123456
|
||||
REM 带有REM的为注释 删掉你需要的系统的那行REM这三个单词 修改QQ本脚本启动即可
|
@@ -4,7 +4,7 @@
|
||||
"name": "NapCatQQ",
|
||||
"slug": "NapCat.Framework",
|
||||
"description": "高性能的 OneBot 11 协议实现",
|
||||
"version": "2.4.2",
|
||||
"version": "2.5.3",
|
||||
"icon": "./logo.png",
|
||||
"authors": [
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"name": "napcat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "2.4.2",
|
||||
"version": "2.5.3",
|
||||
"scripts": {
|
||||
"build:framework": "vite build --mode framework",
|
||||
"build:shell": "vite build --mode shell",
|
||||
@@ -57,6 +57,7 @@
|
||||
"image-size": "^1.1.1",
|
||||
"json-schema-to-ts": "^3.1.0",
|
||||
"log4js": "^6.9.1",
|
||||
"protobufjs": "~7.4.0",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"silk-wasm": "^3.6.1",
|
||||
"strtok3": "8.0.1",
|
||||
|
@@ -1,66 +1,67 @@
|
||||
import fs from 'fs';
|
||||
import { encode, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
|
||||
import fsPromise from 'fs/promises';
|
||||
import path from 'node:path';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { spawn } from 'node:child_process';
|
||||
import { encode, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
|
||||
import { LogWrapper } from './log';
|
||||
|
||||
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) {
|
||||
async function guessDuration(pttPath: string) {
|
||||
const pttFileInfo = await fsPromise.stat(pttPath);
|
||||
let duration = pttFileInfo.size / 1024 / 3; // 3kb/s
|
||||
duration = Math.floor(duration);
|
||||
duration = Math.max(1, duration);
|
||||
logger.log('通过文件大小估算语音的时长:', duration);
|
||||
return duration;
|
||||
}
|
||||
const ALLOW_SAMPLE_RATE = [8000, 12000, 16000, 24000, 32000, 44100, 48000];
|
||||
const EXIT_CODES = [0, 255];
|
||||
const FFMPEG_PATH = process.env.FFMPEG_PATH || 'ffmpeg';
|
||||
|
||||
async function guessDuration(pttPath: string, logger: LogWrapper) {
|
||||
const pttFileInfo = await fsPromise.stat(pttPath);
|
||||
const duration = Math.max(1, Math.floor(pttFileInfo.size / 1024 / 3)); // 3kb/s
|
||||
logger.log('通过文件大小估算语音的时长:', duration);
|
||||
return duration;
|
||||
}
|
||||
|
||||
async function convert(filePath: string, pcmPath: string, logger: LogWrapper): Promise<Buffer> {
|
||||
return new Promise<Buffer>((resolve, reject) => {
|
||||
const cp = spawn(FFMPEG_PATH, ['-y', '-i', filePath, '-ar', '24000', '-ac', '1', '-f', 's16le', pcmPath]);
|
||||
cp.on('error', (err: Error) => {
|
||||
logger.log('FFmpeg处理转换出错: ', err.message);
|
||||
reject(err);
|
||||
});
|
||||
cp.on('exit', async (code, signal) => {
|
||||
if (code == null || EXIT_CODES.includes(code)) {
|
||||
try {
|
||||
const data = await fsPromise.readFile(pcmPath);
|
||||
await fsPromise.unlink(pcmPath);
|
||||
resolve(data);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
} else {
|
||||
logger.log(`FFmpeg exit: code=${code ?? 'unknown'} sig=${signal ?? 'unknown'}`);
|
||||
reject(new Error('FFmpeg处理转换失败'));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function handleWavFile(
|
||||
file: Buffer, filePath: string, pcmPath: string, logger: LogWrapper
|
||||
): Promise<{input: Buffer, sampleRate: number}> {
|
||||
const { fmt } = getWavFileInfo(file);
|
||||
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
|
||||
return {input: await convert(filePath, pcmPath, logger), sampleRate: 24000};
|
||||
}
|
||||
return {input: file, sampleRate: fmt.sampleRate};
|
||||
}
|
||||
|
||||
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) {
|
||||
try {
|
||||
const file = await fsPromise.readFile(filePath);
|
||||
const pttPath = path.join(TEMP_DIR, randomUUID());
|
||||
if (!isSilk(file)) {
|
||||
logger.log(`语音文件${filePath}需要转换成silk`);
|
||||
const _isWav = isWav(file);
|
||||
const pcmPath = pttPath + '.pcm';
|
||||
let sampleRate = 0;
|
||||
const convert = () => {
|
||||
return new Promise<Buffer>((resolve, reject) => {
|
||||
// todo: 通过配置文件获取ffmpeg路径
|
||||
const ffmpegPath = process.env.FFMPEG_PATH || 'ffmpeg';
|
||||
const cp = spawn(ffmpegPath, ['-y', '-i', filePath, '-ar', '24000', '-ac', '1', '-f', 's16le', pcmPath]);
|
||||
cp.on('error', err => {
|
||||
logger.log('FFmpeg处理转换出错: ', err.message);
|
||||
return reject(err);
|
||||
});
|
||||
cp.on('exit', (code, signal) => {
|
||||
const EXIT_CODES = [0, 255];
|
||||
if (code == null || EXIT_CODES.includes(code)) {
|
||||
sampleRate = 24000;
|
||||
const data = fs.readFileSync(pcmPath);
|
||||
fs.unlink(pcmPath, (err) => {
|
||||
});
|
||||
return resolve(data);
|
||||
}
|
||||
logger.log(`FFmpeg exit: code=${code ?? 'unknown'} sig=${signal ?? 'unknown'}`);
|
||||
reject(Error('FFmpeg处理转换失败'));
|
||||
});
|
||||
});
|
||||
};
|
||||
let input: Buffer;
|
||||
if (!_isWav) {
|
||||
input = await convert();
|
||||
} else {
|
||||
input = file;
|
||||
const allowSampleRate = [8000, 12000, 16000, 24000, 32000, 44100, 48000];
|
||||
const { fmt } = getWavFileInfo(input);
|
||||
// log(`wav文件信息`, fmt)
|
||||
if (!allowSampleRate.includes(fmt.sampleRate)) {
|
||||
input = await convert();
|
||||
}
|
||||
}
|
||||
const pcmPath = `${pttPath}.pcm`;
|
||||
const { input, sampleRate } = isWav(file)
|
||||
? (await handleWavFile(file, filePath, pcmPath, logger))
|
||||
: {input: await convert(filePath, pcmPath, logger), sampleRate: 24000};
|
||||
const silk = await encode(input, sampleRate);
|
||||
fs.writeFileSync(pttPath, silk.data);
|
||||
await fsPromise.writeFile(pttPath, silk.data);
|
||||
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
||||
return {
|
||||
converted: true,
|
||||
@@ -68,15 +69,13 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
||||
duration: silk.duration / 1000,
|
||||
};
|
||||
} else {
|
||||
const silk = file;
|
||||
let duration = 0;
|
||||
try {
|
||||
duration = getDuration(silk) / 1000;
|
||||
duration = getDuration(file) / 1000;
|
||||
} catch (e: any) {
|
||||
logger.log('获取语音文件时长失败, 使用文件大小推测时长', filePath, e.stack);
|
||||
duration = await guessDuration(filePath);
|
||||
duration = await guessDuration(filePath, logger);
|
||||
}
|
||||
|
||||
return {
|
||||
converted: false,
|
||||
path: filePath,
|
||||
@@ -87,4 +86,4 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
||||
logger.logError('convert silk failed', error.stack);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
@@ -128,6 +128,7 @@ export async function httpDownload(options: string | HttpDownloadOptions): Promi
|
||||
let url: string;
|
||||
let headers: Record<string, string> = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36',
|
||||
'referer': typeof options === 'string' ? options : options.url,
|
||||
};
|
||||
if (typeof options === 'string') {
|
||||
url = options;
|
||||
@@ -160,8 +161,7 @@ type Uri2LocalRes = {
|
||||
errMsg: string,
|
||||
fileName: string,
|
||||
ext: string,
|
||||
path: string,
|
||||
isLocal: boolean
|
||||
path: string
|
||||
}
|
||||
|
||||
export async function checkFileV2(filePath: string) {
|
||||
@@ -194,7 +194,6 @@ export async function checkUriType(Uri: string) {
|
||||
return undefined;
|
||||
}, Uri);
|
||||
if (LocalFileRet) return LocalFileRet;
|
||||
|
||||
const OtherFileRet = await solveProblem((uri: string) => {
|
||||
//再判断是否是Http
|
||||
if (uri.startsWith('http://') || uri.startsWith('https://')) {
|
||||
@@ -206,13 +205,13 @@ export async function checkUriType(Uri: string) {
|
||||
}
|
||||
if (uri.startsWith('file://')) {
|
||||
let filePath: string;
|
||||
// await fs.copyFile(url.pathname, filePath);
|
||||
const pathname = decodeURIComponent(new URL(uri).pathname);
|
||||
if (process.platform === 'win32') {
|
||||
filePath = pathname.slice(1);
|
||||
} else {
|
||||
filePath = pathname;
|
||||
}
|
||||
|
||||
return { Uri: filePath, Type: FileUriType.Local };
|
||||
}
|
||||
if (uri.startsWith('data:')) {
|
||||
@@ -228,35 +227,42 @@ export async function checkUriType(Uri: string) {
|
||||
export async function uri2local(dir: string, uri: string, filename: string | undefined = undefined): Promise<Uri2LocalRes> {
|
||||
const { Uri: HandledUri, Type: UriType } = await checkUriType(uri);
|
||||
//解析失败
|
||||
const tempName = randomUUID();
|
||||
if (!filename) filename = randomUUID();
|
||||
//解析Http和Https协议
|
||||
|
||||
if (UriType == FileUriType.Unknown) {
|
||||
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
|
||||
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '' };
|
||||
}
|
||||
//解析File协议和本地文件
|
||||
if (UriType == FileUriType.Local) {
|
||||
const fileExt = path.extname(HandledUri);
|
||||
let filename = path.basename(HandledUri, fileExt);
|
||||
filename += fileExt;
|
||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: HandledUri, isLocal: true };
|
||||
//复制文件到临时文件并保持后缀
|
||||
const filenameTemp = tempName + fileExt;
|
||||
const filePath = path.join(dir, filenameTemp);
|
||||
fs.copyFileSync(HandledUri, filePath);
|
||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
|
||||
}
|
||||
//接下来都要有文件名
|
||||
if (!filename) filename = randomUUID();
|
||||
//解析Http和Https协议
|
||||
|
||||
if (UriType == FileUriType.Remote) {
|
||||
const pathInfo = path.parse(decodeURIComponent(new URL(HandledUri).pathname));
|
||||
if (pathInfo.name) {
|
||||
filename = pathInfo.name;
|
||||
const pathlen = 200 - dir.length - pathInfo.name.length;
|
||||
filename = pathlen > 0 ? pathInfo.name.substring(0, pathlen) : pathInfo.name.substring(pathInfo.name.length, pathInfo.name.length - 10);//过长截断
|
||||
if (pathInfo.ext) {
|
||||
filename += pathInfo.ext;
|
||||
}
|
||||
}
|
||||
filename = filename.replace(/[/\\:*?"<>|]/g, '_');
|
||||
const fileExt = path.extname(HandledUri);
|
||||
const filePath = path.join(dir, filename);
|
||||
const fileExt = path.extname(HandledUri).replace(/[/\\:*?"<>|]/g, '_').substring(0, 10);
|
||||
const filePath = path.join(dir, tempName + fileExt);
|
||||
const buffer = await httpDownload(HandledUri);
|
||||
fs.writeFileSync(filePath, buffer);
|
||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: false };
|
||||
//没有文件就创建
|
||||
fs.writeFileSync(filePath, buffer, { flag: 'wx' });
|
||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
|
||||
}
|
||||
//解析Base64
|
||||
if (UriType == FileUriType.Base64) {
|
||||
@@ -271,7 +277,7 @@ export async function uri2local(dir: string, uri: string, filename: string | und
|
||||
fileExt = ext;
|
||||
filename = filename + '.' + ext;
|
||||
}
|
||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: false };
|
||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath };
|
||||
}
|
||||
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
|
||||
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '' };
|
||||
}
|
||||
|
@@ -163,8 +163,17 @@ export function isEqual(obj1: any, obj2: any) {
|
||||
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
||||
if (os.platform() === 'linux') {
|
||||
return {
|
||||
baseVersion: '3.2.12-27597',
|
||||
curVersion: '3.2.12-27597',
|
||||
baseVersion: '3.2.12.27254',
|
||||
curVersion: '3.2.12.27254',
|
||||
prevVersion: '',
|
||||
onErrorVersions: [],
|
||||
buildId: '27254',
|
||||
};
|
||||
}
|
||||
if (os.platform() === 'darwin') {
|
||||
return {
|
||||
baseVersion: '6.9.53.27597',
|
||||
curVersion: '6.9.53.27597',
|
||||
prevVersion: '',
|
||||
onErrorVersions: [],
|
||||
buildId: '27597',
|
||||
@@ -209,7 +218,8 @@ export function getQQVersionConfigPath(exePath: string = ''): string | undefined
|
||||
return configVersionInfoPath;
|
||||
}
|
||||
|
||||
export function calcQQLevel(level: QQLevel) {
|
||||
export function calcQQLevel(level?: QQLevel) {
|
||||
if (!level) return 0;
|
||||
const { crownNum, sunNum, moonNum, starNum } = level;
|
||||
return crownNum * 64 + sunNum * 16 + moonNum * 4 + starNum;
|
||||
}
|
||||
|
@@ -53,23 +53,23 @@ export class QQBasicInfoWrapper {
|
||||
//此方法不要直接使用
|
||||
getQUAInternal() {
|
||||
switch (systemPlatform) {
|
||||
case 'linux':
|
||||
return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||
case 'darwin':
|
||||
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||
default:
|
||||
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||
case 'linux':
|
||||
return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||
case 'darwin':
|
||||
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||
default:
|
||||
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||
}
|
||||
}
|
||||
|
||||
getAppidInternal() {
|
||||
switch (systemPlatform) {
|
||||
case 'linux':
|
||||
return '537243600';
|
||||
case 'darwin':
|
||||
return '537243441';
|
||||
default:
|
||||
return '537243538';
|
||||
case 'linux':
|
||||
return '537240795';
|
||||
case 'darwin':
|
||||
return '537243538';
|
||||
default:
|
||||
return '537243441';
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
export const napCatVersion = '2.4.2';
|
||||
export const napCatVersion = '2.5.3';
|
||||
|
@@ -1,63 +0,0 @@
|
||||
import {
|
||||
CacheFileListItem,
|
||||
CacheFileType,
|
||||
ChatCacheListItemBasic,
|
||||
ChatType,
|
||||
InstanceContext,
|
||||
NapCatCore,
|
||||
} from '@/core';
|
||||
|
||||
export class NTQQCacheApi {
|
||||
context: InstanceContext;
|
||||
core: NapCatCore;
|
||||
|
||||
constructor(context: InstanceContext, core: NapCatCore) {
|
||||
this.context = context;
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
async setCacheSilentScan(isSilent: boolean = true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
getCacheSessionPathList() {
|
||||
return '';
|
||||
}
|
||||
|
||||
clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
|
||||
// 参数未验证
|
||||
return this.context.session.getStorageCleanService().clearCacheDataByKeys(cacheKeys);
|
||||
}
|
||||
|
||||
addCacheScannedPaths(pathMap: object = {}) {
|
||||
return this.context.session.getStorageCleanService().addCacheScanedPaths(pathMap);
|
||||
}
|
||||
|
||||
scanCache() {
|
||||
//return (await this.context.session.getStorageCleanService().scanCache()).size;
|
||||
}
|
||||
|
||||
getHotUpdateCachePath() {
|
||||
// 未实现
|
||||
return '';
|
||||
}
|
||||
|
||||
getDesktopTmpPath() {
|
||||
// 未实现
|
||||
return '';
|
||||
}
|
||||
|
||||
getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) {
|
||||
return this.context.session.getStorageCleanService().getChatCacheInfo(type, pageSize, 1, pageIndex);
|
||||
}
|
||||
|
||||
getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
|
||||
// const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
|
||||
// 需要五个参数
|
||||
// return napCatCore.session.getStorageCleanService().getFileCacheInfo();
|
||||
}
|
||||
|
||||
async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
|
||||
return this.context.session.getStorageCleanService().clearChatCacheInfo(chats, fileKeys);
|
||||
}
|
||||
}
|
@@ -24,6 +24,7 @@ import pathLib from 'node:path';
|
||||
import { defaultVideoThumbB64, getVideoInfo } from '@/common/video';
|
||||
import ffmpeg from 'fluent-ffmpeg';
|
||||
import { encodeSilk } from '@/common/audio';
|
||||
import { MessageContext } from '@/onebot/api';
|
||||
|
||||
export class NTQQFileApi {
|
||||
context: InstanceContext;
|
||||
@@ -33,7 +34,7 @@ export class NTQQFileApi {
|
||||
constructor(context: InstanceContext, core: NapCatCore) {
|
||||
this.context = context;
|
||||
this.core = core;
|
||||
this.rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey', this.context.logger);
|
||||
this.rkeyManager = new RkeyManager(['https://llob.linyuchen.net/rkey', 'http://napcat-sign.wumiao.wang:2082/rkey'], this.context.logger);
|
||||
}
|
||||
|
||||
async copyFile(filePath: string, destPath: string) {
|
||||
@@ -71,7 +72,7 @@ export class NTQQFileApi {
|
||||
file_uuid: '',
|
||||
});
|
||||
|
||||
await this.copyFile(filePath, mediaPath!);
|
||||
await this.copyFile(filePath, mediaPath);
|
||||
const fileSize = await this.getFileSize(filePath);
|
||||
return {
|
||||
md5: fileMd5,
|
||||
@@ -82,7 +83,7 @@ export class NTQQFileApi {
|
||||
};
|
||||
}
|
||||
|
||||
async createValidSendFileElement(filePath: string, fileName: string = '', folderId: string = '',): Promise<SendFileElement> {
|
||||
async createValidSendFileElement(context: MessageContext, filePath: string, fileName: string = '', folderId: string = '',): Promise<SendFileElement> {
|
||||
const {
|
||||
fileName: _fileName,
|
||||
path,
|
||||
@@ -91,6 +92,7 @@ export class NTQQFileApi {
|
||||
if (fileSize === 0) {
|
||||
throw new Error('文件异常,大小为0');
|
||||
}
|
||||
context.deleteAfterSentFiles.push(path);
|
||||
return {
|
||||
elementType: ElementType.FILE,
|
||||
elementId: '',
|
||||
@@ -103,12 +105,13 @@ export class NTQQFileApi {
|
||||
};
|
||||
}
|
||||
|
||||
async createValidSendPicElement(picPath: string, summary: string = '', subType: 0 | 1 = 0,): Promise<SendPicElement> {
|
||||
async createValidSendPicElement(context: MessageContext, 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);
|
||||
context.deleteAfterSentFiles.push(path);
|
||||
return {
|
||||
elementType: ElementType.PIC,
|
||||
elementId: '',
|
||||
@@ -130,26 +133,40 @@ export class NTQQFileApi {
|
||||
};
|
||||
}
|
||||
|
||||
async createValidSendVideoElement(filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> {
|
||||
async createValidSendVideoElement(context: MessageContext, 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,
|
||||
size: 0,
|
||||
filePath,
|
||||
};
|
||||
try {
|
||||
videoInfo = await getVideoInfo(path, logger);
|
||||
videoInfo = await getVideoInfo(filePath, logger);
|
||||
} catch (e) {
|
||||
logger.logError('获取视频信息失败,将使用默认值', e);
|
||||
}
|
||||
|
||||
let fileExt = 'mp4';
|
||||
try {
|
||||
const tempExt = (await fileType.fileTypeFromFile(filePath))?.ext;
|
||||
if (tempExt) fileExt = tempExt;
|
||||
} catch (e) {
|
||||
this.context.logger.logError('获取文件类型失败', e);
|
||||
}
|
||||
const newFilePath = filePath + '.' + fileExt;
|
||||
fs.copyFileSync(filePath, newFilePath);
|
||||
context.deleteAfterSentFiles.push(newFilePath);
|
||||
filePath = newFilePath;
|
||||
const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
|
||||
if (fileSize === 0) {
|
||||
throw new Error('文件异常,大小为0');
|
||||
}
|
||||
videoInfo.size = fileSize;
|
||||
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
|
||||
thumb = pathLib.dirname(thumb);
|
||||
|
||||
const thumbPath = new Map();
|
||||
const _thumbPath = await new Promise<string | undefined>((resolve, reject) => {
|
||||
const thumbFileName = `${md5}_0.png`;
|
||||
@@ -179,11 +196,13 @@ export class NTQQFileApi {
|
||||
const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0;
|
||||
thumbPath.set(0, _thumbPath);
|
||||
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : '';
|
||||
context.deleteAfterSentFiles.push(path);
|
||||
const uploadName = (fileName || _fileName).toLocaleLowerCase().endsWith('.' + fileExt.toLocaleLowerCase()) ? (fileName || _fileName) : (fileName || _fileName) + '.' + fileExt;
|
||||
return {
|
||||
elementType: ElementType.VIDEO,
|
||||
elementId: '',
|
||||
videoElement: {
|
||||
fileName: fileName || _fileName,
|
||||
fileName: uploadName,
|
||||
filePath: path,
|
||||
videoMd5: md5,
|
||||
thumbMd5,
|
||||
@@ -207,7 +226,9 @@ export class NTQQFileApi {
|
||||
throw new Error('文件异常,大小为0');
|
||||
}
|
||||
if (converted) {
|
||||
fsPromises.unlink(silkPath);
|
||||
fsPromises.unlink(silkPath).then().catch(
|
||||
(e) => this.context.logger.logError('删除临时文件失败', e)
|
||||
);
|
||||
}
|
||||
return {
|
||||
elementType: ElementType.PTT,
|
||||
@@ -246,7 +267,6 @@ export class NTQQFileApi {
|
||||
}
|
||||
|
||||
async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
||||
//logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
|
||||
// 用于下载收到的消息中的图片等
|
||||
if (sourcePath && fs.existsSync(sourcePath)) {
|
||||
if (force) {
|
||||
@@ -346,8 +366,8 @@ export class NTQQFileApi {
|
||||
if (url) {
|
||||
const parsedUrl = new URL(IMAGE_HTTP_HOST + url);
|
||||
const imageAppid = parsedUrl.searchParams.get('appid');
|
||||
const isNTFlavoredPic = imageAppid && ['1406', '1407'].includes(imageAppid);
|
||||
if (isNTFlavoredPic) {
|
||||
const isNTV2 = imageAppid && ['1406', '1407'].includes(imageAppid);
|
||||
if (isNTV2) {
|
||||
let rkey = parsedUrl.searchParams.get('rkey');
|
||||
if (rkey) {
|
||||
return IMAGE_HTTP_HOST_NT + url;
|
||||
@@ -356,11 +376,9 @@ export class NTQQFileApi {
|
||||
rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
|
||||
return IMAGE_HTTP_HOST_NT + url + `${rkey}`;
|
||||
} else {
|
||||
// 老的图片url,不需要rkey
|
||||
return IMAGE_HTTP_HOST + url;
|
||||
}
|
||||
} else if (fileMd5 || md5HexStr) {
|
||||
// 没有url,需要自己拼接
|
||||
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`;
|
||||
}
|
||||
this.context.logger.logDebug('图片url获取失败', element);
|
||||
|
@@ -24,7 +24,7 @@ export class NTQQGroupApi {
|
||||
constructor(context: InstanceContext, core: NapCatCore) {
|
||||
this.context = context;
|
||||
this.core = core;
|
||||
this.initCache().then().catch(context.logger.logError);
|
||||
this.initCache().then().catch(context.logger.logError.bind(context.logger));
|
||||
}
|
||||
|
||||
async initCache() {
|
||||
@@ -32,13 +32,15 @@ export class NTQQGroupApi {
|
||||
for (const group of this.groups) {
|
||||
this.groupCache.set(group.groupCode, group);
|
||||
}
|
||||
// let text = await this.context.session.getMsgService().sendSsoCmdReqByContend(
|
||||
// 'LightAppSvc.mini_app_share.AdaptShareInfo',
|
||||
// JSON.stringify({ data: 'test' }));
|
||||
// console.log(text);
|
||||
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
|
||||
}
|
||||
|
||||
async getCoreAndBaseInfo(uids: string[]) {
|
||||
return await this.core.eventWrapper.callNoListenerEvent(
|
||||
'NodeIKernelProfileService/getCoreAndBaseInfo',
|
||||
'nodeStore',
|
||||
uids,
|
||||
);
|
||||
}
|
||||
async fetchGroupEssenceList(groupCode: string) {
|
||||
const pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
||||
return this.context.session.getGroupService().fetchGroupEssenceList({
|
||||
@@ -266,6 +268,23 @@ export class NTQQGroupApi {
|
||||
}
|
||||
return member;
|
||||
}
|
||||
async searchGroup(groupCode: string) {
|
||||
const [, ret] = await this.core.eventWrapper.callNormalEventV2(
|
||||
'NodeIKernelSearchService/searchGroup',
|
||||
'NodeIKernelSearchListener/onSearchGroupResult',
|
||||
[{
|
||||
keyWords: groupCode,
|
||||
groupNum: 25,
|
||||
exactSearch: false,
|
||||
penetrate: ''
|
||||
}],
|
||||
(ret) => ret.result === 0,
|
||||
(params) => !!params.groupInfos.find(g => g.groupCode === groupCode),
|
||||
1,
|
||||
5000
|
||||
);
|
||||
return ret.groupInfos.find(g => g.groupCode === groupCode);
|
||||
}
|
||||
async getGroupMemberEx(GroupCode: string, uid: string, forced = false, retry = 2) {
|
||||
const data = await solveAsyncProblem((eventWrapper: NTEventWrapper, GroupCode: string, uid: string, forced = false) => {
|
||||
return eventWrapper.callNormalEventV2(
|
||||
|
@@ -5,5 +5,4 @@ export * from './msg';
|
||||
export * from './user';
|
||||
export * from './webapi';
|
||||
export * from './sign';
|
||||
export * from './system';
|
||||
export * from './cache';
|
||||
export * from './system';
|
@@ -94,6 +94,7 @@ export class NTQQMsgApi {
|
||||
pageLimit: 1,
|
||||
});
|
||||
}
|
||||
//@deprecated
|
||||
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
|
||||
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
|
||||
}
|
||||
|
@@ -11,7 +11,13 @@ export class NTQQUserApi {
|
||||
this.context = context;
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
//self_tind格式
|
||||
async createUidFromTinyId(tinyId: string) {
|
||||
return this.context.session.getMsgService().createUidFromTinyId(this.core.selfInfo.uin, tinyId);
|
||||
}
|
||||
async getStatusByUid(uid: string) {
|
||||
return this.context.session.getProfileService().getStatus(uid);
|
||||
}
|
||||
async getProfileLike(uid: string) {
|
||||
return this.context.session.getProfileLikeService().getBuddyProfileLike({
|
||||
friendUids: [uid],
|
||||
@@ -24,7 +30,18 @@ export class NTQQUserApi {
|
||||
limit: 20,
|
||||
});
|
||||
}
|
||||
|
||||
async fetchOtherProfileLike(uid: string) {
|
||||
return this.context.session.getProfileLikeService().getBuddyProfileLike({
|
||||
friendUids: [uid],
|
||||
basic: 1,
|
||||
vote: 1,
|
||||
favorite: 0,
|
||||
userProfile: 0,
|
||||
type: 1,
|
||||
start: 0,
|
||||
limit: 20,
|
||||
});
|
||||
}
|
||||
async setLongNick(longNick: string) {
|
||||
return this.context.session.getProfileService().setLongNick(longNick);
|
||||
}
|
||||
@@ -159,7 +176,7 @@ export class NTQQUserApi {
|
||||
if (uid) return uid;
|
||||
uid = (await this.context.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin);
|
||||
if (uid) return uid;
|
||||
const unverifiedUid = (await this.getUserDetailInfoByUinV2(Uin)).detail.uid;//从QQ Native 特殊转换
|
||||
const unverifiedUid = (await this.getUserDetailInfoByUin(Uin)).detail.uid;//从QQ Native 特殊转换
|
||||
if (unverifiedUid.indexOf('*') == -1) uid = unverifiedUid;
|
||||
//if (uid) return uid;
|
||||
return uid;
|
||||
@@ -195,7 +212,7 @@ export class NTQQUserApi {
|
||||
return await this.context.session.getRecentContactService().getRecentContactList();
|
||||
}
|
||||
|
||||
async getUserDetailInfoByUinV2(Uin: string) {
|
||||
async getUserDetailInfoByUin(Uin: string) {
|
||||
return await this.core.eventWrapper.callNoListenerEvent(
|
||||
'NodeIKernelProfileService/getUserDetailInfoByUin',
|
||||
Uin
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { GroupMemberRole, Peer } from '@/core';
|
||||
import { GroupMemberRole } from '@/core';
|
||||
|
||||
export interface Peer {
|
||||
chatType: ChatType;
|
||||
@@ -959,3 +959,18 @@ export interface TmpChatInfo {
|
||||
sessionType: number;
|
||||
sig: string;
|
||||
}
|
||||
export interface MsgReqType {
|
||||
peer: Peer,
|
||||
byType: number,
|
||||
msgId: string,
|
||||
msgSeq: string,
|
||||
msgTime: string,
|
||||
clientSeq: string,
|
||||
cnt: number,
|
||||
queryOrder: boolean,
|
||||
includeSelf: boolean,
|
||||
includeDeleteMsg: boolean,
|
||||
extraCnt: number
|
||||
}
|
||||
//getMsgsIncludeSelf Peer必须 byType 1
|
||||
//getMsgsWithMsgTimeAndClientSeqForC2C Peer必须 byType 3
|
@@ -216,7 +216,7 @@ export interface BuddyProfileLikeReq {
|
||||
userProfile: number;
|
||||
type: number;
|
||||
start: number;
|
||||
limit: number;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export interface QQLevel {
|
||||
@@ -297,7 +297,7 @@ export enum BizKey {
|
||||
KPHOTOWALL
|
||||
}
|
||||
|
||||
export interface UserDetailInfoByUinV2 {
|
||||
export interface UserDetailInfoByUin {
|
||||
result: number,
|
||||
errMsg: string,
|
||||
detail: {
|
||||
@@ -308,65 +308,6 @@ export interface UserDetailInfoByUinV2 {
|
||||
photoWall: null
|
||||
}
|
||||
}
|
||||
|
||||
export interface UserDetailInfoByUin {
|
||||
result: number,
|
||||
errMsg: string,
|
||||
info: {
|
||||
uid: string,//这个没办法用
|
||||
qid: string,
|
||||
uin: string,
|
||||
nick: string,
|
||||
remark: string,
|
||||
longNick: string,
|
||||
avatarUrl: string,
|
||||
birthday_year: number,
|
||||
birthday_month: number,
|
||||
birthday_day: number,
|
||||
sex: number,//0
|
||||
topTime: string,
|
||||
constellation: number,
|
||||
shengXiao: number,
|
||||
kBloodType: number,
|
||||
homeTown: string,
|
||||
makeFriendCareer: number,
|
||||
pos: string,
|
||||
eMail: string,
|
||||
phoneNum: string,
|
||||
college: string,
|
||||
country: string,
|
||||
province: string,
|
||||
city: string,
|
||||
postCode: string,
|
||||
address: string,
|
||||
isBlock: boolean,
|
||||
isSpecialCareOpen: boolean,
|
||||
isSpecialCareZone: boolean,
|
||||
ringId: string,
|
||||
regTime: number,
|
||||
interest: string,
|
||||
termType: number,
|
||||
labels: any[],
|
||||
qqLevel: { crownNum: number, sunNum: number, moonNum: number, starNum: number },
|
||||
isHideQQLevel: number,
|
||||
privilegeIcon: { jumpUrl: string, openIconList: any[], closeIconList: any[] },
|
||||
isHidePrivilegeIcon: number,
|
||||
photoWall: { picList: any[] },
|
||||
vipFlag: boolean,
|
||||
yearVipFlag: boolean,
|
||||
svipFlag: boolean,
|
||||
vipLevel: number,
|
||||
status: number,
|
||||
qidianMasterFlag: number,
|
||||
qidianCrewFlag: number,
|
||||
qidianCrewFlag2: number,
|
||||
extStatus: number,
|
||||
recommendImgFlag: number,
|
||||
disableEmojiShortCuts: number,
|
||||
pendantId: string,
|
||||
vipNameColorId: string
|
||||
}
|
||||
}
|
||||
export enum UserDetailSource {
|
||||
KDB,
|
||||
KSERVER
|
||||
|
15
src/core/external/appid.json
vendored
15
src/core/external/appid.json
vendored
@@ -1,4 +1,14 @@
|
||||
{
|
||||
|
||||
"3.2.12-27254":{
|
||||
"appid": 537240795,
|
||||
"qua": "V1_LNX_NQ_3.2.12_27254_GW_B"
|
||||
},
|
||||
"9.9.15-27254":{
|
||||
"appid": 537240709,
|
||||
"qua": "V1_WIN_NQ_9.9.15_27254_GW_B"
|
||||
},
|
||||
|
||||
"3.2.12-27597": {
|
||||
"appid": 537243600,
|
||||
"qua": "V1_LNX_NQ_3.2.12_27597_GW_B"
|
||||
@@ -10,5 +20,10 @@
|
||||
"6.9.53-27597": {
|
||||
"appid": 537243538,
|
||||
"qua": "V1_MAC_NQ_6.9.53_27597_GW_B"
|
||||
},
|
||||
|
||||
"9.9.15-28060":{
|
||||
"appid": 537246092,
|
||||
"qua": "V1_WIN_NQ_9.9.15_28060_GW_B"
|
||||
}
|
||||
}
|
||||
|
18
src/core/external/proto/ProfileLikeTip.proto
vendored
Normal file
18
src/core/external/proto/ProfileLikeTip.proto
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
syntax = "proto3";
|
||||
package SysMessage;
|
||||
|
||||
message likeDetail {
|
||||
string txt = 1;
|
||||
int64 uin = 3;
|
||||
string nickname = 5;
|
||||
}
|
||||
|
||||
message likeMsg {
|
||||
int32 times = 1;
|
||||
int32 time = 2;
|
||||
likeDetail detail = 3;
|
||||
}
|
||||
|
||||
message profileLikeTip {
|
||||
likeMsg msg = 14;
|
||||
}
|
@@ -8,7 +8,7 @@ interface ServerRkeyData {
|
||||
}
|
||||
|
||||
export class RkeyManager {
|
||||
serverUrl: string = '';
|
||||
serverUrl: string[] = [];
|
||||
logger: LogWrapper;
|
||||
private rkeyData: ServerRkeyData = {
|
||||
group_rkey: '',
|
||||
@@ -16,7 +16,7 @@ export class RkeyManager {
|
||||
expired_time: 0,
|
||||
};
|
||||
|
||||
constructor(serverUrl: string, logger: LogWrapper) {
|
||||
constructor(serverUrl: string[], logger: LogWrapper) {
|
||||
this.logger = logger;
|
||||
this.serverUrl = serverUrl;
|
||||
}
|
||||
@@ -40,6 +40,13 @@ export class RkeyManager {
|
||||
|
||||
async refreshRkey(): Promise<any> {
|
||||
//刷新rkey
|
||||
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(this.serverUrl, 'GET');
|
||||
for (const url of this.serverUrl) {
|
||||
try {
|
||||
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET');
|
||||
} catch (e) {
|
||||
this.logger.logError(`[Rkey] Get Rkey ${url} Error `, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -145,7 +145,6 @@ export class NapCatCore {
|
||||
if (Info.status == 20) {
|
||||
this.selfInfo.online = false;
|
||||
this.context.logger.log("账号状态变更为离线");
|
||||
return;
|
||||
} else {
|
||||
this.selfInfo.online = true;
|
||||
}
|
||||
|
97
src/core/listeners/NodeIKernelSearchListener.ts
Normal file
97
src/core/listeners/NodeIKernelSearchListener.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { ChatType } from '@/core';
|
||||
export interface SearchGroupInfo {
|
||||
groupCode: string;
|
||||
ownerUid: string;
|
||||
groupFlag: number;
|
||||
groupFlagExt: number;
|
||||
maxMemberNum: number;
|
||||
memberNum: number;
|
||||
groupOption: number;
|
||||
classExt: number;
|
||||
groupName: string;
|
||||
fingerMemo: string;
|
||||
groupQuestion: string;
|
||||
certType: number;
|
||||
shutUpAllTimestamp: number;
|
||||
shutUpMeTimestamp: number;
|
||||
groupTypeFlag: number;
|
||||
privilegeFlag: number;
|
||||
groupSecLevel: number;
|
||||
groupFlagExt3: number;
|
||||
isConfGroup: number;
|
||||
isModifyConfGroupFace: number;
|
||||
isModifyConfGroupName: number;
|
||||
noFigerOpenFlag: number;
|
||||
noCodeFingerOpenFlag: number;
|
||||
groupFlagExt4: number;
|
||||
groupMemo: string;
|
||||
cmdUinMsgSeq: number;
|
||||
cmdUinJoinTime: number;
|
||||
cmdUinUinFlag: number;
|
||||
cmdUinMsgMask: number;
|
||||
groupSecLevelInfo: number;
|
||||
cmdUinPrivilege: number;
|
||||
cmdUinFlagEx2: number;
|
||||
appealDeadline: number;
|
||||
remarkName: string;
|
||||
isTop: boolean;
|
||||
richFingerMemo: string;
|
||||
groupAnswer: string;
|
||||
joinGroupAuth: string;
|
||||
isAllowModifyConfGroupName: number;
|
||||
}
|
||||
|
||||
export interface GroupInfo {
|
||||
groupCode: string;
|
||||
searchGroupInfo: SearchGroupInfo;
|
||||
privilege: number;
|
||||
}
|
||||
|
||||
export interface GroupSearchResult {
|
||||
keyWord: string;
|
||||
errorCode: number;
|
||||
groupInfos: GroupInfo[];
|
||||
penetrate: string;
|
||||
isEnd: boolean;
|
||||
nextPos: number;
|
||||
}
|
||||
export interface NodeIKernelSearchListener {
|
||||
|
||||
onSearchGroupResult(params: GroupSearchResult): void;
|
||||
|
||||
onSearchFileKeywordsResult(params: {
|
||||
searchId: string,
|
||||
hasMore: boolean,
|
||||
resultItems: {
|
||||
chatType: ChatType,
|
||||
buddyChatInfo: any[],
|
||||
discussChatInfo: any[],
|
||||
groupChatInfo: {
|
||||
groupCode: string,
|
||||
isConf: boolean,
|
||||
hasModifyConfGroupFace: boolean,
|
||||
hasModifyConfGroupName: boolean,
|
||||
groupName: string,
|
||||
remark: string
|
||||
}[],
|
||||
dataLineChatInfo: any[],
|
||||
tmpChatInfo: any[],
|
||||
msgId: string,
|
||||
msgSeq: string,
|
||||
msgTime: string,
|
||||
senderUid: string,
|
||||
senderNick: string,
|
||||
senderRemark: string,
|
||||
senderCard: string,
|
||||
elemId: string,
|
||||
elemType: number,
|
||||
fileSize: string,
|
||||
filePath: string,
|
||||
fileName: string,
|
||||
hits: {
|
||||
start: number,
|
||||
end: number
|
||||
}[]
|
||||
}[]
|
||||
}): void;
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
import { ChatType } from '@/core';
|
||||
|
||||
export interface NodeIKernelSearchListener_Polyfill {
|
||||
onSearchFileKeywordsResult(params: {
|
||||
searchId: string,
|
||||
hasMore: boolean,
|
||||
resultItems: {
|
||||
chatType: ChatType,
|
||||
buddyChatInfo: any[],
|
||||
discussChatInfo: any[],
|
||||
groupChatInfo: {
|
||||
groupCode: string,
|
||||
isConf: boolean,
|
||||
hasModifyConfGroupFace: boolean,
|
||||
hasModifyConfGroupName: boolean,
|
||||
groupName: string,
|
||||
remark: string
|
||||
}[],
|
||||
dataLineChatInfo: any[],
|
||||
tmpChatInfo: any[],
|
||||
msgId: string,
|
||||
msgSeq: string,
|
||||
msgTime: string,
|
||||
senderUid: string,
|
||||
senderNick: string,
|
||||
senderRemark: string,
|
||||
senderCard: string,
|
||||
elemId: string,
|
||||
elemType: number,
|
||||
fileSize: string,
|
||||
filePath: string,
|
||||
fileName: string,
|
||||
hits: {
|
||||
start: number,
|
||||
end: number
|
||||
}[]
|
||||
}[]
|
||||
}): void;
|
||||
}
|
@@ -9,7 +9,7 @@ export * from './NodeIKernelProfileListener';
|
||||
export * from './NodeIKernelTicketListener';
|
||||
export * from './NodeIKernelStorageCleanListener';
|
||||
export * from './NodeIKernelFileAssistantListener';
|
||||
export * from './NodeIKernelSearchListener_Polyfill';
|
||||
export * from './NodeIKernelSearchListener';
|
||||
|
||||
import type {
|
||||
NodeIKernelBuddyListener,
|
||||
@@ -19,11 +19,11 @@ import type {
|
||||
NodeIKernelMsgListener,
|
||||
NodeIKernelProfileListener,
|
||||
NodeIKernelRobotListener,
|
||||
NodeIKernelSearchListener_Polyfill,
|
||||
NodeIKernelSessionListener,
|
||||
NodeIKernelStorageCleanListener,
|
||||
NodeIKernelTicketListener,
|
||||
} from '.';
|
||||
import { NodeIKernelSearchListener } from './NodeIKernelSearchListener';
|
||||
|
||||
export type ListenerNamingMapping = {
|
||||
NodeIKernelSessionListener: NodeIKernelSessionListener;
|
||||
@@ -36,5 +36,5 @@ export type ListenerNamingMapping = {
|
||||
NodeIKernelTicketListener: NodeIKernelTicketListener;
|
||||
NodeIKernelStorageCleanListener: NodeIKernelStorageCleanListener;
|
||||
NodeIKernelFileAssistantListener: NodeIKernelFileAssistantListener;
|
||||
NodeIKernelSearchListener: NodeIKernelSearchListener_Polyfill;
|
||||
NodeIKernelSearchListener: NodeIKernelSearchListener;
|
||||
};
|
||||
|
@@ -1,341 +0,0 @@
|
||||
// @generated by protobuf-ts 2.9.4
|
||||
// @generated from protobuf file "EmojiLikeToOthers.proto" (package "SysMessage", syntax proto3)
|
||||
// tslint:disable
|
||||
import type {
|
||||
BinaryReadOptions,
|
||||
BinaryWriteOptions,
|
||||
IBinaryReader,
|
||||
IBinaryWriter,
|
||||
PartialMessage,
|
||||
} from '@protobuf-ts/runtime';
|
||||
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
|
||||
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper1
|
||||
*/
|
||||
export interface EmojiLikeToOthersWrapper1 {
|
||||
/**
|
||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersWrapper2 wrapper = 1;
|
||||
*/
|
||||
wrapper?: EmojiLikeToOthersWrapper2;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper2
|
||||
*/
|
||||
export interface EmojiLikeToOthersWrapper2 {
|
||||
/**
|
||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersWrapper3 body = 1;
|
||||
*/
|
||||
body?: EmojiLikeToOthersWrapper3;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper3
|
||||
*/
|
||||
export interface EmojiLikeToOthersWrapper3 {
|
||||
/**
|
||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersMsgSpec msgSpec = 2;
|
||||
*/
|
||||
msgSpec?: EmojiLikeToOthersMsgSpec;
|
||||
/**
|
||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersAttributes attributes = 3;
|
||||
*/
|
||||
attributes?: EmojiLikeToOthersAttributes;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersMsgSpec
|
||||
*/
|
||||
export interface EmojiLikeToOthersMsgSpec {
|
||||
/**
|
||||
* @generated from protobuf field: uint32 msgSeq = 1;
|
||||
*/
|
||||
msgSeq: number;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.EmojiLikeToOthersAttributes
|
||||
*/
|
||||
export interface EmojiLikeToOthersAttributes {
|
||||
/**
|
||||
* @generated from protobuf field: string emojiId = 1;
|
||||
*/
|
||||
emojiId: string;
|
||||
/**
|
||||
* @generated from protobuf field: string senderUid = 4;
|
||||
*/
|
||||
senderUid: string;
|
||||
/**
|
||||
* @generated from protobuf field: SysMessage.EmojiLikeToOthersAttributes.Operation operation = 5;
|
||||
*/
|
||||
operation: EmojiLikeToOthersAttributes_Operation;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf enum SysMessage.EmojiLikeToOthersAttributes.Operation
|
||||
*/
|
||||
export enum EmojiLikeToOthersAttributes_Operation {
|
||||
/**
|
||||
* @generated from protobuf enum value: FALLBACK = 0;
|
||||
*/
|
||||
FALLBACK = 0,
|
||||
/**
|
||||
* @generated from protobuf enum value: LIKE = 1;
|
||||
*/
|
||||
LIKE = 1,
|
||||
/**
|
||||
* @generated from protobuf enum value: UNLIKE = 2;
|
||||
*/
|
||||
UNLIKE = 2
|
||||
}
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class EmojiLikeToOthersWrapper1$Type extends MessageType<EmojiLikeToOthersWrapper1> {
|
||||
constructor() {
|
||||
super("SysMessage.EmojiLikeToOthersWrapper1", [
|
||||
{ no: 1, name: "wrapper", kind: "message", T: () => EmojiLikeToOthersWrapper2 }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<EmojiLikeToOthersWrapper1>): EmojiLikeToOthersWrapper1 {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<EmojiLikeToOthersWrapper1>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersWrapper1): EmojiLikeToOthersWrapper1 {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* SysMessage.EmojiLikeToOthersWrapper2 wrapper */ 1:
|
||||
message.wrapper = EmojiLikeToOthersWrapper2.internalBinaryRead(reader, reader.uint32(), options, message.wrapper);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: EmojiLikeToOthersWrapper1, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* SysMessage.EmojiLikeToOthersWrapper2 wrapper = 1; */
|
||||
if (message.wrapper)
|
||||
EmojiLikeToOthersWrapper2.internalBinaryWrite(message.wrapper, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersWrapper1
|
||||
*/
|
||||
export const EmojiLikeToOthersWrapper1 = new EmojiLikeToOthersWrapper1$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class EmojiLikeToOthersWrapper2$Type extends MessageType<EmojiLikeToOthersWrapper2> {
|
||||
constructor() {
|
||||
super("SysMessage.EmojiLikeToOthersWrapper2", [
|
||||
{ no: 1, name: "body", kind: "message", T: () => EmojiLikeToOthersWrapper3 }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<EmojiLikeToOthersWrapper2>): EmojiLikeToOthersWrapper2 {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<EmojiLikeToOthersWrapper2>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersWrapper2): EmojiLikeToOthersWrapper2 {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* SysMessage.EmojiLikeToOthersWrapper3 body */ 1:
|
||||
message.body = EmojiLikeToOthersWrapper3.internalBinaryRead(reader, reader.uint32(), options, message.body);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: EmojiLikeToOthersWrapper2, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* SysMessage.EmojiLikeToOthersWrapper3 body = 1; */
|
||||
if (message.body)
|
||||
EmojiLikeToOthersWrapper3.internalBinaryWrite(message.body, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersWrapper2
|
||||
*/
|
||||
export const EmojiLikeToOthersWrapper2 = new EmojiLikeToOthersWrapper2$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class EmojiLikeToOthersWrapper3$Type extends MessageType<EmojiLikeToOthersWrapper3> {
|
||||
constructor() {
|
||||
super("SysMessage.EmojiLikeToOthersWrapper3", [
|
||||
{ no: 2, name: "msgSpec", kind: "message", T: () => EmojiLikeToOthersMsgSpec },
|
||||
{ no: 3, name: "attributes", kind: "message", T: () => EmojiLikeToOthersAttributes }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<EmojiLikeToOthersWrapper3>): EmojiLikeToOthersWrapper3 {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<EmojiLikeToOthersWrapper3>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersWrapper3): EmojiLikeToOthersWrapper3 {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* SysMessage.EmojiLikeToOthersMsgSpec msgSpec */ 2:
|
||||
message.msgSpec = EmojiLikeToOthersMsgSpec.internalBinaryRead(reader, reader.uint32(), options, message.msgSpec);
|
||||
break;
|
||||
case /* SysMessage.EmojiLikeToOthersAttributes attributes */ 3:
|
||||
message.attributes = EmojiLikeToOthersAttributes.internalBinaryRead(reader, reader.uint32(), options, message.attributes);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: EmojiLikeToOthersWrapper3, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* SysMessage.EmojiLikeToOthersMsgSpec msgSpec = 2; */
|
||||
if (message.msgSpec)
|
||||
EmojiLikeToOthersMsgSpec.internalBinaryWrite(message.msgSpec, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
|
||||
/* SysMessage.EmojiLikeToOthersAttributes attributes = 3; */
|
||||
if (message.attributes)
|
||||
EmojiLikeToOthersAttributes.internalBinaryWrite(message.attributes, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersWrapper3
|
||||
*/
|
||||
export const EmojiLikeToOthersWrapper3 = new EmojiLikeToOthersWrapper3$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class EmojiLikeToOthersMsgSpec$Type extends MessageType<EmojiLikeToOthersMsgSpec> {
|
||||
constructor() {
|
||||
super("SysMessage.EmojiLikeToOthersMsgSpec", [
|
||||
{ no: 1, name: "msgSeq", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<EmojiLikeToOthersMsgSpec>): EmojiLikeToOthersMsgSpec {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.msgSeq = 0;
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<EmojiLikeToOthersMsgSpec>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersMsgSpec): EmojiLikeToOthersMsgSpec {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* uint32 msgSeq */ 1:
|
||||
message.msgSeq = reader.uint32();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: EmojiLikeToOthersMsgSpec, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* uint32 msgSeq = 1; */
|
||||
if (message.msgSeq !== 0)
|
||||
writer.tag(1, WireType.Varint).uint32(message.msgSeq);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersMsgSpec
|
||||
*/
|
||||
export const EmojiLikeToOthersMsgSpec = new EmojiLikeToOthersMsgSpec$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class EmojiLikeToOthersAttributes$Type extends MessageType<EmojiLikeToOthersAttributes> {
|
||||
constructor() {
|
||||
super("SysMessage.EmojiLikeToOthersAttributes", [
|
||||
{ no: 1, name: "emojiId", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 4, name: "senderUid", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 5, name: "operation", kind: "enum", T: () => ["SysMessage.EmojiLikeToOthersAttributes.Operation", EmojiLikeToOthersAttributes_Operation] }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<EmojiLikeToOthersAttributes>): EmojiLikeToOthersAttributes {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.emojiId = "";
|
||||
message.senderUid = "";
|
||||
message.operation = 0;
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<EmojiLikeToOthersAttributes>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EmojiLikeToOthersAttributes): EmojiLikeToOthersAttributes {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string emojiId */ 1:
|
||||
message.emojiId = reader.string();
|
||||
break;
|
||||
case /* string senderUid */ 4:
|
||||
message.senderUid = reader.string();
|
||||
break;
|
||||
case /* SysMessage.EmojiLikeToOthersAttributes.Operation operation */ 5:
|
||||
message.operation = reader.int32();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: EmojiLikeToOthersAttributes, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* string emojiId = 1; */
|
||||
if (message.emojiId !== "")
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.emojiId);
|
||||
/* string senderUid = 4; */
|
||||
if (message.senderUid !== "")
|
||||
writer.tag(4, WireType.LengthDelimited).string(message.senderUid);
|
||||
/* SysMessage.EmojiLikeToOthersAttributes.Operation operation = 5; */
|
||||
if (message.operation !== 0)
|
||||
writer.tag(5, WireType.Varint).int32(message.operation);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.EmojiLikeToOthersAttributes
|
||||
*/
|
||||
export const EmojiLikeToOthersAttributes = new EmojiLikeToOthersAttributes$Type();
|
@@ -1,104 +0,0 @@
|
||||
// @generated by protobuf-ts 2.9.4
|
||||
// @generated from protobuf file "GreyTipWrapper.proto" (package "SysMessage", syntax proto3)
|
||||
// tslint:disable
|
||||
import type {
|
||||
BinaryReadOptions,
|
||||
BinaryWriteOptions,
|
||||
IBinaryReader,
|
||||
IBinaryWriter,
|
||||
PartialMessage,
|
||||
} from '@protobuf-ts/runtime';
|
||||
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
|
||||
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.GreyTipWrapper
|
||||
*/
|
||||
export interface GreyTipWrapper {
|
||||
/**
|
||||
* @generated from protobuf field: uint32 subTypeId = 1;
|
||||
*/
|
||||
subTypeId: number;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 groupCode = 4;
|
||||
*/
|
||||
groupCode: number;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 subTypeIdMinusOne = 13;
|
||||
*/
|
||||
subTypeIdMinusOne: number;
|
||||
/**
|
||||
* @generated from protobuf field: bytes rest = 44;
|
||||
*/
|
||||
rest: Uint8Array;
|
||||
}
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class GreyTipWrapper$Type extends MessageType<GreyTipWrapper> {
|
||||
constructor() {
|
||||
super("SysMessage.GreyTipWrapper", [
|
||||
{ no: 1, name: "subTypeId", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 4, name: "groupCode", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 13, name: "subTypeIdMinusOne", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 44, name: "rest", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GreyTipWrapper>): GreyTipWrapper {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.subTypeId = 0;
|
||||
message.groupCode = 0;
|
||||
message.subTypeIdMinusOne = 0;
|
||||
message.rest = new Uint8Array(0);
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<GreyTipWrapper>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GreyTipWrapper): GreyTipWrapper {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* uint32 subTypeId */ 1:
|
||||
message.subTypeId = reader.uint32();
|
||||
break;
|
||||
case /* uint32 groupCode */ 4:
|
||||
message.groupCode = reader.uint32();
|
||||
break;
|
||||
case /* uint32 subTypeIdMinusOne */ 13:
|
||||
message.subTypeIdMinusOne = reader.uint32();
|
||||
break;
|
||||
case /* bytes rest */ 44:
|
||||
message.rest = reader.bytes();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: GreyTipWrapper, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* uint32 subTypeId = 1; */
|
||||
if (message.subTypeId !== 0)
|
||||
writer.tag(1, WireType.Varint).uint32(message.subTypeId);
|
||||
/* uint32 groupCode = 4; */
|
||||
if (message.groupCode !== 0)
|
||||
writer.tag(4, WireType.Varint).uint32(message.groupCode);
|
||||
/* uint32 subTypeIdMinusOne = 13; */
|
||||
if (message.subTypeIdMinusOne !== 0)
|
||||
writer.tag(13, WireType.Varint).uint32(message.subTypeIdMinusOne);
|
||||
/* bytes rest = 44; */
|
||||
if (message.rest.length)
|
||||
writer.tag(44, WireType.LengthDelimited).bytes(message.rest);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.GreyTipWrapper
|
||||
*/
|
||||
export const GreyTipWrapper = new GreyTipWrapper$Type();
|
95
src/core/proto/ProfileLike.ts
Normal file
95
src/core/proto/ProfileLike.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import * as pb from 'protobufjs';
|
||||
|
||||
// Proto: from src/core/proto/ProfileLike.proto
|
||||
// Author: Mlikiowa
|
||||
|
||||
export interface LikeDetailType {
|
||||
txt: string;
|
||||
uin: pb.Long;
|
||||
nickname: string;
|
||||
}
|
||||
export interface LikeMsgType {
|
||||
times: number;
|
||||
time: number;
|
||||
detail: LikeDetailType;
|
||||
}
|
||||
|
||||
export interface profileLikeSubTipType {
|
||||
msg: LikeMsgType;
|
||||
}
|
||||
|
||||
export interface ProfileLikeTipType {
|
||||
msgType: number;
|
||||
subType: number;
|
||||
content: profileLikeSubTipType;
|
||||
}
|
||||
export interface SysMessageHeaderType {
|
||||
id: string;
|
||||
timestamp: number;
|
||||
sender: string;
|
||||
}
|
||||
|
||||
export interface SysMessageMsgSpecType {
|
||||
msgType: number;
|
||||
subType: number;
|
||||
subSubType: number;
|
||||
msgSeq: number;
|
||||
time: number;
|
||||
msgId: pb.Long;
|
||||
other: number;
|
||||
}
|
||||
export interface SysMessageBodyWrapperType {
|
||||
wrappedBody: Uint8Array;
|
||||
}
|
||||
export interface SysMessageType {
|
||||
header: SysMessageHeaderType[];
|
||||
msgSpec: SysMessageMsgSpecType[];
|
||||
bodyWrapper: SysMessageBodyWrapperType;
|
||||
}
|
||||
|
||||
export const SysMessageHeader = new pb.Type("SysMessageHeader")
|
||||
.add(new pb.Field("PeerNumber", 1, "uint32"))
|
||||
.add(new pb.Field("PeerString", 2, "string"))
|
||||
.add(new pb.Field("Uin", 5, "uint32"))
|
||||
.add(new pb.Field("Uid", 6, "string", "optional"));
|
||||
|
||||
export const SysMessageMsgSpec = new pb.Type("SysMessageMsgSpec")
|
||||
.add(new pb.Field("msgType", 1, "uint32"))
|
||||
.add(new pb.Field("subType", 2, "uint32"))
|
||||
.add(new pb.Field("subSubType", 3, "uint32"))
|
||||
.add(new pb.Field("msgSeq", 5, "uint32"))
|
||||
.add(new pb.Field("time", 6, "uint32"))
|
||||
.add(new pb.Field("msgId", 12, "uint64"))
|
||||
.add(new pb.Field("other", 13, "uint32"));
|
||||
|
||||
export const SysMessageBodyWrapper = new pb.Type("SysMessageBodyWrapper")
|
||||
.add(new pb.Field("wrappedBody", 2, "bytes"));
|
||||
|
||||
export const SysMessage = new pb.Type("SysMessage")
|
||||
.add(SysMessageHeader)
|
||||
.add(SysMessageMsgSpec)
|
||||
.add(SysMessageBodyWrapper)
|
||||
.add(new pb.Field("header", 1, "SysMessageHeader", "repeated"))
|
||||
.add(new pb.Field("msgSpec", 2, "SysMessageMsgSpec", "repeated"))
|
||||
.add(new pb.Field("bodyWrapper", 3, "SysMessageBodyWrapper"));
|
||||
|
||||
export const likeDetail = new pb.Type("likeDetail")
|
||||
.add(new pb.Field("txt", 1, "string"))
|
||||
.add(new pb.Field("uin", 3, "int64"))
|
||||
.add(new pb.Field("nickname", 5, "string"));
|
||||
|
||||
export const likeMsg = new pb.Type("likeMsg")
|
||||
.add(likeDetail)
|
||||
.add(new pb.Field("times", 1, "int32"))
|
||||
.add(new pb.Field("time", 2, "int32"))
|
||||
.add(new pb.Field("detail", 3, "likeDetail"));
|
||||
|
||||
export const profileLikeSubTip = new pb.Type("profileLikeSubTip")
|
||||
.add(likeMsg)
|
||||
.add(new pb.Field("msg", 14, "likeMsg"))
|
||||
|
||||
export const profileLikeTip = new pb.Type("profileLikeTip")
|
||||
.add(profileLikeSubTip)
|
||||
.add(new pb.Field("msgType", 1, "int32"))
|
||||
.add(new pb.Field("subType", 2, "int32"))
|
||||
.add(new pb.Field("content", 203, "profileLikeSubTip"));
|
@@ -1,435 +0,0 @@
|
||||
// @generated by protobuf-ts 2.9.4
|
||||
// @generated from protobuf file "SysMessage.proto" (package "SysMessage", syntax proto3)
|
||||
// tslint:disable
|
||||
import type {
|
||||
BinaryReadOptions,
|
||||
BinaryWriteOptions,
|
||||
IBinaryReader,
|
||||
IBinaryWriter,
|
||||
PartialMessage,
|
||||
} from '@protobuf-ts/runtime';
|
||||
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
|
||||
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.SysMessage
|
||||
*/
|
||||
export interface SysMessage {
|
||||
/**
|
||||
* @generated from protobuf field: repeated SysMessage.SysMessageHeader header = 1;
|
||||
*/
|
||||
header: SysMessageHeader[];
|
||||
/**
|
||||
* @generated from protobuf field: repeated SysMessage.SysMessageMsgSpec msgSpec = 2;
|
||||
*/
|
||||
msgSpec: SysMessageMsgSpec[];
|
||||
/**
|
||||
* @generated from protobuf field: SysMessage.SysMessageBodyWrapper bodyWrapper = 3;
|
||||
*/
|
||||
bodyWrapper?: SysMessageBodyWrapper;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.SysMessageHeader
|
||||
*/
|
||||
export interface SysMessageHeader {
|
||||
/**
|
||||
* @generated from protobuf field: uint32 PeerNumber = 1 [json_name = "PeerNumber"];
|
||||
*/
|
||||
peerNumber: number;
|
||||
/**
|
||||
* @generated from protobuf field: string PeerString = 2 [json_name = "PeerString"];
|
||||
*/
|
||||
peerString: string;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 Uin = 5 [json_name = "Uin"];
|
||||
*/
|
||||
uin: number;
|
||||
/**
|
||||
* @generated from protobuf field: optional string Uid = 6 [json_name = "Uid"];
|
||||
*/
|
||||
uid?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.SysMessageMsgSpec
|
||||
*/
|
||||
export interface SysMessageMsgSpec {
|
||||
/**
|
||||
* @generated from protobuf field: uint32 msgType = 1;
|
||||
*/
|
||||
msgType: number;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 subType = 2;
|
||||
*/
|
||||
subType: number;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 subSubType = 3;
|
||||
*/
|
||||
subSubType: number;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 msgSeq = 5;
|
||||
*/
|
||||
msgSeq: number;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 time = 6;
|
||||
*/
|
||||
time: number;
|
||||
/**
|
||||
* @generated from protobuf field: uint64 msgId = 12;
|
||||
*/
|
||||
msgId: bigint;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 other = 13;
|
||||
*/
|
||||
other: number;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.SysMessageBodyWrapper
|
||||
*/
|
||||
export interface SysMessageBodyWrapper {
|
||||
/**
|
||||
* @generated from protobuf field: bytes wrappedBody = 2;
|
||||
*/
|
||||
wrappedBody: Uint8Array; // Find the first [08], or ignore the first 7 bytes?
|
||||
// And it becomes another ProtoBuf message.
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message SysMessage.KeyValuePair
|
||||
*/
|
||||
export interface KeyValuePair {
|
||||
/**
|
||||
* @generated from protobuf field: string key = 1;
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* @generated from protobuf field: string value = 2;
|
||||
*/
|
||||
value: string;
|
||||
}
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class SysMessage$Type extends MessageType<SysMessage> {
|
||||
constructor() {
|
||||
super("SysMessage.SysMessage", [
|
||||
{ no: 1, name: "header", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => SysMessageHeader },
|
||||
{ no: 2, name: "msgSpec", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => SysMessageMsgSpec },
|
||||
{ no: 3, name: "bodyWrapper", kind: "message", T: () => SysMessageBodyWrapper }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<SysMessage>): SysMessage {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.header = [];
|
||||
message.msgSpec = [];
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<SysMessage>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessage): SysMessage {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* repeated SysMessage.SysMessageHeader header */ 1:
|
||||
message.header.push(SysMessageHeader.internalBinaryRead(reader, reader.uint32(), options));
|
||||
break;
|
||||
case /* repeated SysMessage.SysMessageMsgSpec msgSpec */ 2:
|
||||
message.msgSpec.push(SysMessageMsgSpec.internalBinaryRead(reader, reader.uint32(), options));
|
||||
break;
|
||||
case /* SysMessage.SysMessageBodyWrapper bodyWrapper */ 3:
|
||||
message.bodyWrapper = SysMessageBodyWrapper.internalBinaryRead(reader, reader.uint32(), options, message.bodyWrapper);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: SysMessage, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* repeated SysMessage.SysMessageHeader header = 1; */
|
||||
for (let i = 0; i < message.header.length; i++)
|
||||
SysMessageHeader.internalBinaryWrite(message.header[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
/* repeated SysMessage.SysMessageMsgSpec msgSpec = 2; */
|
||||
for (let i = 0; i < message.msgSpec.length; i++)
|
||||
SysMessageMsgSpec.internalBinaryWrite(message.msgSpec[i], writer.tag(2, WireType.LengthDelimited).fork(), options).join();
|
||||
/* SysMessage.SysMessageBodyWrapper bodyWrapper = 3; */
|
||||
if (message.bodyWrapper)
|
||||
SysMessageBodyWrapper.internalBinaryWrite(message.bodyWrapper, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.SysMessage
|
||||
*/
|
||||
export const SysMessage = new SysMessage$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class SysMessageHeader$Type extends MessageType<SysMessageHeader> {
|
||||
constructor() {
|
||||
super("SysMessage.SysMessageHeader", [
|
||||
{ no: 1, name: "PeerNumber", kind: "scalar", jsonName: "PeerNumber", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 2, name: "PeerString", kind: "scalar", jsonName: "PeerString", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 5, name: "Uin", kind: "scalar", jsonName: "Uin", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 6, name: "Uid", kind: "scalar", jsonName: "Uid", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<SysMessageHeader>): SysMessageHeader {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.peerNumber = 0;
|
||||
message.peerString = "";
|
||||
message.uin = 0;
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<SysMessageHeader>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessageHeader): SysMessageHeader {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* uint32 PeerNumber = 1 [json_name = "PeerNumber"];*/ 1:
|
||||
message.peerNumber = reader.uint32();
|
||||
break;
|
||||
case /* string PeerString = 2 [json_name = "PeerString"];*/ 2:
|
||||
message.peerString = reader.string();
|
||||
break;
|
||||
case /* uint32 Uin = 5 [json_name = "Uin"];*/ 5:
|
||||
message.uin = reader.uint32();
|
||||
break;
|
||||
case /* optional string Uid = 6 [json_name = "Uid"];*/ 6:
|
||||
message.uid = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: SysMessageHeader, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* uint32 PeerNumber = 1 [json_name = "PeerNumber"]; */
|
||||
if (message.peerNumber !== 0)
|
||||
writer.tag(1, WireType.Varint).uint32(message.peerNumber);
|
||||
/* string PeerString = 2 [json_name = "PeerString"]; */
|
||||
if (message.peerString !== "")
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.peerString);
|
||||
/* uint32 Uin = 5 [json_name = "Uin"]; */
|
||||
if (message.uin !== 0)
|
||||
writer.tag(5, WireType.Varint).uint32(message.uin);
|
||||
/* optional string Uid = 6 [json_name = "Uid"]; */
|
||||
if (message.uid !== undefined)
|
||||
writer.tag(6, WireType.LengthDelimited).string(message.uid);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.SysMessageHeader
|
||||
*/
|
||||
export const SysMessageHeader = new SysMessageHeader$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class SysMessageMsgSpec$Type extends MessageType<SysMessageMsgSpec> {
|
||||
constructor() {
|
||||
super("SysMessage.SysMessageMsgSpec", [
|
||||
{ no: 1, name: "msgType", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 2, name: "subType", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 3, name: "subSubType", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 5, name: "msgSeq", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 6, name: "time", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 12, name: "msgId", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
||||
{ no: 13, name: "other", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<SysMessageMsgSpec>): SysMessageMsgSpec {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.msgType = 0;
|
||||
message.subType = 0;
|
||||
message.subSubType = 0;
|
||||
message.msgSeq = 0;
|
||||
message.time = 0;
|
||||
message.msgId = 0n;
|
||||
message.other = 0;
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<SysMessageMsgSpec>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessageMsgSpec): SysMessageMsgSpec {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* uint32 msgType */ 1:
|
||||
message.msgType = reader.uint32();
|
||||
break;
|
||||
case /* uint32 subType */ 2:
|
||||
message.subType = reader.uint32();
|
||||
break;
|
||||
case /* uint32 subSubType */ 3:
|
||||
message.subSubType = reader.uint32();
|
||||
break;
|
||||
case /* uint32 msgSeq */ 5:
|
||||
message.msgSeq = reader.uint32();
|
||||
break;
|
||||
case /* uint32 time */ 6:
|
||||
message.time = reader.uint32();
|
||||
break;
|
||||
case /* uint64 msgId */ 12:
|
||||
message.msgId = reader.uint64().toBigInt();
|
||||
break;
|
||||
case /* uint32 other */ 13:
|
||||
message.other = reader.uint32();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: SysMessageMsgSpec, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* uint32 msgType = 1; */
|
||||
if (message.msgType !== 0)
|
||||
writer.tag(1, WireType.Varint).uint32(message.msgType);
|
||||
/* uint32 subType = 2; */
|
||||
if (message.subType !== 0)
|
||||
writer.tag(2, WireType.Varint).uint32(message.subType);
|
||||
/* uint32 subSubType = 3; */
|
||||
if (message.subSubType !== 0)
|
||||
writer.tag(3, WireType.Varint).uint32(message.subSubType);
|
||||
/* uint32 msgSeq = 5; */
|
||||
if (message.msgSeq !== 0)
|
||||
writer.tag(5, WireType.Varint).uint32(message.msgSeq);
|
||||
/* uint32 time = 6; */
|
||||
if (message.time !== 0)
|
||||
writer.tag(6, WireType.Varint).uint32(message.time);
|
||||
/* uint64 msgId = 12; */
|
||||
if (message.msgId !== 0n)
|
||||
writer.tag(12, WireType.Varint).uint64(message.msgId);
|
||||
/* uint32 other = 13; */
|
||||
if (message.other !== 0)
|
||||
writer.tag(13, WireType.Varint).uint32(message.other);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.SysMessageMsgSpec
|
||||
*/
|
||||
export const SysMessageMsgSpec = new SysMessageMsgSpec$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class SysMessageBodyWrapper$Type extends MessageType<SysMessageBodyWrapper> {
|
||||
constructor() {
|
||||
super("SysMessage.SysMessageBodyWrapper", [
|
||||
{ no: 2, name: "wrappedBody", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<SysMessageBodyWrapper>): SysMessageBodyWrapper {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.wrappedBody = new Uint8Array(0);
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<SysMessageBodyWrapper>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SysMessageBodyWrapper): SysMessageBodyWrapper {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* bytes wrappedBody */ 2:
|
||||
message.wrappedBody = reader.bytes();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: SysMessageBodyWrapper, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* bytes wrappedBody = 2; */
|
||||
if (message.wrappedBody.length)
|
||||
writer.tag(2, WireType.LengthDelimited).bytes(message.wrappedBody);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.SysMessageBodyWrapper
|
||||
*/
|
||||
export const SysMessageBodyWrapper = new SysMessageBodyWrapper$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class KeyValuePair$Type extends MessageType<KeyValuePair> {
|
||||
constructor() {
|
||||
super("SysMessage.KeyValuePair", [
|
||||
{ no: 1, name: "key", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "value", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<KeyValuePair>): KeyValuePair {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.key = "";
|
||||
message.value = "";
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<KeyValuePair>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: KeyValuePair): KeyValuePair {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string key */ 1:
|
||||
message.key = reader.string();
|
||||
break;
|
||||
case /* string value */ 2:
|
||||
message.value = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: KeyValuePair, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* string key = 1; */
|
||||
if (message.key !== "")
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.key);
|
||||
/* string value = 2; */
|
||||
if (message.value !== "")
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.value);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message SysMessage.KeyValuePair
|
||||
*/
|
||||
export const KeyValuePair = new KeyValuePair$Type();
|
@@ -114,7 +114,7 @@ export interface NodeIKernelBuddyService {
|
||||
|
||||
reportDoubtBuddyReqUnread(): void;
|
||||
|
||||
getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise<unknown>;
|
||||
getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise<GeneralCallResult & { arkMsg: string }>;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { ElementType, MessageElement, Peer, RawMessage, SendMessageElement } from '@/core/entities';
|
||||
import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
import { QueryMsgsParams, TmpChatInfoApi } from '../entities/msg';
|
||||
import { MsgReqType, QueryMsgsParams, TmpChatInfoApi } from '../entities/msg';
|
||||
|
||||
export interface NodeIKernelMsgService {
|
||||
|
||||
@@ -147,12 +147,15 @@ export interface NodeIKernelMsgService {
|
||||
msgList: RawMessage[]
|
||||
}>;
|
||||
|
||||
//@deprecated
|
||||
getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise<unknown>;
|
||||
|
||||
//@deprecated
|
||||
getMsgsIncludeSelf(peer: Peer, msgId: string, count: number, queryOrder: boolean): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[]
|
||||
}>;
|
||||
|
||||
//@deprecated
|
||||
getMsgsWithMsgTimeAndClientSeqForC2C(...args: unknown[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||
|
||||
getMsgsWithStatus(params: {
|
||||
@@ -168,7 +171,7 @@ export interface NodeIKernelMsgService {
|
||||
getMsgsBySeqRange(peer: Peer, startSeq: string, endSeq: string): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[]
|
||||
}>;
|
||||
|
||||
//@deprecated
|
||||
getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, unknownArg: boolean): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[]
|
||||
}>;
|
||||
@@ -179,6 +182,8 @@ export interface NodeIKernelMsgService {
|
||||
|
||||
getMsgsBySeqList(peer: Peer, seqList: string[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||
|
||||
getMsgsExt(msgReq: MsgReqType): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||
|
||||
getSingleMsg(Peer: Peer, msgSeq: string): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||
|
||||
getSourceOfReplyMsg(peer: Peer, MsgId: string, SourceSeq: string): unknown;
|
||||
@@ -318,7 +323,7 @@ export interface NodeIKernelMsgService {
|
||||
|
||||
getFileThumbSavePath(...args: unknown[]): unknown;
|
||||
|
||||
translatePtt2Text(msgId: string, peer: Peer, msgElement: unknown): unknown;
|
||||
translatePtt2Text(msgId: string, peer: Peer, msgElement: MessageElement): unknown;
|
||||
|
||||
setPttPlayedState(...args: unknown[]): unknown;
|
||||
|
||||
@@ -391,7 +396,12 @@ export interface NodeIKernelMsgService {
|
||||
|
||||
getEmojiResourcePath(...args: unknown[]): unknown;
|
||||
|
||||
JoinDragonGroupEmoji(JoinDragonGroupEmojiReq: any/*joinDragonGroupEmojiReq*/): unknown;
|
||||
JoinDragonGroupEmoji(JoinDragonGroupEmojiReq: {
|
||||
latestMsgSeq: string,
|
||||
manageEmojiId: number,
|
||||
manageMsgSeq: string,
|
||||
peerContact: Peer
|
||||
}): Promise<unknown>;
|
||||
|
||||
getMsgAbstracts(...args: unknown[]): unknown;
|
||||
|
||||
@@ -518,7 +528,7 @@ export interface NodeIKernelMsgService {
|
||||
|
||||
canImportOldDbMsg(...args: unknown[]): unknown;
|
||||
|
||||
setPowerStatus(z: boolean): unknown;
|
||||
setPowerStatus(isPowerOn: boolean): unknown;
|
||||
|
||||
canProcessDataMigration(...args: unknown[]): unknown;
|
||||
|
||||
@@ -607,7 +617,7 @@ export interface NodeIKernelMsgService {
|
||||
setIKernelPublicAccountAdapter(...args: unknown[]): unknown;
|
||||
|
||||
//tempChatGameSession有关
|
||||
createUidFromTinyId(fromTinyId: string, toTinyId: string): unknown;
|
||||
createUidFromTinyId(fromTinyId: string, toTinyId: string): string;
|
||||
|
||||
dataMigrationGetDataAvaiableContactList(...args: unknown[]): unknown;
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { AnyCnameRecord } from 'node:dns';
|
||||
import { BizKey, ModifyProfileParams, NodeIKernelProfileListener, ProfileBizType, SimpleInfo, UserDetailInfoByUinV2, UserDetailSource } from '@/core';
|
||||
import { BizKey, ModifyProfileParams, NodeIKernelProfileListener, ProfileBizType, SimpleInfo, UserDetailInfoByUin, UserDetailSource } from '@/core';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
|
||||
export interface NodeIKernelProfileService {
|
||||
@@ -55,7 +55,7 @@ export interface NodeIKernelProfileService {
|
||||
|
||||
getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise<GeneralCallResult>;
|
||||
|
||||
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUinV2>;
|
||||
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUin>;
|
||||
|
||||
getZplanAvatarInfos(args: string[]): Promise<unknown>;
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { ChatType } from '../entities';
|
||||
import { GeneralCallResult } from './common';
|
||||
|
||||
export interface NodeIKernelSearchService {
|
||||
|
||||
@@ -8,7 +9,12 @@ export interface NodeIKernelSearchService {
|
||||
|
||||
searchStranger(unknown: string, searchStranger: unknown, searchParams: unknown): Promise<unknown>;
|
||||
|
||||
searchGroup(...args: any[]): unknown;// needs 1 arguments
|
||||
searchGroup(param: {
|
||||
keyWords: string,
|
||||
groupNum: number,
|
||||
exactSearch: boolean,
|
||||
penetrate: string
|
||||
}): Promise<GeneralCallResult>;// needs 1 arguments
|
||||
|
||||
searchLocalInfo(keywords: string, unknown: number/*4*/): unknown;
|
||||
|
||||
|
11
src/onebot/action/extends/FetchUserProfileLike.ts
Normal file
11
src/onebot/action/extends/FetchUserProfileLike.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import BaseAction from '../BaseAction';
|
||||
import { ActionName } from '../types';
|
||||
|
||||
export class FetchUserProfileLike extends BaseAction<{ qq: number }, any> {
|
||||
actionName = ActionName.FetchUserProfileLike;
|
||||
|
||||
async _handle(payload: { qq: number }) {
|
||||
if (!payload.qq) throw new Error('qq is required');
|
||||
return await this.core.apis.UserApi.getUidByUinV2(payload.qq.toString());
|
||||
}
|
||||
}
|
@@ -19,26 +19,21 @@ export class OCRImage extends BaseAction<Payload, any> {
|
||||
payloadSchema = SchemaData;
|
||||
|
||||
async _handle(payload: Payload) {
|
||||
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.image));
|
||||
const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.image));
|
||||
if (!success) {
|
||||
throw `OCR ${payload.image}失败,image字段可能格式不正确`;
|
||||
}
|
||||
if (path) {
|
||||
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
||||
const ret = await this.core.apis.SystemApi.ocrImage(path);
|
||||
if (!isLocal) {
|
||||
fs.unlink(path, () => {
|
||||
});
|
||||
}
|
||||
fs.unlink(path, () => { });
|
||||
|
||||
if (!ret) {
|
||||
throw `OCR ${payload.file}失败`;
|
||||
}
|
||||
return ret.result;
|
||||
}
|
||||
if (!isLocal) {
|
||||
fs.unlink(path, () => {
|
||||
});
|
||||
}
|
||||
fs.unlink(path, () => { });
|
||||
throw `OCR ${payload.file}失败,文件可能不存在`;
|
||||
}
|
||||
}
|
||||
|
@@ -24,17 +24,16 @@ export default class SetAvatar extends BaseAction<Payload, null> {
|
||||
}
|
||||
|
||||
async _handle(payload: Payload): Promise<null> {
|
||||
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
|
||||
const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
|
||||
if (!success) {
|
||||
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
||||
}
|
||||
if (path) {
|
||||
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
||||
const ret = await this.core.apis.UserApi.setQQAvatar(path);
|
||||
if (!isLocal) {
|
||||
fs.unlink(path, () => {
|
||||
});
|
||||
}
|
||||
fs.unlink(path, () => {
|
||||
});
|
||||
|
||||
if (!ret) {
|
||||
throw `头像${payload.file}设置失败,api无返回`;
|
||||
}
|
||||
@@ -45,10 +44,8 @@ export default class SetAvatar extends BaseAction<Payload, null> {
|
||||
throw `头像${payload.file}设置失败,未知的错误,${ret['result']}:${ret['errMsg']}`;
|
||||
}
|
||||
} else {
|
||||
if (!isLocal) {
|
||||
fs.unlink(path, () => {
|
||||
});
|
||||
}
|
||||
fs.unlink(path, () => { });
|
||||
|
||||
throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`;
|
||||
}
|
||||
return null;
|
||||
|
@@ -7,17 +7,18 @@ const SchemaData = {
|
||||
properties: {
|
||||
group_id: { type: ['string', 'number'] },
|
||||
folder_id: { type: 'string' },
|
||||
folder: { type: 'string' }
|
||||
},
|
||||
required: ['group_id', 'folder_id'],
|
||||
required: ['group_id'],
|
||||
} as const satisfies JSONSchema;
|
||||
|
||||
type Payload = FromSchema<typeof SchemaData>;
|
||||
|
||||
export class DeleteGroupFileFolder extends BaseAction<Payload, any> {
|
||||
export class DeleteGroupFileFolder extends BaseAction<Payload, any> {
|
||||
actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder;
|
||||
payloadSchema = SchemaData;
|
||||
async _handle(payload: Payload) {
|
||||
return (await this.core.apis.GroupApi.DelGroupFileFolder(
|
||||
payload.group_id.toString(), payload.folder_id)).groupFileCommonResult;
|
||||
payload.group_id.toString(), payload.folder ?? payload.folder_id ?? '')).groupFileCommonResult;
|
||||
}
|
||||
}
|
||||
|
@@ -73,7 +73,7 @@ export default class GoCQHTTPDownloadFile extends BaseAction<Payload, FileRespon
|
||||
headers[headerItem] = '';
|
||||
} else {
|
||||
const key = headerItem.substring(0, spilt);
|
||||
headers[key] = headerItem.substring(0, spilt + 1);
|
||||
headers[key] = headerItem.substring(spilt + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,9 +8,10 @@ const SchemaData = {
|
||||
properties: {
|
||||
group_id: { type: ['string', 'number'] },
|
||||
folder_id: { type: 'string' },
|
||||
folder: { type: 'string' },
|
||||
file_count: { type: ['string', 'number'] },
|
||||
},
|
||||
required: ['group_id', 'folder_id'],
|
||||
required: ['group_id'],
|
||||
} as const satisfies JSONSchema;
|
||||
|
||||
type Payload = FromSchema<typeof SchemaData>;
|
||||
@@ -26,7 +27,7 @@ export class GetGroupFilesByFolder extends BaseAction<any, any> {
|
||||
startIndex: 0,
|
||||
sortOrder: 2,
|
||||
showOnlinedocFolder: 0,
|
||||
folderId: payload.folder_id,
|
||||
folderId: payload.folder ?? payload.folder_id ?? '',
|
||||
}).catch(() => []);
|
||||
return {
|
||||
files: ret.filter(item => item.fileInfo)
|
||||
|
@@ -20,25 +20,26 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
|
||||
|
||||
async _handle(payload: Payload): Promise<OB11User> {
|
||||
const user_id = payload.user_id.toString();
|
||||
const extendData = await this.core.apis.UserApi.getUserDetailInfoByUinV2(user_id);
|
||||
const uid = (await this.core.apis.UserApi.getUidByUinV2(user_id))!;
|
||||
if (!uid || uid.indexOf('*') != -1) {
|
||||
return {
|
||||
...extendData.detail.simpleInfo.coreInfo,
|
||||
...extendData.detail.commonExt,
|
||||
...extendData.detail.simpleInfo.baseInfo,
|
||||
...extendData.detail.simpleInfo.relationFlags,
|
||||
...extendData.detail.simpleInfo.status,
|
||||
user_id: parseInt(extendData.detail.uin) || 0,
|
||||
nickname: extendData.detail.simpleInfo.coreInfo.nick,
|
||||
sex: OB11UserSex.unknown,
|
||||
age: extendData.detail.simpleInfo.baseInfo.age || 0,
|
||||
qid: extendData.detail.simpleInfo.baseInfo.qid,
|
||||
level: calcQQLevel(extendData.detail.commonExt?.qqLevel ?? 0) || 0,
|
||||
login_days: 0,
|
||||
};
|
||||
}
|
||||
const data = { ...extendData, ...(await this.core.apis.UserApi.getUserDetailInfo(uid)) };
|
||||
return OB11Entities.stranger(data);
|
||||
const extendData = await this.core.apis.UserApi.getUserDetailInfoByUin(user_id);
|
||||
let uid = (await this.core.apis.UserApi.getUidByUinV2(user_id));
|
||||
if (!uid) uid = extendData.detail.uid;
|
||||
const info = (await this.core.apis.UserApi.getUserDetailInfo(uid));
|
||||
return {
|
||||
user_id: parseInt(extendData.detail.uin) ?? 0,
|
||||
uid: info.uid ?? uid,
|
||||
nickname: extendData.detail.simpleInfo.coreInfo.nick,
|
||||
age: extendData.detail.simpleInfo.baseInfo.age ?? info.age,
|
||||
qid: extendData.detail.simpleInfo.baseInfo.qid,
|
||||
qqLevel: calcQQLevel(extendData.detail.commonExt?.qqLevel ?? info.qqLevel),
|
||||
sex: OB11Entities.sex(extendData.detail.simpleInfo.baseInfo.sex) ?? OB11UserSex.unknown,
|
||||
long_nick: extendData.detail.simpleInfo.baseInfo.longNick ?? info.longNick,
|
||||
reg_time: extendData.detail.commonExt.regTime ?? info.regTime,
|
||||
is_vip: extendData.detail.simpleInfo.vasInfo?.svipFlag,
|
||||
is_years_vip: extendData.detail.simpleInfo.vasInfo?.yearVipFlag,
|
||||
vip_level: extendData.detail.simpleInfo.vasInfo?.vipLevel,
|
||||
remark: extendData.detail.simpleInfo.coreInfo.remark ?? info.remark,
|
||||
status: extendData.detail.simpleInfo.status?.status ?? info.status,
|
||||
login_days: 0,//失效
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -31,7 +31,6 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
||||
//公告图逻辑
|
||||
const {
|
||||
path,
|
||||
isLocal,
|
||||
success,
|
||||
} = (await uri2local(this.core.NapCatTempPath, payload.image));
|
||||
if (!success) {
|
||||
@@ -45,10 +44,10 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
||||
if (ImageUploadResult.errCode != 0) {
|
||||
throw `群公告${payload.image}设置失败,图片上传失败`;
|
||||
}
|
||||
if (!isLocal) {
|
||||
unlink(path, () => {
|
||||
});
|
||||
}
|
||||
|
||||
unlink(path, () => {
|
||||
});
|
||||
|
||||
UploadImage = ImageUploadResult.picInfo;
|
||||
}
|
||||
|
||||
@@ -58,7 +57,6 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
||||
const noticeShowEditCard = +(payload.is_show_edit_card ?? 0);
|
||||
const noticeTipWindowType = +(payload.tip_window_type ?? 0);
|
||||
const noticeConfirmRequired = +(payload.confirm_required ?? 1);
|
||||
//const publishGroupBulletinResult = await this.core.apis.GroupApi.publishGroupBulletin(payload.group_id.toString(), payload.content, UploadImage, noticePinned, noticeConfirmRequired);
|
||||
const publishGroupBulletinResult = await this.core.apis.WebApi.setGroupNotice(
|
||||
payload.group_id.toString(),
|
||||
payload.content,
|
||||
@@ -72,7 +70,7 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
|
||||
UploadImage?.height
|
||||
);
|
||||
if (!publishGroupBulletinResult || publishGroupBulletinResult.ec != 0) {
|
||||
throw `设置群公告失败,错误信息:${publishGroupBulletinResult?.em}`;
|
||||
throw new Error(`设置群公告失败,错误信息:${publishGroupBulletinResult?.em}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@@ -25,17 +25,14 @@ export default class SetGroupPortrait extends BaseAction<Payload, any> {
|
||||
}
|
||||
|
||||
async _handle(payload: Payload): Promise<any> {
|
||||
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
|
||||
const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
|
||||
if (!success) {
|
||||
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
||||
}
|
||||
if (path) {
|
||||
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
||||
const ret = await this.core.apis.GroupApi.setGroupAvatar(payload.group_id.toString(), path) as any;
|
||||
if (!isLocal) {
|
||||
fs.unlink(path, () => {
|
||||
});
|
||||
}
|
||||
fs.unlink(path, () => { });
|
||||
if (!ret) {
|
||||
throw `头像${payload.file}设置失败,api无返回`;
|
||||
}
|
||||
@@ -46,10 +43,7 @@ export default class SetGroupPortrait extends BaseAction<Payload, any> {
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
if (!isLocal) {
|
||||
fs.unlink(path, () => {
|
||||
});
|
||||
}
|
||||
fs.unlink(path, () => {});
|
||||
throw `头像${payload.file}设置失败,无法获取头像,文件可能不存在`;
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import BaseAction from '../BaseAction';
|
||||
import { ActionName } from '../types';
|
||||
import { ChatType } from '@/core/entities';
|
||||
import { ChatType, Peer } from '@/core/entities';
|
||||
import fs from 'fs';
|
||||
import { uri2local } from '@/common/file';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
import { MessageContext } from '@/onebot/api';
|
||||
|
||||
const SchemaData = {
|
||||
type: 'object',
|
||||
@@ -29,14 +30,19 @@ export default class GoCQHTTPUploadGroupFile extends BaseAction<Payload, null> {
|
||||
file = `file://${file}`;
|
||||
}
|
||||
const downloadResult = await uri2local(this.core.NapCatTempPath, file);
|
||||
const peer: Peer = {
|
||||
chatType: ChatType.KCHATTYPEGROUP,
|
||||
peerUid: payload.group_id.toString(),
|
||||
};
|
||||
if (!downloadResult.success) {
|
||||
throw new Error(downloadResult.errMsg);
|
||||
}
|
||||
const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name, payload.folder_id);
|
||||
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId({
|
||||
chatType: ChatType.KCHATTYPEGROUP,
|
||||
peerUid: payload.group_id.toString(),
|
||||
}, [sendFileEle], [], true);
|
||||
const msgContext: MessageContext = {
|
||||
peer: peer,
|
||||
deleteAfterSentFiles: []
|
||||
};
|
||||
const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name, payload.folder ?? payload.folder_id);
|
||||
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, [sendFileEle], [], true);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,8 @@ import { ChatType, Peer, SendFileElement } from '@/core/entities';
|
||||
import fs from 'fs';
|
||||
import { uri2local } from '@/common/file';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
import { MessageContext } from '@/onebot/api';
|
||||
import { ContextMode, createContext } from '../msg/SendMsg';
|
||||
|
||||
const SchemaData = {
|
||||
type: 'object',
|
||||
@@ -42,7 +44,15 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
|
||||
if (!downloadResult.success) {
|
||||
throw new Error(downloadResult.errMsg);
|
||||
}
|
||||
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name);
|
||||
|
||||
const msgContext: MessageContext = {
|
||||
peer: await createContext(this.core, {
|
||||
user_id: payload.user_id.toString(),
|
||||
group_id: undefined,
|
||||
}, ContextMode.Private),
|
||||
deleteAfterSentFiles: []
|
||||
};
|
||||
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name);
|
||||
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(await this.getPeer(payload), [sendFileEle], [], true);
|
||||
return null;
|
||||
}
|
||||
|
@@ -20,7 +20,17 @@ class GetGroupInfo extends BaseAction<Payload, OB11Group> {
|
||||
|
||||
async _handle(payload: Payload) {
|
||||
const group = (await this.core.apis.GroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString());
|
||||
if (!group) throw `群${payload.group_id}不存在`;
|
||||
if (!group) {
|
||||
const data = await this.core.apis.GroupApi.searchGroup(payload.group_id.toString());
|
||||
if (!data) throw new Error('Group not found');
|
||||
return {
|
||||
...data.searchGroupInfo,
|
||||
group_id: +payload.group_id,
|
||||
group_name: data.searchGroupInfo.groupName,
|
||||
member_count: data.searchGroupInfo.memberNum,
|
||||
max_member_count: data.searchGroupInfo.maxMemberNum,
|
||||
};
|
||||
}
|
||||
return OB11Entities.group(group);
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ import { OB11Entities } from '@/onebot/entities';
|
||||
import BaseAction from '../BaseAction';
|
||||
import { ActionName } from '../types';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
import { calcQQLevel } from '@/common/helper';
|
||||
|
||||
const SchemaData = {
|
||||
type: 'object',
|
||||
@@ -22,7 +23,8 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
|
||||
async _handle(payload: Payload) {
|
||||
const groupMembers = await this.core.apis.GroupApi.getGroupMembersV2(payload.group_id.toString());
|
||||
const groupMembersArr = Array.from(groupMembers.values());
|
||||
|
||||
let uids = groupMembersArr.map(item => item.uid);
|
||||
//let CoreAndBase = await this.core.apis.GroupApi.getCoreAndBaseInfo(uids)
|
||||
let _groupMembers = groupMembersArr.map(item => {
|
||||
return OB11Entities.groupMember(payload.group_id.toString(), item);
|
||||
});
|
||||
@@ -32,34 +34,38 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
|
||||
|
||||
for (let i = 0, len = _groupMembers.length; i < len; i++) {
|
||||
// 保证基础数据有这个 同时避免群管插件过于依赖这个杀了
|
||||
_groupMembers[i].join_time = date;
|
||||
_groupMembers[i].last_sent_time = date;
|
||||
const Member = await this.core.apis.GroupApi.getGroupMember(payload.group_id.toString(), _groupMembers[i].user_id);
|
||||
_groupMembers[i].join_time = +(Member?.joinTime ?? date);
|
||||
_groupMembers[i].last_sent_time = +(Member?.lastSpeakTime ?? date);
|
||||
MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]);
|
||||
}
|
||||
|
||||
|
||||
const selfRole = groupMembers.get(this.core.selfInfo.uid)?.role;
|
||||
const isPrivilege = selfRole === 3 || selfRole === 4;
|
||||
|
||||
_groupMembers.forEach(item => {
|
||||
item.last_sent_time = date;
|
||||
item.join_time = date;
|
||||
});
|
||||
|
||||
if (isPrivilege) {
|
||||
const webGroupMembers = await this.core.apis.WebApi.getGroupMembers(payload.group_id.toString());
|
||||
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
||||
if (!webGroupMembers[i]?.uin) {
|
||||
continue;
|
||||
}
|
||||
const MemberData = MemberMap.get(webGroupMembers[i]?.uin);
|
||||
if (MemberData) {
|
||||
MemberData.join_time = webGroupMembers[i]?.join_time;
|
||||
MemberData.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
||||
MemberData.qage = webGroupMembers[i]?.qage;
|
||||
MemberData.level = webGroupMembers[i]?.lv.level.toString();
|
||||
MemberMap.set(webGroupMembers[i]?.uin, MemberData);
|
||||
try {
|
||||
const webGroupMembers = await this.core.apis.WebApi.getGroupMembers(payload.group_id.toString());
|
||||
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
||||
if (!webGroupMembers[i]?.uin) {
|
||||
continue;
|
||||
}
|
||||
const MemberData = MemberMap.get(webGroupMembers[i]?.uin);
|
||||
if (MemberData) {
|
||||
MemberData.join_time = webGroupMembers[i]?.join_time;
|
||||
MemberData.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
||||
MemberData.qage = webGroupMembers[i]?.qage;
|
||||
MemberData.level = webGroupMembers[i]?.lv.level.toString();
|
||||
MemberMap.set(webGroupMembers[i]?.uin, MemberData);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
const logger = this.core.context.logger;
|
||||
logger.logError.bind(logger)('GetGroupMemberList', e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_groupMembers = Array.from(MemberMap.values());
|
||||
|
@@ -68,8 +68,8 @@ import SetGroupPortrait from './go-cqhttp/SetGroupPortrait';
|
||||
import { FetchCustomFace } from './extends/FetchCustomFace';
|
||||
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivateFile';
|
||||
import { FetchEmojiLike } from './extends/FetchEmojiLike';
|
||||
import { FetchUserProfileLike } from './extends/FetchUserProfileLike';
|
||||
import { NapCatCore } from '@/core';
|
||||
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
import GetGuildProfile from './guild/GetGuildProfile';
|
||||
import SetModelShow from './go-cqhttp/SetModelShow';
|
||||
@@ -83,6 +83,8 @@ import { DeleteGroupFileFolder } from '@/onebot/action/go-cqhttp/DeleteGroupFile
|
||||
import { GetGroupFileSystemInfo } from '@/onebot/action/go-cqhttp/GetGroupFileSystemInfo';
|
||||
import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
|
||||
import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesByFolder';
|
||||
import { GetGroupSystemMsg } from './system/GetSystemMsg';
|
||||
|
||||
|
||||
export type ActionMap = Map<string, BaseAction<any, any>>;
|
||||
|
||||
@@ -176,6 +178,8 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
|
||||
new DeleteGroupFileFolder(obContext, core),
|
||||
new GetGroupFileSystemInfo(obContext, core),
|
||||
new GetGroupFilesByFolder(obContext, core),
|
||||
new GetGroupSystemMsg(obContext, core),
|
||||
new FetchUserProfileLike(obContext, core),
|
||||
];
|
||||
const actionMap = new Map();
|
||||
for (const action of actionHandlers) {
|
||||
|
@@ -3,6 +3,7 @@ import {
|
||||
OB11MessageDataType,
|
||||
OB11MessageMixType,
|
||||
OB11MessageNode,
|
||||
OB11PostContext,
|
||||
OB11PostSendMsg,
|
||||
} from '@/onebot/types';
|
||||
import { ActionName, BaseCheckResult } from '@/onebot/action/types';
|
||||
@@ -30,7 +31,7 @@ export function normalize(message: OB11MessageMixType, autoEscape = false): OB11
|
||||
) : Array.isArray(message) ? message : [message];
|
||||
}
|
||||
|
||||
export async function createContext(core: NapCatCore, payload: OB11PostSendMsg, contextMode: ContextMode): Promise<Peer> {
|
||||
export async function createContext(core: NapCatCore, payload: OB11PostContext, contextMode: ContextMode): Promise<Peer> {
|
||||
// This function determines the type of message by the existence of user_id / group_id,
|
||||
// not message_type.
|
||||
// This redundant design of Ob11 here should be blamed.
|
||||
|
50
src/onebot/action/system/GetSystemMsg.ts
Normal file
50
src/onebot/action/system/GetSystemMsg.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { GroupNotifyMsgStatus } from '@/core';
|
||||
import BaseAction from '../BaseAction';
|
||||
import { ActionName } from '../types';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
|
||||
const SchemaData = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
group_id: { type: ['number', 'string'] },
|
||||
},
|
||||
} as const satisfies JSONSchema;
|
||||
|
||||
type Payload = FromSchema<typeof SchemaData>;
|
||||
|
||||
export class GetGroupSystemMsg extends BaseAction<void, any> {
|
||||
actionName = ActionName.GetGroupSystemMsg;
|
||||
|
||||
async _handle(payload: void) {
|
||||
const NTQQUserApi = this.core.apis.UserApi;
|
||||
const NTQQGroupApi = this.core.apis.GroupApi;
|
||||
// 默认10条 该api未完整实现 包括响应数据规范化 类型规范化
|
||||
const SingleScreenNotifies = await NTQQGroupApi.getSingleScreenNotifies(false,10);
|
||||
const retData: any = { InvitedRequest: [], join_requests: [] };
|
||||
for (const SSNotify of SingleScreenNotifies) {
|
||||
if (SSNotify.type == 1) {
|
||||
retData.InvitedRequest.push({
|
||||
request_id: SSNotify.seq,
|
||||
invitor_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid),
|
||||
invitor_nick: SSNotify.user1?.nickName,
|
||||
group_id: SSNotify.group?.groupCode,
|
||||
group_name: SSNotify.group?.groupName,
|
||||
checked: SSNotify.status === GroupNotifyMsgStatus.KUNHANDLE ? false : true,
|
||||
actor: await NTQQUserApi.getUinByUidV2(SSNotify.user2?.uid) || 0,
|
||||
});
|
||||
} else if (SSNotify.type == 7) {
|
||||
retData.join_requests.push({
|
||||
request_id: SSNotify.seq,
|
||||
requester_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid),
|
||||
requester_nick: SSNotify.user1?.nickName,
|
||||
group_id: SSNotify.group?.groupCode,
|
||||
group_name: SSNotify.group?.groupName,
|
||||
checked: SSNotify.status === GroupNotifyMsgStatus.KUNHANDLE ? false : true,
|
||||
actor: await NTQQUserApi.getUinByUidV2(SSNotify.user2?.uid) || 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return retData;
|
||||
}
|
||||
}
|
@@ -16,8 +16,8 @@ export interface InvalidCheckResult {
|
||||
export enum ActionName {
|
||||
// 以下为扩展napcat扩展
|
||||
Unknown = 'unknown',
|
||||
SharePeer = 'ArkShareGroup',
|
||||
ShareGroupEx = 'ArkSharePeer',
|
||||
SharePeer = 'ArkSharePeer',
|
||||
ShareGroupEx = 'ArkShareGroup',
|
||||
RebootNormal = 'reboot_normal',//无快速登录重新启动
|
||||
GetRobotUinRange = 'get_robot_uin_range',
|
||||
SetOnlineStatus = 'set_online_status',
|
||||
@@ -116,5 +116,7 @@ export enum ActionName {
|
||||
SetInputStatus = 'set_input_status',
|
||||
GetCSRF = 'get_csrf_token',
|
||||
DelGroupNotice = '_del_group_notice',
|
||||
GetGroupInfoEx = "get_group_info_ex"
|
||||
GetGroupInfoEx = "get_group_info_ex",
|
||||
GetGroupSystemMsg = 'get_group_system_msg',
|
||||
FetchUserProfileLike = "fetch_user_profile_like",
|
||||
}
|
||||
|
@@ -140,15 +140,25 @@ export class OneBotGroupApi {
|
||||
}
|
||||
if (element.grayTipElement.jsonGrayTipElement.busiId == 2407) {
|
||||
//下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE
|
||||
const memberUin = json.items[1].param[0];
|
||||
const title = json.items[3].txt;
|
||||
logger.logDebug('收到群成员新头衔消息', json);
|
||||
return new OB11GroupTitleEvent(
|
||||
this.core,
|
||||
parseInt(msg.peerUid),
|
||||
parseInt(memberUin),
|
||||
title,
|
||||
);
|
||||
const type = json.items[json.items.length - 1]?.txt;
|
||||
switch (type) {
|
||||
case "头衔": {
|
||||
const memberUin = json.items[1].param[0];
|
||||
const title = json.items[3].txt;
|
||||
logger.logDebug('收到群成员新头衔消息', json);
|
||||
return new OB11GroupTitleEvent(
|
||||
this.core,
|
||||
parseInt(msg.peerUid),
|
||||
parseInt(memberUin),
|
||||
title,
|
||||
);
|
||||
}
|
||||
case "移出":
|
||||
logger.logDebug('收到机器人被踢消息', json);
|
||||
return;
|
||||
default:
|
||||
logger.logWarn('收到未知的灰条消息', json);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@ import { RequestUtil } from '@/common/request';
|
||||
import fs from 'node:fs';
|
||||
import fsPromise from 'node:fs/promises';
|
||||
import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent';
|
||||
import { SysMessage, SysMessageType } from '@/core/proto/ProfileLike';
|
||||
|
||||
type RawToOb11Converters = {
|
||||
[Key in keyof MessageElement as Key extends `${string}Element` ? Key : never]: (
|
||||
@@ -107,7 +108,7 @@ export class OneBotMsgApi {
|
||||
peerUid: msg.peerUid,
|
||||
guildId: '',
|
||||
};
|
||||
const encodedFileId = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+element.fileName);
|
||||
const encodedFileId = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + element.fileName);
|
||||
return {
|
||||
type: OB11MessageDataType.image,
|
||||
data: {
|
||||
@@ -138,7 +139,7 @@ export class OneBotMsgApi {
|
||||
file: element.fileName,
|
||||
path: element.filePath,
|
||||
url: pathToFileURL(element.filePath).href,
|
||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+element.fileName),
|
||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + element.fileName),
|
||||
file_size: element.fileSize,
|
||||
file_unique: element.fileName,
|
||||
},
|
||||
@@ -184,8 +185,8 @@ export class OneBotMsgApi {
|
||||
type: OB11MessageDataType.image,
|
||||
data: {
|
||||
file: 'marketface',
|
||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+_.key+".jpg"),
|
||||
path: elementWrapper.elementId,
|
||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + _.key + ".jpg"),
|
||||
path: url,
|
||||
url: url,
|
||||
file_unique: _.key
|
||||
},
|
||||
@@ -262,7 +263,7 @@ export class OneBotMsgApi {
|
||||
if (!videoDownUrl) {
|
||||
videoDownUrl = element.filePath;
|
||||
}
|
||||
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+element.fileName);
|
||||
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + element.fileName);
|
||||
return {
|
||||
type: OB11MessageDataType.video,
|
||||
data: {
|
||||
@@ -282,7 +283,7 @@ export class OneBotMsgApi {
|
||||
peerUid: msg.peerUid,
|
||||
guildId: '',
|
||||
};
|
||||
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "."+element.fileName);
|
||||
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "." + element.fileName);
|
||||
return {
|
||||
type: OB11MessageDataType.voice,
|
||||
data: {
|
||||
@@ -460,17 +461,17 @@ export class OneBotMsgApi {
|
||||
// File service
|
||||
[OB11MessageDataType.image]: async (sendMsg, context) => {
|
||||
const sendPicElement = await this.core.apis.FileApi.createValidSendPicElement(
|
||||
context,
|
||||
(await this.handleOb11FileLikeMessage(sendMsg, context)).path,
|
||||
sendMsg.data.summary,
|
||||
sendMsg.data.sub_type,
|
||||
);
|
||||
context.deleteAfterSentFiles.push(sendPicElement.picElement.sourcePath);
|
||||
return sendPicElement;
|
||||
},
|
||||
|
||||
[OB11MessageDataType.file]: async (sendMsg, context) => {
|
||||
const { path, fileName } = await this.handleOb11FileLikeMessage(sendMsg, context);
|
||||
return await this.core.apis.FileApi.createValidSendFileElement(path, fileName);
|
||||
return await this.core.apis.FileApi.createValidSendFileElement(context, path, fileName);
|
||||
},
|
||||
|
||||
[OB11MessageDataType.video]: async (sendMsg, context) => {
|
||||
@@ -481,9 +482,7 @@ export class OneBotMsgApi {
|
||||
const uri2LocalRes = await uri2local(this.core.NapCatTempPath, thumb);
|
||||
if (uri2LocalRes.success) thumb = uri2LocalRes.path;
|
||||
}
|
||||
const videoEle = await this.core.apis.FileApi.createValidSendVideoElement(path, fileName, thumb);
|
||||
|
||||
context.deleteAfterSentFiles.push(videoEle.videoElement.filePath);
|
||||
const videoEle = await this.core.apis.FileApi.createValidSendVideoElement(context, path, fileName, thumb);
|
||||
return videoEle;
|
||||
},
|
||||
|
||||
@@ -608,6 +607,14 @@ export class OneBotMsgApi {
|
||||
}),
|
||||
|
||||
[OB11MessageDataType.miniapp]: async () => undefined,
|
||||
|
||||
[OB11MessageDataType.contact]: async ({ data }, context) => {
|
||||
let arkJson = await this.core.apis.UserApi.getBuddyRecommendContactArkJson(data.qq, '');
|
||||
return this.ob11ToRawConverters.json({
|
||||
data: { data: arkJson.arkMsg },
|
||||
type: OB11MessageDataType.json
|
||||
}, context);
|
||||
}
|
||||
};
|
||||
|
||||
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
||||
@@ -630,7 +637,7 @@ export class OneBotMsgApi {
|
||||
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_XMLMSG) {
|
||||
//好友添加成功事件
|
||||
if (element.grayTipElement.xmlElement.templId === '10229' && msg.peerUin !== '') {
|
||||
return new OB11FriendAddNoticeEvent(this.core, parseInt(msg.peerUin));
|
||||
return new OB11FriendAddNoticeEvent(this.core, parseInt(msg.peerUin) || Number(await this.core.apis.UserApi.getUinByUidV2(msg.peerUid)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -798,18 +805,13 @@ export class OneBotMsgApi {
|
||||
{ data: inputdata }: OB11MessageFileBase,
|
||||
{ deleteAfterSentFiles }: MessageContext,
|
||||
) {
|
||||
const isBlankUrl = !inputdata.url || inputdata.url === '';
|
||||
const isBlankFile = !inputdata.file || inputdata.file === '';
|
||||
const isBlankPath = !inputdata.path || inputdata.path === '';
|
||||
if (isBlankUrl && isBlankFile) {
|
||||
const realUri = inputdata.url || inputdata.file || inputdata.path || '';
|
||||
if (realUri.length === 0) {
|
||||
this.core.context.logger.logError('文件消息缺少参数', inputdata);
|
||||
throw Error('文件消息缺少参数');
|
||||
}
|
||||
//path->url->file
|
||||
const realUri = (!isBlankUrl ? inputdata.url :(!isBlankPath ? inputdata.path:inputdata.file ))??'';
|
||||
const {
|
||||
path,
|
||||
isLocal,
|
||||
fileName,
|
||||
errMsg,
|
||||
success,
|
||||
@@ -820,10 +822,42 @@ export class OneBotMsgApi {
|
||||
throw Error('文件下载失败' + errMsg);
|
||||
}
|
||||
|
||||
if (!isLocal) { // 只删除http和base64转过来的文件
|
||||
deleteAfterSentFiles.push(path);
|
||||
}
|
||||
deleteAfterSentFiles.push(path);
|
||||
|
||||
return { path, fileName: inputdata.name ?? fileName };
|
||||
}
|
||||
async parseSysMessage(msg: number[]) {
|
||||
const sysMsg = SysMessage.decode(Uint8Array.from(msg)) as unknown as SysMessageType;
|
||||
if (sysMsg.msgSpec.length === 0) {
|
||||
return;
|
||||
}
|
||||
const { msgType, subType, subSubType } = sysMsg.msgSpec[0];
|
||||
if (msgType === 528 && subType === 39 && subSubType === 39) {
|
||||
if (!sysMsg.bodyWrapper) return;
|
||||
const event = await this.obContext.apis.UserApi.parseLikeEvent(sysMsg.bodyWrapper.wrappedBody);
|
||||
return event;
|
||||
}
|
||||
/*
|
||||
if (msgType === 732 && subType === 16 && subSubType === 16) {
|
||||
const greyTip = GreyTipWrapper.fromBinary(Uint8Array.from(sysMsg.bodyWrapper!.wrappedBody.slice(7)));
|
||||
if (greyTip.subTypeId === 36) {
|
||||
const emojiLikeToOthers = EmojiLikeToOthersWrapper1
|
||||
.fromBinary(greyTip.rest)
|
||||
.wrapper!
|
||||
.body!;
|
||||
if (emojiLikeToOthers.attributes?.operation !== 1) { // Un-like
|
||||
return;
|
||||
}
|
||||
const eventOrEmpty = await this.apis.GroupApi.createGroupEmojiLikeEvent(
|
||||
greyTip.groupCode.toString(),
|
||||
await this.core.apis.UserApi.getUinByUidV2(emojiLikeToOthers.attributes!.senderUid),
|
||||
emojiLikeToOthers.msgSpec!.msgSeq.toString(),
|
||||
emojiLikeToOthers.attributes!.emojiId,
|
||||
);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@ export class OneBotQuickActionApi {
|
||||
const peerContextMode = msg.message_type == 'private' ? ContextMode.Private : ContextMode.Group;
|
||||
|
||||
const peer: Peer = await createContext(this.core, {
|
||||
message: "",
|
||||
message_type: undefined,
|
||||
group_id: msg.group_id?.toString(),
|
||||
user_id: msg.user_id?.toString(),
|
||||
}, peerContextMode);
|
||||
|
@@ -1,6 +1,8 @@
|
||||
import { NapCatCore } from '@/core';
|
||||
import { profileLikeTip, ProfileLikeTipType } from '@/core/proto/ProfileLike';
|
||||
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
import { OB11ProfileLikeEvent } from '../event/notice/OB11ProfileLikeEvent';
|
||||
|
||||
export class OneBotUserApi {
|
||||
obContext: NapCatOneBot11Adapter;
|
||||
@@ -10,4 +12,21 @@ export class OneBotUserApi {
|
||||
this.obContext = obContext;
|
||||
this.core = core;
|
||||
}
|
||||
async parseLikeEvent(wrappedBody: Uint8Array): Promise<OB11ProfileLikeEvent | undefined> {
|
||||
const likeTip = profileLikeTip.decode(Uint8Array.from(wrappedBody)) as unknown as ProfileLikeTipType;
|
||||
if (likeTip?.msgType !== 0 || likeTip?.subType !== 203) return;
|
||||
this.core.context.logger.logDebug("收到点赞通知消息");
|
||||
const likeMsg = likeTip.content.msg;
|
||||
if (!likeMsg) return;
|
||||
const detail = likeMsg.detail;
|
||||
if (!detail) return;
|
||||
const times = detail.txt.match(/\d+/) ?? "0";
|
||||
return new OB11ProfileLikeEvent(
|
||||
this.core,
|
||||
Number(detail.uin),
|
||||
detail.nickname,
|
||||
parseInt(times[0], 10),
|
||||
likeMsg.time,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -48,7 +48,8 @@ export class OB11Entities {
|
||||
}[role];
|
||||
}
|
||||
|
||||
static sex(sex: Sex): OB11UserSex {
|
||||
static sex(sex?: Sex): OB11UserSex {
|
||||
if (!sex) return OB11UserSex.unknown;
|
||||
return {
|
||||
[Sex.male]: OB11UserSex.male,
|
||||
[Sex.female]: OB11UserSex.female,
|
||||
@@ -126,6 +127,7 @@ export class OB11Entities {
|
||||
return {
|
||||
group_id: parseInt(peerId),
|
||||
folder_id: folder.folderId,
|
||||
folder: folder.folderId,
|
||||
folder_name: folder.folderName,
|
||||
create_time: folder.createTime,
|
||||
creator: parseInt(folder.createUin),
|
||||
|
19
src/onebot/event/notice/OB11ProfileLikeEvent.ts
Normal file
19
src/onebot/event/notice/OB11ProfileLikeEvent.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent';
|
||||
import { NapCatCore } from '@/core';
|
||||
|
||||
export class OB11ProfileLikeEvent extends OB11BaseNoticeEvent {
|
||||
notice_type = 'notify';
|
||||
sub_type = 'profile_like';
|
||||
operator_id: number;
|
||||
operator_nick: string;
|
||||
times: number;
|
||||
time: number;
|
||||
|
||||
constructor(core: NapCatCore, operatorId: number, operatorNick: string, times: number, time: number) {
|
||||
super(core);
|
||||
this.operator_id = operatorId;
|
||||
this.operator_nick = operatorNick;
|
||||
this.times = times;
|
||||
this.time = time;
|
||||
}
|
||||
}
|
@@ -43,7 +43,8 @@ import { OB11FriendRecallNoticeEvent } from '@/onebot/event/notice/OB11FriendRec
|
||||
import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent';
|
||||
import { LRUCache } from '@/common/lru-cache';
|
||||
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
|
||||
|
||||
import { OB11ProfileLikeEvent } from './event/notice/OB11ProfileLikeEvent';
|
||||
import { profileLikeTip, ProfileLikeTipType, SysMessage, SysMessageType } from '@/core/proto/ProfileLike';
|
||||
//OneBot实现类
|
||||
export class NapCatOneBot11Adapter {
|
||||
readonly core: NapCatCore;
|
||||
@@ -237,36 +238,11 @@ export class NapCatOneBot11Adapter {
|
||||
|
||||
private initMsgListener() {
|
||||
const msgListener = new NodeIKernelMsgListener();
|
||||
|
||||
/*
|
||||
msgListener.onRecvSysMsg = async () => {
|
||||
const sysMsg = SysMessage.fromBinary(Uint8Array.from(msg));
|
||||
if (sysMsg.msgSpec.length === 0) {
|
||||
return;
|
||||
}
|
||||
const { msgType, subType, subSubType } = sysMsg.msgSpec[0];
|
||||
if (msgType === 732 && subType === 16 && subSubType === 16) {
|
||||
const greyTip = GreyTipWrapper.fromBinary(Uint8Array.from(sysMsg.bodyWrapper!.wrappedBody.slice(7)));
|
||||
if (greyTip.subTypeId === 36) {
|
||||
const emojiLikeToOthers = EmojiLikeToOthersWrapper1
|
||||
.fromBinary(greyTip.rest)
|
||||
.wrapper!
|
||||
.body!;
|
||||
if (emojiLikeToOthers.attributes?.operation !== 1) { // Un-like
|
||||
return;
|
||||
}
|
||||
const eventOrEmpty = await this.apis.GroupApi.createGroupEmojiLikeEvent(
|
||||
greyTip.groupCode.toString(),
|
||||
await this.core.apis.UserApi.getUinByUidV2(emojiLikeToOthers.attributes!.senderUid),
|
||||
emojiLikeToOthers.msgSpec!.msgSeq.toString(),
|
||||
emojiLikeToOthers.attributes!.emojiId,
|
||||
);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty);
|
||||
}
|
||||
}
|
||||
msgListener.onRecvSysMsg = (msg) => {
|
||||
this.apis.MsgApi.parseSysMessage(msg).then((event) => {
|
||||
if (event) this.networkManager.emitEvent(event);
|
||||
}).catch(e => this.context.logger.logError('constructSysMessage error: ', e));
|
||||
};
|
||||
*/
|
||||
|
||||
msgListener.onInputStatusPush = async data => {
|
||||
const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin);
|
||||
|
@@ -21,6 +21,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
||||
core: NapCatCore;
|
||||
logger: LogWrapper;
|
||||
private heartbeatIntervalId: NodeJS.Timeout | null = null;
|
||||
wsClientWithEvent: WebSocket[] = [];
|
||||
|
||||
constructor(
|
||||
ip: string,
|
||||
@@ -46,7 +47,12 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
||||
}
|
||||
//鉴权
|
||||
this.authorize(token, wsClient, wsReq);
|
||||
this.connectEvent(core, wsClient);
|
||||
const paramUrl = wsReq.url?.indexOf('?') !== -1 ? wsReq.url?.substring(0, wsReq.url?.indexOf('?')) : wsReq.url;
|
||||
const isEventConnect = paramUrl === '/event' || paramUrl === '' || paramUrl === '/';
|
||||
if (isEventConnect) {
|
||||
this.connectEvent(core, wsClient);
|
||||
}
|
||||
|
||||
wsClient.on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Client Error:', err.message));
|
||||
wsClient.on('message', (message) => {
|
||||
this.handleMessage(wsClient, message).then().catch(this.logger.logError);
|
||||
@@ -59,13 +65,21 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
||||
});
|
||||
wsClient.once('close', () => {
|
||||
this.wsClientsMutex.runExclusive(async () => {
|
||||
const index = this.wsClients.indexOf(wsClient);
|
||||
if (index !== -1) {
|
||||
this.wsClients.splice(index, 1);
|
||||
const NormolIndex = this.wsClients.indexOf(wsClient);
|
||||
if (NormolIndex !== -1) {
|
||||
this.wsClients.splice(NormolIndex, 1);
|
||||
}
|
||||
const EventIndex = this.wsClientWithEvent.indexOf(wsClient);
|
||||
if (EventIndex !== -1) {
|
||||
this.wsClientWithEvent.splice(EventIndex, 1);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
await this.wsClientsMutex.runExclusive(async () => {
|
||||
if(isEventConnect){
|
||||
this.wsClientWithEvent.push(wsClient);
|
||||
}
|
||||
this.wsClients.push(wsClient);
|
||||
});
|
||||
}).on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Server Error:', err.message));
|
||||
@@ -81,7 +95,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
||||
|
||||
onEvent<T extends OB11EmitEventContent>(event: T) {
|
||||
this.wsClientsMutex.runExclusive(async () => {
|
||||
this.wsClients.forEach((wsClient) => {
|
||||
this.wsClientWithEvent.forEach((wsClient) => {
|
||||
wsClient.send(JSON.stringify(event));
|
||||
});
|
||||
});
|
||||
|
@@ -1,4 +1,5 @@
|
||||
export interface OB11User {
|
||||
[key: string]: any;
|
||||
user_id: number;
|
||||
nickname: string;
|
||||
remark?: string;
|
||||
@@ -81,6 +82,7 @@ export interface OB11GroupFile {
|
||||
export interface OB11GroupFileFolder {
|
||||
group_id: number,
|
||||
folder_id: string,
|
||||
folder: string,
|
||||
folder_name: string,
|
||||
create_time: number,
|
||||
creator: number,
|
||||
|
@@ -62,6 +62,7 @@ export enum OB11MessageDataType {
|
||||
dice = 'dice',
|
||||
RPS = 'rps',
|
||||
miniapp = 'miniapp',//json类
|
||||
contact = 'contact',
|
||||
Location = 'location'
|
||||
}
|
||||
|
||||
@@ -81,10 +82,15 @@ export interface OB11MessageText {
|
||||
text: string, // 纯文本
|
||||
}
|
||||
}
|
||||
|
||||
export interface OB11MessageContext {
|
||||
type: OB11MessageDataType.contact,
|
||||
data: {
|
||||
qq: string,
|
||||
}
|
||||
}
|
||||
export interface OB11MessageFileBase {
|
||||
data: {
|
||||
file_unique?:string,
|
||||
file_unique?: string,
|
||||
path?: string;
|
||||
thumb?: string;
|
||||
name?: string;
|
||||
@@ -198,7 +204,7 @@ export type OB11MessageData =
|
||||
OB11MessageAt | OB11MessageReply |
|
||||
OB11MessageImage | OB11MessageRecord | OB11MessageFile | OB11MessageVideo |
|
||||
OB11MessageNode | OB11MessageIdMusic | OB11MessageCustomMusic | OB11MessageJson |
|
||||
OB11MessageDice | OB11MessageRPS | OB11MessageMarkdown | OB11MessageForward
|
||||
OB11MessageDice | OB11MessageRPS | OB11MessageMarkdown | OB11MessageForward | OB11MessageContext
|
||||
|
||||
export interface OB11PostSendMsg {
|
||||
message_type?: 'private' | 'group'
|
||||
@@ -208,3 +214,8 @@ export interface OB11PostSendMsg {
|
||||
messages?: OB11MessageMixType; // 兼容 go-cqhttp
|
||||
auto_escape?: boolean | string
|
||||
}
|
||||
export interface OB11PostContext {
|
||||
message_type?: 'private' | 'group'
|
||||
user_id?: string,
|
||||
group_id?: string,
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
|
||||
SettingItem(
|
||||
'<span id="napcat-update-title">Napcat</span>',
|
||||
undefined,
|
||||
SettingButton('V2.4.2', 'napcat-update-button', 'secondary'),
|
||||
SettingButton('V2.5.3', 'napcat-update-button', 'secondary'),
|
||||
),
|
||||
]),
|
||||
SettingList([
|
||||
|
@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
|
||||
SettingItem(
|
||||
'<span id="napcat-update-title">Napcat</span>',
|
||||
void 0,
|
||||
SettingButton("V2.4.2", "napcat-update-button", "secondary")
|
||||
SettingButton("V2.5.3", "napcat-update-button", "secondary")
|
||||
)
|
||||
]),
|
||||
SettingList([
|
||||
|
Reference in New Issue
Block a user