mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
224 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f59248cc5a | ||
![]() |
8647c5c607 | ||
![]() |
6699ff38a1 | ||
![]() |
d79b98bd55 | ||
![]() |
5065a052fb | ||
![]() |
45603bb78c | ||
![]() |
40948995b4 | ||
![]() |
4ccdd8d1d3 | ||
![]() |
30d0174f47 | ||
![]() |
5a986ba25c | ||
![]() |
fe63c24ac3 | ||
![]() |
c384bd6875 | ||
![]() |
dcbff3f569 | ||
![]() |
7d91e05a69 | ||
![]() |
a5ce424a40 | ||
![]() |
47c36ca062 | ||
![]() |
c4c5b3bf8b | ||
![]() |
b1a81b0d12 | ||
![]() |
ad9fe64850 | ||
![]() |
f236349dc6 | ||
![]() |
5f56c8a7d4 | ||
![]() |
309d8a9f18 | ||
![]() |
2981799803 | ||
![]() |
00f8e1c0da | ||
![]() |
e9482e2ec4 | ||
![]() |
9bff327377 | ||
![]() |
ae009f98c1 | ||
![]() |
77505a6f5b | ||
![]() |
19c729aa23 | ||
![]() |
595888128a | ||
![]() |
51589d0eae | ||
![]() |
f1643ac549 | ||
![]() |
3f24461612 | ||
![]() |
b5deb198de | ||
![]() |
78452cf6a9 | ||
![]() |
4b4a784f56 | ||
![]() |
3e53cbcf8f | ||
![]() |
f34740f1f0 | ||
![]() |
b406bdfc37 | ||
![]() |
03c056702c | ||
![]() |
9c5f3f1946 | ||
![]() |
b50d7c24e7 | ||
![]() |
f05cf68945 | ||
![]() |
efc1875e35 | ||
![]() |
df063e6762 | ||
![]() |
e5c55b4339 | ||
![]() |
bee9095d6f | ||
![]() |
92f8eaaac9 | ||
![]() |
f5e7288fe5 | ||
![]() |
214aa7b6e4 | ||
![]() |
5b5d5b41f5 | ||
![]() |
23d613321e | ||
![]() |
0b6be0923f | ||
![]() |
aba748ea13 | ||
![]() |
f1f1ac582d | ||
![]() |
54a7cbc3f4 | ||
![]() |
2f4dbaec4c | ||
![]() |
578f518aaf | ||
![]() |
077ba74b22 | ||
![]() |
e0efe635c7 | ||
![]() |
1a06841de0 | ||
![]() |
3987e0ee0b | ||
![]() |
9f53bea02f | ||
![]() |
737709f9e7 | ||
![]() |
39477aa6a0 | ||
![]() |
f097050b56 | ||
![]() |
f14726ed1a | ||
![]() |
e1e4d038d9 | ||
![]() |
d2db4cf887 | ||
![]() |
2f3ece9ca3 | ||
![]() |
9f82007116 | ||
![]() |
f79198a472 | ||
![]() |
ce3d35d7ec | ||
![]() |
f4d40f0466 | ||
![]() |
a2fa085d5f | ||
![]() |
a598266a6e | ||
![]() |
f5fe33cee7 | ||
![]() |
200c7226ef | ||
![]() |
53475a6a0e | ||
![]() |
b4ec1ad6c0 | ||
![]() |
ef511a729d | ||
![]() |
275c4ce226 | ||
![]() |
45f9c029c8 | ||
![]() |
db5e4ad5d9 | ||
![]() |
f05d0a9727 | ||
![]() |
04593e9d9a | ||
![]() |
b1ecf13f8e | ||
![]() |
e91e054f20 | ||
![]() |
130ff7517e | ||
![]() |
c7042d9684 | ||
![]() |
5752e45dd1 | ||
![]() |
1a034ecb53 | ||
![]() |
025da8fb76 | ||
![]() |
2027da1db5 | ||
![]() |
7732f28ca8 | ||
![]() |
7f9da8cc2d | ||
![]() |
c6342b80a7 | ||
![]() |
f99c82de4b | ||
![]() |
56fa57ea02 | ||
![]() |
cc85985d08 | ||
![]() |
bd1751903e | ||
![]() |
03a298a70f | ||
![]() |
2722ca2b0e | ||
![]() |
179c4b800e | ||
![]() |
6bdf14223d | ||
![]() |
1b8252aa4f | ||
![]() |
8219889154 | ||
![]() |
df4ac5dcce | ||
![]() |
738eaf9de9 | ||
![]() |
c483ccbbbc | ||
![]() |
0d65f846ae | ||
![]() |
f47e75c423 | ||
![]() |
c008e58fb8 | ||
![]() |
26e0f17bc5 | ||
![]() |
6543f28bdb | ||
![]() |
a86851b338 | ||
![]() |
3a03e455c6 | ||
![]() |
3d39fd1580 | ||
![]() |
601b0add26 | ||
![]() |
4f974cc913 | ||
![]() |
f691320453 | ||
![]() |
be39fc3a21 | ||
![]() |
d2fafaf33a | ||
![]() |
27ae331352 | ||
![]() |
3f2dcfbacc | ||
![]() |
8565aee8b6 | ||
![]() |
f983add599 | ||
![]() |
030192afeb | ||
![]() |
c8b6a158f1 | ||
![]() |
e71f7849a7 | ||
![]() |
b64d1ff4ff | ||
![]() |
5a0028be26 | ||
![]() |
926d7deb43 | ||
![]() |
6384b50bae | ||
![]() |
9feb0f4b53 | ||
![]() |
43ec1b7cfd | ||
![]() |
05b7a59f8d | ||
![]() |
17e680f7af | ||
![]() |
035d256d4e | ||
![]() |
8939adf886 | ||
![]() |
027ffbffa6 | ||
![]() |
3cca06712b | ||
![]() |
2b9359dbf4 | ||
![]() |
c0f5d3bd2e | ||
![]() |
2a2d5382e1 | ||
![]() |
2e4986024c | ||
![]() |
8a9c605dae | ||
![]() |
44f51a93c8 | ||
![]() |
66c8537b41 | ||
![]() |
86ae6dd332 | ||
![]() |
69380c9c73 | ||
![]() |
3d3759137c | ||
![]() |
9b9b8f6f6f | ||
![]() |
8ff87a8245 | ||
![]() |
d1896da171 | ||
![]() |
0bc4f6fd96 | ||
![]() |
b16a429686 | ||
![]() |
fa1d266696 | ||
![]() |
d5dd2e9551 | ||
![]() |
be57c312c4 | ||
![]() |
f180687ba3 | ||
![]() |
3f3d9cc6f1 | ||
![]() |
4f98c0d045 | ||
![]() |
c254441d40 | ||
![]() |
17cbe74fa3 | ||
![]() |
7aa0bd9b79 | ||
![]() |
2553cf6b72 | ||
![]() |
fe9050aeda | ||
![]() |
7092894d22 | ||
![]() |
af6ac26664 | ||
![]() |
a22ef67486 | ||
![]() |
7bb57cd78a | ||
![]() |
89b69bbdf8 | ||
![]() |
e21c779d06 | ||
![]() |
dfa3553b71 | ||
![]() |
19097388d0 | ||
![]() |
a71eddbed2 | ||
![]() |
65bbed0c26 | ||
![]() |
871cc61dfc | ||
![]() |
bc62feb71b | ||
![]() |
0bba329999 | ||
![]() |
b1a1fdbeee | ||
![]() |
542c5beb1b | ||
![]() |
7b87b0919b | ||
![]() |
9c34f558d3 | ||
![]() |
3e2da3b490 | ||
![]() |
fb4a4f50be | ||
![]() |
6596e9cab6 | ||
![]() |
f1b137f2e1 | ||
![]() |
535720d0fe | ||
![]() |
f063cf4a16 | ||
![]() |
90bbdbf2fe | ||
![]() |
5f1d8fb99d | ||
![]() |
5486ffcdcc | ||
![]() |
adfd123970 | ||
![]() |
f1a364bfa2 | ||
![]() |
9da714bf15 | ||
![]() |
fc73295520 | ||
![]() |
ab955e41fb | ||
![]() |
c64367335c | ||
![]() |
edc787eb3e | ||
![]() |
f2c69fc68b | ||
![]() |
d947fe743b | ||
![]() |
5b37ae9026 | ||
![]() |
ec9e042b29 | ||
![]() |
337ac0eab9 | ||
![]() |
f6a1b784c4 | ||
![]() |
332fcecb78 | ||
![]() |
18590be1e7 | ||
![]() |
b76edcaf1d | ||
![]() |
96457bbec3 | ||
![]() |
a20a6bc8bb | ||
![]() |
f81b1926fb | ||
![]() |
670d4108e6 | ||
![]() |
a5c7b88a40 | ||
![]() |
e52b2e6d69 | ||
![]() |
e4066fb8df | ||
![]() |
f7a0fb22b4 | ||
![]() |
cad2ae723c | ||
![]() |
889a8c6093 | ||
![]() |
573418914f | ||
![]() |
d7fb6f9c05 | ||
![]() |
d5ff2d7099 | ||
![]() |
2a7f8d0c99 |
@@ -4,7 +4,7 @@ module.exports = {
|
|||||||
'es2021': true,
|
'es2021': true,
|
||||||
'node': true
|
'node': true
|
||||||
},
|
},
|
||||||
'ignorePatterns': ['src/proto/'],
|
'ignorePatterns': ['src/core/proto/'],
|
||||||
'extends': [
|
'extends': [
|
||||||
'eslint:recommended',
|
'eslint:recommended',
|
||||||
'plugin:@typescript-eslint/recommended'
|
'plugin:@typescript-eslint/recommended'
|
||||||
|
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@@ -1,15 +1,11 @@
|
|||||||
name: "Build Action"
|
name: "Build Action"
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Build-LiteLoader:
|
Build-LiteLoader:
|
||||||
if: ${{ startsWith(github.event.head_commit.message, 'build:') }}
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Clone Main Repository
|
- name: Clone Main Repository
|
||||||
@@ -37,7 +33,6 @@ jobs:
|
|||||||
name: NapCat.Framework
|
name: NapCat.Framework
|
||||||
path: dist
|
path: dist
|
||||||
Build-Shell:
|
Build-Shell:
|
||||||
if: ${{ startsWith(github.event.head_commit.message, 'build:') }}
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Clone Main Repository
|
- name: Clone Main Repository
|
||||||
@@ -63,4 +58,4 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: NapCat.Shell
|
name: NapCat.Shell
|
||||||
path: dist
|
path: dist
|
||||||
|
@@ -7,10 +7,12 @@
|
|||||||
NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现。
|
NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现。
|
||||||
|
|
||||||
## 猫猫技能
|
## 猫猫技能
|
||||||
|
- [x] **高性能**:1K+ 群聊数目、20 线程并行发送消息毫无压力
|
||||||
- [x] **多种启动方式**:支持以无头、LiteLoader 插件、仅 QQ GUI 三种方式启动
|
- [x] **多种启动方式**:支持以无头、LiteLoader 插件、仅 QQ GUI 三种方式启动
|
||||||
- [x] **低占用**:无头模式占用资源极低,适合在服务器上运行
|
- [x] **低占用**:无头模式占用资源极低,适合在服务器上运行
|
||||||
- [x] **超多接口**:在实现大部分Onebot接口上扩展了一套私有API
|
- [x] **超多接口**:实现大部分 OneBot 和 go-cqhttp 接口,超多扩展 API
|
||||||
- [x] **WebUI**:自带 WebUI 支持,远程管理更加便捷
|
- [x] **WebUI**:自带 WebUI 支持,远程管理更加便捷
|
||||||
|
- [x] **低故障率**:快速适配最新版本,日常保证 0 Issue
|
||||||
|
|
||||||
## 使用猫猫
|
## 使用猫猫
|
||||||
|
|
||||||
@@ -31,5 +33,7 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
|
|||||||
---
|
---
|
||||||
|
|
||||||
## 约法三章
|
## 约法三章
|
||||||
|
> [!CAUTION]\
|
||||||
|
> **请不要在 QQ 官方群聊和任何影响力较大的简中互联网平台(包括但不限于: 哔哩哔哩,微博,知乎,抖音等)发布和讨论*任何*与本项目存在相关性的信息**
|
||||||
|
|
||||||
任何使用本仓库代码的地方,都应当严格遵守[本仓库开源许可](./LICENSE)。**此外,禁止任何项目未经授权二次分发或基于 NapCat 代码开发。**
|
任何使用本仓库代码的地方,都应当严格遵守[本仓库开源许可](./LICENSE)。**此外,禁止任何项目未经授权二次分发或基于 NapCat 代码开发。**
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "2.2.8",
|
"version": "2.2.43",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.2.8",
|
"version": "2.2.43",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:framework": "vite build --mode framework",
|
"build:framework": "vite build --mode framework",
|
||||||
"build:shell": "vite build --mode shell",
|
"build:shell": "vite build --mode shell",
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
"@types/node": "^22.0.1",
|
"@types/node": "^22.0.1",
|
||||||
"@types/qrcode-terminal": "^0.12.2",
|
"@types/qrcode-terminal": "^0.12.2",
|
||||||
"@types/ws": "^8.5.12",
|
"@types/ws": "^8.5.12",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
"@typescript-eslint/eslint-plugin": "^8.3.0",
|
||||||
"@typescript-eslint/parser": "^7.4.0",
|
"@typescript-eslint/parser": "^8.3.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.1",
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
|
2
script/KillQQ.bat
Normal file
2
script/KillQQ.bat
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
@echo off
|
||||||
|
taskkill /f /im QQ.exe
|
Binary file not shown.
@@ -4,13 +4,13 @@ import type { NapCatCore } from '@/core';
|
|||||||
|
|
||||||
export abstract class ConfigBase<T> {
|
export abstract class ConfigBase<T> {
|
||||||
name: string;
|
name: string;
|
||||||
coreContext: NapCatCore;
|
core: NapCatCore;
|
||||||
configPath: string;
|
configPath: string;
|
||||||
configData: T = {} as T;
|
configData: T = {} as T;
|
||||||
|
|
||||||
protected constructor(name: string, coreContext: NapCatCore, configPath: string) {
|
protected constructor(name: string, core: NapCatCore, configPath: string) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.coreContext = coreContext;
|
this.core = core;
|
||||||
this.configPath = configPath;
|
this.configPath = configPath;
|
||||||
fs.mkdirSync(this.configPath, { recursive: true });
|
fs.mkdirSync(this.configPath, { recursive: true });
|
||||||
this.read();
|
this.read();
|
||||||
@@ -28,8 +28,8 @@ export abstract class ConfigBase<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
read(): T {
|
read(): T {
|
||||||
const logger = this.coreContext.context.logger;
|
const logger = this.core.context.logger;
|
||||||
const configPath = this.getConfigPath(this.coreContext.selfInfo.uin);
|
const configPath = this.getConfigPath(this.core.selfInfo.uin);
|
||||||
if (!fs.existsSync(configPath)) {
|
if (!fs.existsSync(configPath)) {
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
|
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
|
||||||
@@ -54,8 +54,8 @@ export abstract class ConfigBase<T> {
|
|||||||
|
|
||||||
|
|
||||||
save(newConfigData: T = this.configData) {
|
save(newConfigData: T = this.configData) {
|
||||||
const logger = this.coreContext.context.logger;
|
const logger = this.core.context.logger;
|
||||||
const selfInfo = this.coreContext.selfInfo;
|
const selfInfo = this.core.selfInfo;
|
||||||
this.configData = newConfigData;
|
this.configData = newConfigData;
|
||||||
const configPath = this.getConfigPath(selfInfo.uin);
|
const configPath = this.getConfigPath(selfInfo.uin);
|
||||||
try {
|
try {
|
@@ -1,4 +1,4 @@
|
|||||||
import type { NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core/wrapper/wrapper';
|
import type { NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core/wrapper';
|
||||||
import EventEmitter from 'node:events';
|
import EventEmitter from 'node:events';
|
||||||
|
|
||||||
export type ListenerClassBase = Record<string, string>;
|
export type ListenerClassBase = Record<string, string>;
|
||||||
@@ -6,9 +6,11 @@ export type ListenerClassBase = Record<string, string>;
|
|||||||
export interface ListenerIBase {
|
export interface ListenerIBase {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||||
new(listener: any): ListenerClassBase;
|
new(listener: any): ListenerClassBase;
|
||||||
|
|
||||||
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NTEventChannel extends EventEmitter {
|
export class NTEventWrapperV2 extends EventEmitter {
|
||||||
private wrapperApi: WrapperNodeApi;
|
private wrapperApi: WrapperNodeApi;
|
||||||
private wrapperSession: NodeIQQNTWrapperSession;
|
private wrapperSession: NodeIQQNTWrapperSession;
|
||||||
private listenerRefStorage = new Map<string, ListenerIBase>();
|
private listenerRefStorage = new Map<string, ListenerIBase>();
|
||||||
@@ -26,12 +28,11 @@ export class NTEventChannel extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createProxyDispatch(ListenerMainName: string) {
|
createProxyDispatch(ListenerMainName: string) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
const dispatcherListener = this.dispatcherListener.bind(this);
|
||||||
const current = this;
|
|
||||||
return new Proxy({}, {
|
return new Proxy({}, {
|
||||||
get(_target: any, prop: any, _receiver: any) {
|
get(_target: any, prop: any, _receiver: any) {
|
||||||
return (...args: any[]) => {
|
return (...args: any[]) => {
|
||||||
current.dispatcherListener.apply(current, [ListenerMainName + '/' + prop, ...args]);
|
dispatcherListener(ListenerMainName + '/' + prop, ...args);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -47,7 +48,7 @@ export class NTEventChannel extends EventEmitter {
|
|||||||
Listener = new ListenerType(this.createProxyDispatch(listenerMainName));
|
Listener = new ListenerType(this.createProxyDispatch(listenerMainName));
|
||||||
if (!Listener) throw new Error('Init Listener failed');
|
if (!Listener) throw new Error('Init Listener failed');
|
||||||
//实例化NTQQ Listener外包装
|
//实例化NTQQ Listener外包装
|
||||||
const ServiceSubName = listenerMainName.match(/^NodeIKernel(.*?)Listener$/)![1];
|
const ServiceSubName = /^NodeIKernel(.*?)Listener$/.exec(listenerMainName)![1];
|
||||||
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
|
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
|
||||||
const addfunc = this.createEventFunction<(listener: T) => number>(Service);
|
const addfunc = this.createEventFunction<(listener: T) => number>(Service);
|
||||||
//添加Listener到NTQQ
|
//添加Listener到NTQQ
|
||||||
@@ -122,10 +123,9 @@ export class NTEventChannel extends EventEmitter {
|
|||||||
|
|
||||||
async callEvent<EventType extends (...args: any[]) => Promise<any> | any>(
|
async callEvent<EventType extends (...args: any[]) => Promise<any> | any>(
|
||||||
EventName = '', timeout: number = 3000, ...args: Parameters<EventType>) {
|
EventName = '', timeout: number = 3000, ...args: Parameters<EventType>) {
|
||||||
return new Promise<Awaited<ReturnType<EventType>>>(async (resolve, reject) => {
|
return new Promise<Awaited<ReturnType<EventType>>>((resolve) => {
|
||||||
const EventFunc = this.createEventFunction<EventType>(EventName);
|
const EventFunc = this.createEventFunction<EventType>(EventName);
|
||||||
const retData = await EventFunc!(...args);
|
EventFunc!(...args).then((retData: Awaited<ReturnType<EventType>> | PromiseLike<Awaited<ReturnType<EventType>>>) => resolve(retData));
|
||||||
resolve(retData);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,5 +1,6 @@
|
|||||||
import { NodeIQQNTWrapperSession } from '@/core/wrapper/wrapper';
|
import { NodeIQQNTWrapperSession } from '@/core/wrapper';
|
||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
|
import { ListenerNamingMapping, ServiceNamingMapping } from '@/core';
|
||||||
|
|
||||||
interface InternalMapKey {
|
interface InternalMapKey {
|
||||||
timeout: number;
|
timeout: number;
|
||||||
@@ -10,18 +11,13 @@ interface InternalMapKey {
|
|||||||
|
|
||||||
export type ListenerClassBase = Record<string, string>;
|
export type ListenerClassBase = Record<string, string>;
|
||||||
|
|
||||||
export interface ListenerIBase {
|
export class NTEventWrapper {
|
||||||
new(listener: any): ListenerClassBase;
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LegacyNTEventWrapper {
|
|
||||||
private WrapperSession: NodeIQQNTWrapperSession | undefined; //WrapperSession
|
private WrapperSession: NodeIQQNTWrapperSession | undefined; //WrapperSession
|
||||||
private listenerManager: Map<string, ListenerClassBase> = new Map<string, ListenerClassBase>(); //ListenerName-Unique -> Listener实例
|
private listenerManager: Map<string, ListenerClassBase> = new Map<string, ListenerClassBase>(); //ListenerName-Unique -> Listener实例
|
||||||
private EventTask = new Map<string, Map<string, Map<string, InternalMapKey>>>(); //tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func}
|
private EventTask = new Map<string, Map<string, Map<string, InternalMapKey>>>(); //tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
wrapperSession: NodeIQQNTWrapperSession
|
wrapperSession: NodeIQQNTWrapperSession,
|
||||||
) {
|
) {
|
||||||
this.WrapperSession = wrapperSession;
|
this.WrapperSession = wrapperSession;
|
||||||
}
|
}
|
||||||
@@ -45,7 +41,13 @@ export class LegacyNTEventWrapper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
createEventFunction<T extends (...args: any) => any>(eventName: string): T | undefined {
|
createEventFunction<
|
||||||
|
Service extends keyof ServiceNamingMapping,
|
||||||
|
ServiceMethod extends Exclude<keyof ServiceNamingMapping[Service], symbol>,
|
||||||
|
// eslint-disable-next-line
|
||||||
|
// @ts-ignore
|
||||||
|
T extends (...args: any) => any = ServiceNamingMapping[Service][ServiceMethod],
|
||||||
|
>(eventName: `${Service}/${ServiceMethod}`): T | undefined {
|
||||||
const eventNameArr = eventName.split('/');
|
const eventNameArr = eventName.split('/');
|
||||||
type eventType = {
|
type eventType = {
|
||||||
[key: string]: () => { [key: string]: (...params: Parameters<T>) => Promise<ReturnType<T>> };
|
[key: string]: () => { [key: string]: (...params: Parameters<T>) => Promise<ReturnType<T>> };
|
||||||
@@ -68,10 +70,11 @@ export class LegacyNTEventWrapper {
|
|||||||
const existListener = this.listenerManager.get(listenerMainName + uniqueCode);
|
const existListener = this.listenerManager.get(listenerMainName + uniqueCode);
|
||||||
if (!existListener) {
|
if (!existListener) {
|
||||||
const Listener = this.createProxyDispatch(listenerMainName);
|
const Listener = this.createProxyDispatch(listenerMainName);
|
||||||
const ServiceSubName = listenerMainName.match(/^NodeIKernel(.*?)Listener$/)![1];
|
const ServiceSubName = /^NodeIKernel(.*?)Listener$/.exec(listenerMainName)![1];
|
||||||
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
|
const Service = `NodeIKernel${ServiceSubName}Service/addKernel${ServiceSubName}Listener`;
|
||||||
const addfunc = this.createEventFunction<(listener: T) => number>(Service);
|
// eslint-disable-next-line
|
||||||
addfunc!(Listener as T);
|
// @ts-ignore
|
||||||
|
this.createEventFunction(Service)(Listener as T);
|
||||||
this.listenerManager.set(listenerMainName + uniqueCode, Listener);
|
this.listenerManager.set(listenerMainName + uniqueCode, Listener);
|
||||||
return Listener as T;
|
return Listener as T;
|
||||||
}
|
}
|
||||||
@@ -93,47 +96,49 @@ export class LegacyNTEventWrapper {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async callNoListenerEvent<EventType extends (...args: any[]) => Promise<any> | any>(
|
async callNoListenerEvent<
|
||||||
EventName = '',
|
Service extends keyof ServiceNamingMapping,
|
||||||
timeout: number = 3000,
|
ServiceMethod extends Exclude<keyof ServiceNamingMapping[Service], symbol>,
|
||||||
|
// eslint-disable-next-line
|
||||||
|
// @ts-ignore
|
||||||
|
EventType extends (...args: any) => any = ServiceNamingMapping[Service][ServiceMethod],
|
||||||
|
>(
|
||||||
|
serviceAndMethod: `${Service}/${ServiceMethod}`,
|
||||||
...args: Parameters<EventType>
|
...args: Parameters<EventType>
|
||||||
) {
|
): Promise<Awaited<ReturnType<EventType>>> {
|
||||||
return new Promise<Awaited<ReturnType<EventType>>>(async (resolve, reject) => {
|
return (this.createEventFunction(serviceAndMethod))!(...args);
|
||||||
const EventFunc = this.createEventFunction<EventType>(EventName);
|
|
||||||
let complete = false;
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!complete) {
|
|
||||||
reject(new Error('NTEvent EventName:' + EventName + ' timeout'));
|
|
||||||
}
|
|
||||||
}, timeout);
|
|
||||||
const retData = await EventFunc!(...args);
|
|
||||||
complete = true;
|
|
||||||
resolve(retData);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async RegisterListen<ListenerType extends (...args: any[]) => void>(
|
async registerListen<
|
||||||
ListenerName = '',
|
Listener extends keyof ListenerNamingMapping,
|
||||||
|
ListenerMethod extends Exclude<keyof ListenerNamingMapping[Listener], symbol>,
|
||||||
|
// eslint-disable-next-line
|
||||||
|
// @ts-ignore
|
||||||
|
ListenerType extends (...args: any) => any = ListenerNamingMapping[Listener][ListenerMethod],
|
||||||
|
>(
|
||||||
|
listenerAndMethod: `${Listener}/${ListenerMethod}`,
|
||||||
waitTimes = 1,
|
waitTimes = 1,
|
||||||
timeout = 5000,
|
timeout = 5000,
|
||||||
checker: (...args: Parameters<ListenerType>) => boolean,
|
checker: (...args: Parameters<ListenerType>) => boolean,
|
||||||
) {
|
) {
|
||||||
return new Promise<Parameters<ListenerType>>((resolve, reject) => {
|
return new Promise<Parameters<ListenerType>>((resolve, reject) => {
|
||||||
const ListenerNameList = ListenerName.split('/');
|
const ListenerNameList = listenerAndMethod.split('/');
|
||||||
const ListenerMainName = ListenerNameList[0];
|
const ListenerMainName = ListenerNameList[0];
|
||||||
const ListenerSubName = ListenerNameList[1];
|
const ListenerSubName = ListenerNameList[1];
|
||||||
const id = randomUUID();
|
const id = randomUUID();
|
||||||
let complete = 0;
|
let complete = 0;
|
||||||
let retData: Parameters<ListenerType> | undefined = undefined;
|
let retData: Parameters<ListenerType> | undefined = undefined;
|
||||||
const databack = () => {
|
|
||||||
|
function sendDataCallback() {
|
||||||
if (complete == 0) {
|
if (complete == 0) {
|
||||||
reject(new Error(' ListenerName:' + ListenerName + ' timeout'));
|
reject(new Error(' ListenerName:' + listenerAndMethod + ' timeout'));
|
||||||
} else {
|
} else {
|
||||||
resolve(retData!);
|
resolve(retData!);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
const timeoutRef = setTimeout(databack, timeout);
|
|
||||||
const eventCallbak = {
|
const timeoutRef = setTimeout(sendDataCallback, timeout);
|
||||||
|
const eventCallback = {
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
createtime: Date.now(),
|
createtime: Date.now(),
|
||||||
checker: checker,
|
checker: checker,
|
||||||
@@ -142,7 +147,7 @@ export class LegacyNTEventWrapper {
|
|||||||
retData = args;
|
retData = args;
|
||||||
if (complete >= waitTimes) {
|
if (complete >= waitTimes) {
|
||||||
clearTimeout(timeoutRef);
|
clearTimeout(timeoutRef);
|
||||||
databack();
|
sendDataCallback();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -152,21 +157,30 @@ export class LegacyNTEventWrapper {
|
|||||||
if (!this.EventTask.get(ListenerMainName)?.get(ListenerSubName)) {
|
if (!this.EventTask.get(ListenerMainName)?.get(ListenerSubName)) {
|
||||||
this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map());
|
this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map());
|
||||||
}
|
}
|
||||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak);
|
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallback);
|
||||||
this.createListenerFunction(ListenerMainName);
|
this.createListenerFunction(ListenerMainName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async CallNormalEventV2<
|
|
||||||
EventType extends (...args: any[]) => Promise<any>,
|
async callNormalEventV2<
|
||||||
ListenerType extends (...args: any[]) => void
|
Service extends keyof ServiceNamingMapping,
|
||||||
|
ServiceMethod extends Exclude<keyof ServiceNamingMapping[Service], symbol>,
|
||||||
|
Listener extends keyof ListenerNamingMapping,
|
||||||
|
ListenerMethod extends Exclude<keyof ListenerNamingMapping[Listener], symbol>,
|
||||||
|
// eslint-disable-next-line
|
||||||
|
// @ts-ignore
|
||||||
|
EventType extends (...args: any) => any = ServiceNamingMapping[Service][ServiceMethod],
|
||||||
|
// eslint-disable-next-line
|
||||||
|
// @ts-ignore
|
||||||
|
ListenerType extends (...args: any) => any = ListenerNamingMapping[Listener][ListenerMethod]
|
||||||
>(
|
>(
|
||||||
EventName = '',
|
serviceAndMethod: `${Service}/${ServiceMethod}`,
|
||||||
ListenerName = '',
|
listenerAndMethod: `${Listener}/${ListenerMethod}`,
|
||||||
waitTimes = 1,
|
args: Parameters<EventType>,
|
||||||
timeout: number = 3000,
|
|
||||||
checkerEvent: (ret: Awaited<ReturnType<EventType>>) => boolean = () => true,
|
checkerEvent: (ret: Awaited<ReturnType<EventType>>) => boolean = () => true,
|
||||||
checkerListener: (...args: Parameters<ListenerType>) => boolean = () => true,
|
checkerListener: (...args: Parameters<ListenerType>) => boolean = () => true,
|
||||||
...args: Parameters<EventType>
|
callbackTimesToWait = 1,
|
||||||
|
timeout = 5000,
|
||||||
) {
|
) {
|
||||||
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(
|
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(
|
||||||
async (resolve, reject) => {
|
async (resolve, reject) => {
|
||||||
@@ -174,14 +188,15 @@ export class LegacyNTEventWrapper {
|
|||||||
let complete = 0;
|
let complete = 0;
|
||||||
let retData: Parameters<ListenerType> | undefined = undefined;
|
let retData: Parameters<ListenerType> | undefined = undefined;
|
||||||
let retEvent: any = {};
|
let retEvent: any = {};
|
||||||
const databack = () => {
|
|
||||||
|
function sendDataCallback() {
|
||||||
if (complete == 0) {
|
if (complete == 0) {
|
||||||
reject(
|
reject(
|
||||||
new Error(
|
new Error(
|
||||||
'Timeout: NTEvent EventName:' +
|
'Timeout: NTEvent serviceAndMethod:' +
|
||||||
EventName +
|
serviceAndMethod +
|
||||||
' ListenerName:' +
|
' ListenerName:' +
|
||||||
ListenerName +
|
listenerAndMethod +
|
||||||
' EventRet:\n' +
|
' EventRet:\n' +
|
||||||
JSON.stringify(retEvent, null, 4) +
|
JSON.stringify(retEvent, null, 4) +
|
||||||
'\n',
|
'\n',
|
||||||
@@ -190,24 +205,24 @@ export class LegacyNTEventWrapper {
|
|||||||
} else {
|
} else {
|
||||||
resolve([retEvent as Awaited<ReturnType<EventType>>, ...retData!]);
|
resolve([retEvent as Awaited<ReturnType<EventType>>, ...retData!]);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const ListenerNameList = ListenerName.split('/');
|
const ListenerNameList = listenerAndMethod.split('/');
|
||||||
const ListenerMainName = ListenerNameList[0];
|
const ListenerMainName = ListenerNameList[0];
|
||||||
const ListenerSubName = ListenerNameList[1];
|
const ListenerSubName = ListenerNameList[1];
|
||||||
|
|
||||||
const Timeouter = setTimeout(databack, timeout);
|
const timeoutRef = setTimeout(sendDataCallback, timeout);
|
||||||
|
|
||||||
const eventCallbak = {
|
const eventCallback = {
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
createtime: Date.now(),
|
createtime: Date.now(),
|
||||||
checker: checkerListener,
|
checker: checkerListener,
|
||||||
func: (...args: any[]) => {
|
func: (...args: any[]) => {
|
||||||
complete++;
|
complete++;
|
||||||
retData = args as Parameters<ListenerType>;
|
retData = args as Parameters<ListenerType>;
|
||||||
if (complete >= waitTimes) {
|
if (complete >= callbackTimesToWait) {
|
||||||
clearTimeout(Timeouter);
|
clearTimeout(timeoutRef);
|
||||||
databack();
|
sendDataCallback();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -217,18 +232,18 @@ export class LegacyNTEventWrapper {
|
|||||||
if (!this.EventTask.get(ListenerMainName)?.get(ListenerSubName)) {
|
if (!this.EventTask.get(ListenerMainName)?.get(ListenerSubName)) {
|
||||||
this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map());
|
this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map());
|
||||||
}
|
}
|
||||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak);
|
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallback);
|
||||||
this.createListenerFunction(ListenerMainName);
|
this.createListenerFunction(ListenerMainName);
|
||||||
const EventFunc = this.createEventFunction<EventType>(EventName);
|
const eventFunction = this.createEventFunction(serviceAndMethod);
|
||||||
retEvent = await EventFunc!(...(args as any[]));
|
retEvent = await eventFunction!(...(args));
|
||||||
if (!checkerEvent(retEvent)) {
|
if (!checkerEvent(retEvent)) {
|
||||||
clearTimeout(Timeouter);
|
clearTimeout(timeoutRef);
|
||||||
reject(
|
reject(
|
||||||
new Error(
|
new Error(
|
||||||
'EventChecker Failed: NTEvent EventName:' +
|
'EventChecker Failed: NTEvent serviceAndMethod:' +
|
||||||
EventName +
|
serviceAndMethod +
|
||||||
' ListenerName:' +
|
' ListenerName:' +
|
||||||
ListenerName +
|
listenerAndMethod +
|
||||||
' EventRet:\n' +
|
' EventRet:\n' +
|
||||||
JSON.stringify(retEvent, null, 4) +
|
JSON.stringify(retEvent, null, 4) +
|
||||||
'\n',
|
'\n',
|
||||||
@@ -238,12 +253,22 @@ export class LegacyNTEventWrapper {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
async CallNormalEvent<
|
|
||||||
EventType extends (...args: any[]) => Promise<any>,
|
/*
|
||||||
ListenerType extends (...args: any[]) => void
|
async callNormalEvent<
|
||||||
|
Service extends keyof ServiceNamingMapping,
|
||||||
|
ServiceMethod extends Exclude<keyof ServiceNamingMapping[Service], symbol>,
|
||||||
|
Listener extends keyof ListenerNamingMapping,
|
||||||
|
ListenerMethod extends Exclude<keyof ListenerNamingMapping[Listener], symbol>,
|
||||||
|
// eslint-disable-next-line
|
||||||
|
// @ts-ignore
|
||||||
|
EventType extends (...args: any) => any = ServiceNamingMapping[Service][ServiceMethod],
|
||||||
|
// eslint-disable-next-line
|
||||||
|
// @ts-ignore
|
||||||
|
ListenerType extends (...args: any) => any = ListenerNamingMapping[Listener][ListenerMethod]
|
||||||
>(
|
>(
|
||||||
EventName = '',
|
serviceAndMethod: `${Service}/${ServiceMethod}`,
|
||||||
ListenerName = '',
|
listenerAndMethod: `${Listener}/${ListenerMethod}`,
|
||||||
waitTimes = 1,
|
waitTimes = 1,
|
||||||
timeout: number = 3000,
|
timeout: number = 3000,
|
||||||
checker: (...args: Parameters<ListenerType>) => boolean,
|
checker: (...args: Parameters<ListenerType>) => boolean,
|
||||||
@@ -260,9 +285,9 @@ export class LegacyNTEventWrapper {
|
|||||||
reject(
|
reject(
|
||||||
new Error(
|
new Error(
|
||||||
'Timeout: NTEvent EventName:' +
|
'Timeout: NTEvent EventName:' +
|
||||||
EventName +
|
serviceAndMethod +
|
||||||
' ListenerName:' +
|
' ListenerName:' +
|
||||||
ListenerName +
|
listenerAndMethod +
|
||||||
' EventRet:\n' +
|
' EventRet:\n' +
|
||||||
JSON.stringify(retEvent, null, 4) +
|
JSON.stringify(retEvent, null, 4) +
|
||||||
'\n',
|
'\n',
|
||||||
@@ -273,7 +298,7 @@ export class LegacyNTEventWrapper {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const ListenerNameList = ListenerName.split('/');
|
const ListenerNameList = listenerAndMethod.split('/');
|
||||||
const ListenerMainName = ListenerNameList[0];
|
const ListenerMainName = ListenerNameList[0];
|
||||||
const ListenerSubName = ListenerNameList[1];
|
const ListenerSubName = ListenerNameList[1];
|
||||||
|
|
||||||
@@ -301,9 +326,10 @@ export class LegacyNTEventWrapper {
|
|||||||
}
|
}
|
||||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak);
|
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak);
|
||||||
this.createListenerFunction(ListenerMainName);
|
this.createListenerFunction(ListenerMainName);
|
||||||
const EventFunc = this.createEventFunction<EventType>(EventName);
|
const EventFunc = this.createEventFunction<EventType>(serviceAndMethod);
|
||||||
retEvent = await EventFunc!(...(args as any[]));
|
retEvent = await EventFunc!(...(args as any[]));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
@@ -4,7 +4,7 @@ import crypto, { randomUUID } from 'crypto';
|
|||||||
import util from 'util';
|
import util from 'util';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import * as fileType from 'file-type';
|
import * as fileType from 'file-type';
|
||||||
import { solveAsyncProblem, solveProblem } from './helper';
|
import { solveProblem } from './helper';
|
||||||
|
|
||||||
export function isGIF(path: string) {
|
export function isGIF(path: string) {
|
||||||
const buffer = Buffer.alloc(4);
|
const buffer = Buffer.alloc(4);
|
||||||
@@ -13,6 +13,7 @@ export function isGIF(path: string) {
|
|||||||
fs.closeSync(fd);
|
fs.closeSync(fd);
|
||||||
return buffer.toString() === 'GIF8';
|
return buffer.toString() === 'GIF8';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义一个异步函数来检查文件是否存在
|
// 定义一个异步函数来检查文件是否存在
|
||||||
export function checkFileReceived(path: string, timeout: number = 3000): Promise<void> {
|
export function checkFileReceived(path: string, timeout: number = 3000): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -123,15 +124,14 @@ export interface HttpDownloadOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function httpDownload(options: string | HttpDownloadOptions): Promise<Buffer> {
|
export async function httpDownload(options: string | HttpDownloadOptions): Promise<Buffer> {
|
||||||
const chunks: Buffer[] = [];
|
// const chunks: Buffer[] = [];
|
||||||
let url: string;
|
let url: string;
|
||||||
let headers: Record<string, 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',
|
'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',
|
||||||
};
|
};
|
||||||
if (typeof options === 'string') {
|
if (typeof options === 'string') {
|
||||||
url = options;
|
url = options;
|
||||||
const host = new URL(url).hostname;
|
headers['Host'] = new URL(url).hostname;
|
||||||
headers['Host'] = host;
|
|
||||||
} else {
|
} else {
|
||||||
url = options.url;
|
url = options.url;
|
||||||
if (options.headers) {
|
if (options.headers) {
|
||||||
@@ -194,7 +194,7 @@ export async function checkUriType(Uri: string) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}, Uri);
|
}, Uri);
|
||||||
if (LocalFileRet) return LocalFileRet;
|
if (LocalFileRet) return LocalFileRet;
|
||||||
|
|
||||||
const OtherFileRet = await solveProblem((uri: string) => {
|
const OtherFileRet = await solveProblem((uri: string) => {
|
||||||
//再判断是否是Http
|
//再判断是否是Http
|
||||||
if (uri.startsWith('http://') || uri.startsWith('https://')) {
|
if (uri.startsWith('http://') || uri.startsWith('https://')) {
|
||||||
@@ -217,7 +217,7 @@ export async function checkUriType(Uri: string) {
|
|||||||
}
|
}
|
||||||
}, Uri);
|
}, Uri);
|
||||||
if (OtherFileRet) return OtherFileRet;
|
if (OtherFileRet) return OtherFileRet;
|
||||||
|
|
||||||
return { Uri: Uri, Type: FileUriType.Unknown };
|
return { Uri: Uri, Type: FileUriType.Unknown };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,4 +269,4 @@ export async function uri2local(dir: string, uri: string, filename: string | und
|
|||||||
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: true };
|
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: true };
|
||||||
}
|
}
|
||||||
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
|
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
|
||||||
}
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import { QQLevel } from '@/core';
|
import { Peer, QQLevel } from '@/core';
|
||||||
|
|
||||||
export async function solveProblem<T extends (...arg: any[]) => any>(func: T, ...args: Parameters<T>): Promise<ReturnType<T> | undefined> {
|
export async function solveProblem<T extends (...arg: any[]) => any>(func: T, ...args: Parameters<T>): Promise<ReturnType<T> | undefined> {
|
||||||
return new Promise<ReturnType<T> | undefined>((resolve) => {
|
return new Promise<ReturnType<T> | undefined>((resolve) => {
|
||||||
@@ -15,35 +15,60 @@ export async function solveProblem<T extends (...arg: any[]) => any>(func: T, ..
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function solveAsyncProblem<T extends (...args: any[]) => Promise<any>>(func: T, ...args: Parameters<T>): Promise<Awaited<ReturnType<T>> | undefined> {
|
export async function solveAsyncProblem<T extends (...args: any[]) => Promise<any>>(func: T, ...args: Parameters<T>): Promise<Awaited<ReturnType<T>> | undefined> {
|
||||||
return new Promise<Awaited<ReturnType<T>> | undefined>(async (resolve) => {
|
return new Promise<Awaited<ReturnType<T>> | undefined>((resolve) => {
|
||||||
try {
|
func(...args).then((result) => {
|
||||||
const result = await func(...args);
|
|
||||||
resolve(result);
|
resolve(result);
|
||||||
} catch (e) {
|
}).catch(() => {
|
||||||
resolve(undefined);
|
resolve(undefined);
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//下面这个类是用于将uid+msgid合并的类
|
|
||||||
export class UUIDConverter {
|
export class FileNapCatOneBotUUID {
|
||||||
static encode(highStr: string, lowStr: string): string {
|
static encodeModelId(peer: Peer, modelId: string, fileId: string): string {
|
||||||
const high = BigInt(highStr);
|
return `NapCatOneBot|ModelIdFile|${peer.chatType}|${peer.peerUid}|${modelId}|${fileId}`;
|
||||||
const low = BigInt(lowStr);
|
|
||||||
const highHex = high.toString(16).padStart(16, '0');
|
|
||||||
const lowHex = low.toString(16).padStart(16, '0');
|
|
||||||
const combinedHex = highHex + lowHex;
|
|
||||||
const uuid = `${combinedHex.substring(0, 8)}-${combinedHex.substring(8, 12)}-${combinedHex.substring(
|
|
||||||
12,
|
|
||||||
16,
|
|
||||||
)}-${combinedHex.substring(16, 20)}-${combinedHex.substring(20)}`;
|
|
||||||
return uuid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static decode(uuid: string): { high: string; low: string } {
|
static decodeModelId(uuid: string): undefined | {
|
||||||
const hex = uuid.replace(/-/g, '');
|
peer: Peer,
|
||||||
const high = BigInt('0x' + hex.substring(0, 16));
|
modelId: string,
|
||||||
const low = BigInt('0x' + hex.substring(16));
|
fileId: string
|
||||||
return { high: high.toString(), low: low.toString() };
|
} {
|
||||||
|
if (!uuid.startsWith('NapCatOneBot|ModelIdFile|')) return undefined;
|
||||||
|
const data = uuid.split('|');
|
||||||
|
if (data.length !== 6) return undefined;
|
||||||
|
const [, , chatType, peerUid, modelId,fileId] = data;
|
||||||
|
return {
|
||||||
|
peer: {
|
||||||
|
chatType: chatType as any,
|
||||||
|
peerUid: peerUid,
|
||||||
|
},
|
||||||
|
modelId,
|
||||||
|
fileId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static encode(peer: Peer, msgId: string, elementId: string): string {
|
||||||
|
return `NapCatOneBot|MsgFile|${peer.chatType}|${peer.peerUid}|${msgId}|${elementId}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static decode(uuid: string): undefined | {
|
||||||
|
peer: Peer,
|
||||||
|
msgId: string,
|
||||||
|
elementId: string
|
||||||
|
} {
|
||||||
|
if (!uuid.startsWith('NapCatOneBot|MsgFile|')) return undefined;
|
||||||
|
const data = uuid.split('|');
|
||||||
|
if (data.length !== 6) return undefined;
|
||||||
|
const [, , chatType, peerUid, msgId, elementId] = data;
|
||||||
|
return {
|
||||||
|
peer: {
|
||||||
|
chatType: chatType as any,
|
||||||
|
peerUid: peerUid,
|
||||||
|
},
|
||||||
|
msgId,
|
||||||
|
elementId,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,19 +140,19 @@ export function isEqual(obj1: any, obj2: any) {
|
|||||||
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
||||||
if (os.platform() === 'linux') {
|
if (os.platform() === 'linux') {
|
||||||
return {
|
return {
|
||||||
baseVersion: '3.2.12-27254',
|
baseVersion: '3.2.12-27597',
|
||||||
curVersion: '3.2.12-27254',
|
curVersion: '3.2.12-27597',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '27254',
|
buildId: '27597',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
baseVersion: '9.9.15-27254',
|
baseVersion: '9.9.15-27597',
|
||||||
curVersion: '9.9.15-27254',
|
curVersion: '9.9.15-27597',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '27254',
|
buildId: '27597',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@@ -1,5 +1,5 @@
|
|||||||
import log4js, { Configuration } from 'log4js';
|
import log4js, { Configuration } from 'log4js';
|
||||||
import { truncateString } from '@/common/utils/helper';
|
import { truncateString } from '@/common/helper';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import { AtType, ChatType, ElementType, MessageElement, RawMessage, SelfInfo } from '@/core';
|
import { AtType, ChatType, ElementType, MessageElement, RawMessage, SelfInfo } from '@/core';
|
||||||
@@ -177,12 +177,12 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
|||||||
|
|
||||||
if (element.replyElement) {
|
if (element.replyElement) {
|
||||||
const recordMsgOrNull = msg.records.find(
|
const recordMsgOrNull = msg.records.find(
|
||||||
record => element.replyElement!.sourceMsgIdInRecords === record.msgId
|
record => element.replyElement!.sourceMsgIdInRecords === record.msgId,
|
||||||
);
|
);
|
||||||
return `[回复消息 ${
|
return `[回复消息 ${
|
||||||
recordMsgOrNull &&
|
recordMsgOrNull &&
|
||||||
recordMsgOrNull.peerUin != '284840486' // 非转发消息; 否则定位不到
|
recordMsgOrNull.peerUin != '284840486' // 非转发消息; 否则定位不到
|
||||||
?
|
?
|
||||||
rawMessageToText(recordMsgOrNull, recursiveLevel + 1) :
|
rawMessageToText(recordMsgOrNull, recursiveLevel + 1) :
|
||||||
`未找到消息记录 (MsgId = ${element.replyElement.sourceMsgIdInRecords})`
|
`未找到消息记录 (MsgId = ${element.replyElement.sourceMsgIdInRecords})`
|
||||||
}]`;
|
}]`;
|
@@ -15,23 +15,13 @@ export class LimitedHashTable<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set(key: K, value: V): void {
|
set(key: K, value: V): void {
|
||||||
// const isExist = this.keyToValue.get(key);
|
|
||||||
// if (isExist && isExist === value) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
this.keyToValue.set(key, value);
|
this.keyToValue.set(key, value);
|
||||||
this.valueToKey.set(value, key);
|
this.valueToKey.set(value, key);
|
||||||
while (this.keyToValue.size !== this.valueToKey.size) {
|
while (this.keyToValue.size !== this.valueToKey.size) {
|
||||||
//console.log('keyToValue.size !== valueToKey.size Error Atom');
|
|
||||||
this.keyToValue.clear();
|
this.keyToValue.clear();
|
||||||
this.valueToKey.clear();
|
this.valueToKey.clear();
|
||||||
}
|
}
|
||||||
// console.log('---------------');
|
|
||||||
// console.log(this.keyToValue);
|
|
||||||
// console.log(this.valueToKey);
|
|
||||||
// console.log('---------------');
|
|
||||||
while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) {
|
while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) {
|
||||||
//console.log(this.keyToValue.size > this.maxSize, this.valueToKey.size > this.maxSize);
|
|
||||||
const oldestKey = this.keyToValue.keys().next().value;
|
const oldestKey = this.keyToValue.keys().next().value;
|
||||||
this.valueToKey.delete(this.keyToValue.get(oldestKey)!);
|
this.valueToKey.delete(this.keyToValue.get(oldestKey)!);
|
||||||
this.keyToValue.delete(oldestKey);
|
this.keyToValue.delete(oldestKey);
|
||||||
@@ -101,17 +91,13 @@ class MessageUniqueWrapper {
|
|||||||
return ret.map((t) => t?.MsgId).filter((t) => t !== undefined);
|
return ret.map((t) => t?.MsgId).filter((t) => t !== undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
createMsg(peer: Peer, msgId: string): number | undefined {
|
createUniqueMsgId(peer: Peer, msgId: string) {
|
||||||
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
||||||
const hash = crypto.createHash('md5').update(key).digest();
|
const hash = crypto.createHash('md5').update(key).digest();
|
||||||
//设置第一个bit为0 保证shortId为正数
|
//设置第一个bit为0 保证shortId为正数
|
||||||
hash[0] &= 0x7f;
|
hash[0] &= 0x7f;
|
||||||
const shortId = hash.readInt32BE(0);
|
const shortId = hash.readInt32BE(0);
|
||||||
//减少性能损耗
|
//减少性能损耗
|
||||||
// const isExist = this.msgIdMap.getKey(shortId);
|
|
||||||
// if (isExist && isExist === msgId) {
|
|
||||||
// return shortId;
|
|
||||||
// }
|
|
||||||
this.msgIdMap.set(msgId, shortId);
|
this.msgIdMap.set(msgId, shortId);
|
||||||
this.msgDataMap.set(key, shortId);
|
this.msgDataMap.set(key, shortId);
|
||||||
return shortId;
|
return shortId;
|
@@ -2,8 +2,6 @@ import path, { dirname } from 'path';
|
|||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
export const napcat_version = '2.2.8';
|
|
||||||
|
|
||||||
export class NapCatPathWrapper {
|
export class NapCatPathWrapper {
|
||||||
binaryPath: string;
|
binaryPath: string;
|
||||||
logsPath: string;
|
logsPath: string;
|
@@ -1,6 +1,6 @@
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import { systemPlatform } from '@/common/utils/system';
|
import { systemPlatform } from '@/common/system';
|
||||||
import { getDefaultQQVersionConfigInfo, getQQVersionConfigPath } from './helper';
|
import { getDefaultQQVersionConfigInfo, getQQVersionConfigPath } from './helper';
|
||||||
import AppidTable from '@/core/external/appid.json';
|
import AppidTable from '@/core/external/appid.json';
|
||||||
import { LogWrapper } from './log';
|
import { LogWrapper } from './log';
|
||||||
@@ -60,20 +60,17 @@ export class QQBasicInfoWrapper {
|
|||||||
|
|
||||||
getAppidV2(): { appid: string; qua: string } {
|
getAppidV2(): { appid: string; qua: string } {
|
||||||
const appidTbale = AppidTable as unknown as QQAppidTableType;
|
const appidTbale = AppidTable as unknown as QQAppidTableType;
|
||||||
try {
|
const fullVersion = this.getFullQQVesion();
|
||||||
const fullVersion = this.getFullQQVesion();
|
if (fullVersion) {
|
||||||
if (!fullVersion) throw new Error('QQ版本获取失败');
|
|
||||||
const data = appidTbale[fullVersion];
|
const data = appidTbale[fullVersion];
|
||||||
if (data) {
|
if (data) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
this.context.logger.log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`);
|
|
||||||
}
|
}
|
||||||
// 以下是兜底措施
|
|
||||||
this.context.logger.log(
|
// else
|
||||||
`[QQ版本兼容性检测] ${this.getFullQQVesion()} 版本兼容性不佳,可能会导致一些功能无法正常使用`,
|
this.context.logger.log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`);
|
||||||
);
|
this.context.logger.log(`[QQ版本兼容性检测] ${fullVersion} 版本兼容性不佳,可能会导致一些功能无法正常使用`,);
|
||||||
return { appid: systemPlatform === 'linux' ? '537240795' : '537240709', qua: this.getQUAInternal() };
|
return { appid: systemPlatform === 'linux' ? '537243600' : '537243441', qua: this.getQUAInternal() };
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -30,7 +30,7 @@ export async function getMachineId(): Promise<string> {
|
|||||||
if (!machineId) {
|
if (!machineId) {
|
||||||
machineId = (async () => {
|
machineId = (async () => {
|
||||||
const id = await getMacMachineId();
|
const id = await getMacMachineId();
|
||||||
return id || randomUUID(); // fallback, generate a UUID
|
return id ?? randomUUID(); // fallback, generate a UUID
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
1
src/common/version.ts
Normal file
1
src/common/version.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const napCatVersion = '2.2.43';
|
63
src/common/video.ts
Normal file
63
src/common/video.ts
Normal file
File diff suppressed because one or more lines are too long
@@ -1,17 +1,4 @@
|
|||||||
interface IDependsAdapter {
|
export class NodeIDependsAdapter {
|
||||||
onMSFStatusChange(arg1: number, arg2: number): void;
|
|
||||||
|
|
||||||
onMSFSsoError(args: unknown): void;
|
|
||||||
|
|
||||||
getGroupCode(args: unknown): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIDependsAdapter extends IDependsAdapter {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IDependsAdapter): NodeIDependsAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DependsAdapter implements IDependsAdapter {
|
|
||||||
onMSFStatusChange(arg1: number, arg2: number) {
|
onMSFStatusChange(arg1: number, arg2: number) {
|
||||||
// console.log(arg1, arg2);
|
// console.log(arg1, arg2);
|
||||||
// if (arg1 == 2 && arg2 == 2) {
|
// if (arg1 == 2 && arg2 == 2) {
|
||||||
|
@@ -1,17 +1,4 @@
|
|||||||
interface IDispatcherAdapter {
|
export class NodeIDispatcherAdapter {
|
||||||
dispatchRequest(arg: unknown): void;
|
|
||||||
|
|
||||||
dispatchCall(arg: unknown): void;
|
|
||||||
|
|
||||||
dispatchCallWithJson(arg: unknown): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIDispatcherAdapter extends IDispatcherAdapter {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IDispatcherAdapter): NodeIDispatcherAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DispatcherAdapter implements IDispatcherAdapter {
|
|
||||||
dispatchRequest(arg: unknown) {
|
dispatchRequest(arg: unknown) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,27 +1,4 @@
|
|||||||
interface IGlobalAdapter {
|
export class NodeIGlobalAdapter {
|
||||||
onLog(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGetSrvCalTime(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onShowErrUITips(...args: unknown[]): void;
|
|
||||||
|
|
||||||
fixPicImgType(...args: unknown[]): void;
|
|
||||||
|
|
||||||
getAppSetting(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onInstallFinished(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onUpdateGeneralFlag(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGetOfflineMsg(...args: unknown[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIGlobalAdapter extends IGlobalAdapter {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IGlobalAdapter): NodeIGlobalAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GlobalAdapter implements IGlobalAdapter {
|
|
||||||
onLog(...args: unknown[]) {
|
onLog(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
63
src/core/apis/cache.ts
Normal file
63
src/core/apis/cache.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import {
|
||||||
|
CacheFileListItem,
|
||||||
|
CacheFileType,
|
||||||
|
ChatCacheListItemBasic,
|
||||||
|
ChatType,
|
||||||
|
InstanceContext,
|
||||||
|
NapCatCore,
|
||||||
|
} from '@/core';
|
||||||
|
|
||||||
|
export class NTQQCacheApi {
|
||||||
|
context: InstanceContext;
|
||||||
|
core: NapCatCore;
|
||||||
|
|
||||||
|
constructor(context: InstanceContext, core: NapCatCore) {
|
||||||
|
this.context = context;
|
||||||
|
this.core = core;
|
||||||
|
}
|
||||||
|
|
||||||
|
async setCacheSilentScan(isSilent: boolean = true) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
getCacheSessionPathList() {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
|
||||||
|
// 参数未验证
|
||||||
|
return this.context.session.getStorageCleanService().clearCacheDataByKeys(cacheKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
addCacheScannedPaths(pathMap: object = {}) {
|
||||||
|
return this.context.session.getStorageCleanService().addCacheScanedPaths(pathMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
scanCache() {
|
||||||
|
//return (await this.context.session.getStorageCleanService().scanCache()).size;
|
||||||
|
}
|
||||||
|
|
||||||
|
getHotUpdateCachePath() {
|
||||||
|
// 未实现
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
getDesktopTmpPath() {
|
||||||
|
// 未实现
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) {
|
||||||
|
return this.context.session.getStorageCleanService().getChatCacheInfo(type, pageSize, 1, pageIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
|
||||||
|
// const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
|
||||||
|
// 需要五个参数
|
||||||
|
// return napCatCore.session.getStorageCleanService().getFileCacheInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
|
||||||
|
return this.context.session.getStorageCleanService().clearChatCacheInfo(chats, fileKeys);
|
||||||
|
}
|
||||||
|
}
|
@@ -10,7 +10,7 @@ export class NTQQCollectionApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createCollection(authorUin: string, authorUid: string, authorName: string, brief: string, rawData: string) {
|
async createCollection(authorUin: string, authorUid: string, authorName: string, brief: string, rawData: string) {
|
||||||
const param = {
|
return this.context.session.getCollectionService().createNewCollectionItem({
|
||||||
commInfo: {
|
commInfo: {
|
||||||
bid: 1,
|
bid: 1,
|
||||||
category: 2,
|
category: 2,
|
||||||
@@ -43,12 +43,11 @@ export class NTQQCollectionApi {
|
|||||||
fileList: [],
|
fileList: [],
|
||||||
},
|
},
|
||||||
need_share_url: false,
|
need_share_url: false,
|
||||||
};
|
});
|
||||||
return this.context.session.getCollectionService().createNewCollectionItem(param);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllCollection(category: number = 0, count: number = 50) {
|
async getAllCollection(category: number = 0, count: number = 50) {
|
||||||
const param = {
|
return this.context.session.getCollectionService().getCollectionItemList({
|
||||||
category: category,
|
category: category,
|
||||||
groupId: -1,
|
groupId: -1,
|
||||||
forceSync: true,
|
forceSync: true,
|
||||||
@@ -56,7 +55,6 @@ export class NTQQCollectionApi {
|
|||||||
timeStamp: '0',
|
timeStamp: '0',
|
||||||
count: count,
|
count: count,
|
||||||
searchDown: true,
|
searchDown: true,
|
||||||
};
|
});
|
||||||
return this.context.session.getCollectionService().getCollectionItemList(param);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,25 +1,29 @@
|
|||||||
import {
|
import {
|
||||||
CacheFileListItem,
|
|
||||||
CacheFileType,
|
|
||||||
ChatCacheListItemBasic,
|
|
||||||
ChatType,
|
ChatType,
|
||||||
ElementType,
|
ElementType,
|
||||||
IMAGE_HTTP_HOST,
|
IMAGE_HTTP_HOST,
|
||||||
IMAGE_HTTP_HOST_NT,
|
IMAGE_HTTP_HOST_NT,
|
||||||
Peer,
|
Peer,
|
||||||
PicElement,
|
PicElement,
|
||||||
|
PicType,
|
||||||
|
SendFileElement,
|
||||||
|
SendPicElement,
|
||||||
|
SendPttElement,
|
||||||
|
SendVideoElement,
|
||||||
} from '@/core/entities';
|
} from '@/core/entities';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import fsPromises from 'fs/promises';
|
import fsPromises from 'fs/promises';
|
||||||
import { InstanceContext, NapCatCore, OnRichMediaDownloadCompleteParams } from '@/core';
|
import { InstanceContext, NapCatCore, SearchResultItem } from '@/core';
|
||||||
import * as fileType from 'file-type';
|
import * as fileType from 'file-type';
|
||||||
import imageSize from 'image-size';
|
import imageSize from 'image-size';
|
||||||
import { ISizeCalculationResult } from 'image-size/dist/types/interface';
|
import { ISizeCalculationResult } from 'image-size/dist/types/interface';
|
||||||
import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService';
|
|
||||||
import { RkeyManager } from '../helper/rkey';
|
import { RkeyManager } from '../helper/rkey';
|
||||||
import { calculateFileMD5 } from '@/common/utils/file';
|
import { calculateFileMD5, isGIF } from '@/common/file';
|
||||||
|
import pathLib from 'node:path';
|
||||||
|
import { defaultVideoThumbB64, getVideoInfo } from '@/common/video';
|
||||||
|
import ffmpeg from 'fluent-ffmpeg';
|
||||||
|
import { encodeSilk } from '@/common/audio';
|
||||||
|
|
||||||
export class NTQQFileApi {
|
export class NTQQFileApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
@@ -32,10 +36,6 @@ export class NTQQFileApi {
|
|||||||
this.rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey', this.context.logger);
|
this.rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey', this.context.logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFileType(filePath: string) {
|
|
||||||
return fileType.fileTypeFromFile(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
async copyFile(filePath: string, destPath: string) {
|
async copyFile(filePath: string, destPath: string) {
|
||||||
await this.core.util.copyFile(filePath, destPath);
|
await this.core.util.copyFile(filePath, destPath);
|
||||||
}
|
}
|
||||||
@@ -51,18 +51,15 @@ export class NTQQFileApi {
|
|||||||
})).urlResult.domainUrl;
|
})).urlResult.domainUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传文件到QQ的文件夹
|
|
||||||
async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) {
|
async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) {
|
||||||
// napCatCore.wrapper.util.
|
|
||||||
const fileMd5 = await calculateFileMD5(filePath);
|
const fileMd5 = await calculateFileMD5(filePath);
|
||||||
let ext: string = (await this.getFileType(filePath))?.ext as string || '';
|
const extOrEmpty = (await fileType.fileTypeFromFile(filePath))?.ext;
|
||||||
if (ext) {
|
const ext = extOrEmpty ? `.${extOrEmpty}` : '';
|
||||||
ext = '.' + ext;
|
|
||||||
}
|
|
||||||
let fileName = `${path.basename(filePath)}`;
|
let fileName = `${path.basename(filePath)}`;
|
||||||
if (fileName.indexOf('.') === -1) {
|
if (fileName.indexOf('.') === -1) {
|
||||||
fileName += ext;
|
fileName += ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mediaPath = this.context.session.getMsgService().getRichMediaFilePathForGuild({
|
const mediaPath = this.context.session.getMsgService().getRichMediaFilePathForGuild({
|
||||||
md5HexStr: fileMd5,
|
md5HexStr: fileMd5,
|
||||||
fileName: fileName,
|
fileName: fileName,
|
||||||
@@ -73,6 +70,7 @@ export class NTQQFileApi {
|
|||||||
downloadType: 1,
|
downloadType: 1,
|
||||||
file_uuid: '',
|
file_uuid: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.copyFile(filePath, mediaPath!);
|
await this.copyFile(filePath, mediaPath!);
|
||||||
const fileSize = await this.getFileSize(filePath);
|
const fileSize = await this.getFileSize(filePath);
|
||||||
return {
|
return {
|
||||||
@@ -84,8 +82,167 @@ export class NTQQFileApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadMediaByUuid() {
|
async createValidSendFileElement(filePath: string, fileName: string = '', folderId: string = '',): Promise<SendFileElement> {
|
||||||
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
|
const {
|
||||||
|
fileName: _fileName,
|
||||||
|
path,
|
||||||
|
fileSize,
|
||||||
|
} = await this.core.apis.FileApi.uploadFile(filePath, ElementType.FILE);
|
||||||
|
if (fileSize === 0) {
|
||||||
|
throw new Error('文件异常,大小为0');
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
elementType: ElementType.FILE,
|
||||||
|
elementId: '',
|
||||||
|
fileElement: {
|
||||||
|
fileName: fileName || _fileName,
|
||||||
|
folderId: folderId,
|
||||||
|
filePath: path,
|
||||||
|
fileSize: (fileSize).toString(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async createValidSendPicElement(picPath: string, summary: string = '', subType: 0 | 1 = 0,): Promise<SendPicElement> {
|
||||||
|
const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType);
|
||||||
|
if (fileSize === 0) {
|
||||||
|
throw new Error('文件异常,大小为0');
|
||||||
|
}
|
||||||
|
const imageSize = await this.core.apis.FileApi.getImageSize(picPath);
|
||||||
|
return {
|
||||||
|
elementType: ElementType.PIC,
|
||||||
|
elementId: '',
|
||||||
|
picElement: {
|
||||||
|
md5HexStr: md5,
|
||||||
|
fileSize: fileSize.toString(),
|
||||||
|
picWidth: imageSize.width,
|
||||||
|
picHeight: imageSize.height,
|
||||||
|
fileName: fileName,
|
||||||
|
sourcePath: path,
|
||||||
|
original: true,
|
||||||
|
picType: isGIF(picPath) ? PicType.gif : PicType.jpg,
|
||||||
|
picSubType: subType,
|
||||||
|
fileUuid: '',
|
||||||
|
fileSubId: '',
|
||||||
|
thumbFileSize: 0,
|
||||||
|
summary,
|
||||||
|
} as PicElement,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async createValidSendVideoElement(filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> {
|
||||||
|
const logger = this.core.context.logger;
|
||||||
|
const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
|
||||||
|
if (fileSize === 0) {
|
||||||
|
throw new Error('文件异常,大小为0');
|
||||||
|
}
|
||||||
|
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
|
||||||
|
thumb = pathLib.dirname(thumb);
|
||||||
|
let videoInfo = {
|
||||||
|
width: 1920, height: 1080,
|
||||||
|
time: 15,
|
||||||
|
format: 'mp4',
|
||||||
|
size: fileSize,
|
||||||
|
filePath,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
videoInfo = await getVideoInfo(path, logger);
|
||||||
|
} catch (e) {
|
||||||
|
logger.logError('获取视频信息失败,将使用默认值', e);
|
||||||
|
}
|
||||||
|
const thumbPath = new Map();
|
||||||
|
const _thumbPath = await new Promise<string | undefined>((resolve, reject) => {
|
||||||
|
const thumbFileName = `${md5}_0.png`;
|
||||||
|
const thumbPath = pathLib.join(thumb, thumbFileName);
|
||||||
|
ffmpeg(filePath)
|
||||||
|
.on('error', (err) => {
|
||||||
|
logger.logDebug('获取视频封面失败,使用默认封面', err);
|
||||||
|
if (diyThumbPath) {
|
||||||
|
fsPromises.copyFile(diyThumbPath, thumbPath).then(() => {
|
||||||
|
resolve(thumbPath);
|
||||||
|
}).catch(reject);
|
||||||
|
} else {
|
||||||
|
fs.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64'));
|
||||||
|
resolve(thumbPath);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.screenshots({
|
||||||
|
timestamps: [0],
|
||||||
|
filename: thumbFileName,
|
||||||
|
folder: thumb,
|
||||||
|
size: videoInfo.width + 'x' + videoInfo.height,
|
||||||
|
})
|
||||||
|
.on('end', () => {
|
||||||
|
resolve(thumbPath);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0;
|
||||||
|
thumbPath.set(0, _thumbPath);
|
||||||
|
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : '';
|
||||||
|
return {
|
||||||
|
elementType: ElementType.VIDEO,
|
||||||
|
elementId: '',
|
||||||
|
videoElement: {
|
||||||
|
fileName: fileName || _fileName,
|
||||||
|
filePath: path,
|
||||||
|
videoMd5: md5,
|
||||||
|
thumbMd5,
|
||||||
|
fileTime: videoInfo.time,
|
||||||
|
thumbPath: thumbPath,
|
||||||
|
thumbSize,
|
||||||
|
thumbWidth: videoInfo.width,
|
||||||
|
thumbHeight: videoInfo.height,
|
||||||
|
fileSize: '' + fileSize,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async createValidSendPttElement(pttPath: string): Promise<SendPttElement> {
|
||||||
|
const { converted, path: silkPath, duration } = await encodeSilk(pttPath, this.core.NapCatTempPath, this.core.context.logger);
|
||||||
|
if (!silkPath) {
|
||||||
|
throw new Error('语音转换失败, 请检查语音文件是否正常');
|
||||||
|
}
|
||||||
|
const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(silkPath, ElementType.PTT);
|
||||||
|
if (fileSize === 0) {
|
||||||
|
throw new Error('文件异常,大小为0');
|
||||||
|
}
|
||||||
|
if (converted) {
|
||||||
|
fsPromises.unlink(silkPath);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
elementType: ElementType.PTT,
|
||||||
|
elementId: '',
|
||||||
|
pttElement: {
|
||||||
|
fileName: fileName,
|
||||||
|
filePath: path,
|
||||||
|
md5HexStr: md5,
|
||||||
|
fileSize: fileSize,
|
||||||
|
duration: duration ?? 1,
|
||||||
|
formatType: 1,
|
||||||
|
voiceType: 1,
|
||||||
|
voiceChangeType: 0,
|
||||||
|
canConvert2Text: true,
|
||||||
|
waveAmplitudes: [
|
||||||
|
0, 18, 9, 23, 16, 17, 16, 15, 44, 17, 24, 20, 14, 15, 17,
|
||||||
|
],
|
||||||
|
fileSubId: '',
|
||||||
|
playState: 1,
|
||||||
|
autoConvertText: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async downloadFileForModelId(peer: Peer, modelId: string, unknown: string, timeout = 1000 * 60 * 2) {
|
||||||
|
const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
|
'NodeIKernelRichMediaService/downloadFileForModelId',
|
||||||
|
'NodeIKernelMsgListener/onRichMediaDownloadComplete',
|
||||||
|
[peer, [modelId], unknown],
|
||||||
|
() => true,
|
||||||
|
(arg) => arg?.commonFileInfo?.fileModelId === modelId,
|
||||||
|
1,
|
||||||
|
timeout,
|
||||||
|
);
|
||||||
|
return fileTransNotifyInfo.filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
||||||
@@ -102,75 +259,40 @@ export class NTQQFileApi {
|
|||||||
return sourcePath;
|
return sourcePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const data = await this.core.eventWrapper.CallNormalEvent<
|
const [, completeRetData] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
(
|
'NodeIKernelMsgService/downloadRichMedia',
|
||||||
params: {
|
'NodeIKernelMsgListener/onRichMediaDownloadComplete',
|
||||||
fileModelId: string,
|
[{
|
||||||
downloadSourceType: number,
|
fileModelId: '0',
|
||||||
triggerType: number,
|
downloadSourceType: 0,
|
||||||
msgId: string,
|
triggerType: 1,
|
||||||
chatType: ChatType,
|
msgId: msgId,
|
||||||
peerUid: string,
|
chatType: chatType,
|
||||||
elementId: string,
|
peerUid: peerUid,
|
||||||
thumbSize: number,
|
elementId: elementId,
|
||||||
downloadType: number,
|
thumbSize: 0,
|
||||||
filePath: string
|
downloadType: 1,
|
||||||
}) => Promise<unknown>,
|
filePath: thumbPath,
|
||||||
(fileTransNotifyInfo: OnRichMediaDownloadCompleteParams) => void
|
}],
|
||||||
>(
|
() => true,
|
||||||
'NodeIKernelMsgService/downloadRichMedia',
|
(arg) => arg.msgId === msgId,
|
||||||
'NodeIKernelMsgListener/onRichMediaDownloadComplete',
|
1,
|
||||||
1,
|
timeout,
|
||||||
timeout,
|
);
|
||||||
(arg: OnRichMediaDownloadCompleteParams) => {
|
return completeRetData.filePath;
|
||||||
if (arg.msgId === msgId) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fileModelId: '0',
|
|
||||||
downloadSourceType: 0,
|
|
||||||
triggerType: 1,
|
|
||||||
msgId: msgId,
|
|
||||||
chatType: chatType,
|
|
||||||
peerUid: peerUid,
|
|
||||||
elementId: elementId,
|
|
||||||
thumbSize: 0,
|
|
||||||
downloadType: 1,
|
|
||||||
filePath: thumbPath,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const msg = await this.core.apis.MsgApi.getMsgsByMsgId({
|
|
||||||
guildId: '',
|
|
||||||
chatType: chatType,
|
|
||||||
peerUid: peerUid,
|
|
||||||
}, [msgId]);
|
|
||||||
if (msg.msgList.length === 0) {
|
|
||||||
return data[1].filePath;
|
|
||||||
}
|
|
||||||
//获取原始消息
|
|
||||||
const FileElements = msg?.msgList[0]?.elements?.find(e => e.elementId === elementId);
|
|
||||||
if (!FileElements) {
|
|
||||||
//失败则就乱来 Todo
|
|
||||||
return data[1].filePath;
|
|
||||||
}
|
|
||||||
//从原始消息获取文件路径
|
|
||||||
const filePath =
|
|
||||||
FileElements?.fileElement?.filePath ||
|
|
||||||
FileElements?.pttElement?.filePath ||
|
|
||||||
FileElements?.videoElement?.filePath ||
|
|
||||||
FileElements?.picElement?.sourcePath;
|
|
||||||
return filePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getImageSize(filePath: string): Promise<ISizeCalculationResult | undefined> {
|
async getImageSize(filePath: string): Promise<ISizeCalculationResult> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
imageSize(filePath, (err, dimensions) => {
|
imageSize(filePath, (err, dimensions) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
resolve(dimensions);
|
if (!dimensions) {
|
||||||
|
reject(new Error('获取图片尺寸失败'));
|
||||||
|
} else {
|
||||||
|
resolve(dimensions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -235,59 +357,41 @@ export class NTQQFileApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchfile(keys: string[]) {
|
async searchForFile(keys: string[]): Promise<SearchResultItem | undefined> {
|
||||||
type EventType = NodeIKernelSearchService['searchFileWithKeywords'];
|
const randomResultId = 100000 + Math.floor(Math.random() * 10000);
|
||||||
|
let searchId = 0;
|
||||||
|
const [, searchResult] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
|
'NodeIKernelFileAssistantService/searchFile',
|
||||||
|
'NodeIKernelFileAssistantListener/onFileSearch',
|
||||||
|
[
|
||||||
|
keys,
|
||||||
|
{ resultType: 2, pageLimit: 1 },
|
||||||
|
randomResultId,
|
||||||
|
],
|
||||||
|
(ret) => {
|
||||||
|
searchId = ret;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
result => result.searchId === searchId && result.resultId === randomResultId,
|
||||||
|
);
|
||||||
|
return searchResult.resultItems[0];
|
||||||
|
}
|
||||||
|
|
||||||
interface OnListener {
|
async downloadFileById(
|
||||||
searchId: string,
|
fileId: string,
|
||||||
hasMore: boolean,
|
fileSize: number = 1024576,
|
||||||
resultItems: {
|
estimatedTime: number = (fileSize * 1000 / 1024576) + 5000,
|
||||||
chatType: ChatType,
|
) {
|
||||||
buddyChatInfo: any[],
|
const [, fileData] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
discussChatInfo: any[],
|
'NodeIKernelFileAssistantService/downloadFile',
|
||||||
groupChatInfo:
|
'NodeIKernelFileAssistantListener/onFileStatusChanged',
|
||||||
{
|
[[fileId]],
|
||||||
groupCode: string,
|
ret => ret.result === 0,
|
||||||
isConf: boolean,
|
status => status.fileStatus === 2 && status.fileProgress === '0',
|
||||||
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
|
|
||||||
}[]
|
|
||||||
}[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const Event = this.core.eventWrapper.createEventFunction<EventType>('NodeIKernelSearchService/searchFileWithKeywords');
|
|
||||||
let id = '';
|
|
||||||
const Listener = this.core.eventWrapper.RegisterListen<(params: OnListener) => void>
|
|
||||||
(
|
|
||||||
'NodeIKernelSearchListener/onSearchFileKeywordsResult',
|
|
||||||
1,
|
1,
|
||||||
20000,
|
estimatedTime, // estimate 1MB/s
|
||||||
(params) => id !== '' && params.searchId == id,
|
);
|
||||||
);
|
return fileData.filePath!;
|
||||||
id = await Event!(keys, 12);
|
|
||||||
const [ret] = (await Listener);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getImageUrl(element: PicElement) {
|
async getImageUrl(element: PicElement) {
|
||||||
@@ -297,84 +401,29 @@ export class NTQQFileApi {
|
|||||||
const url: string = element.originImageUrl!; // 没有域名
|
const url: string = element.originImageUrl!; // 没有域名
|
||||||
const md5HexStr = element.md5HexStr;
|
const md5HexStr = element.md5HexStr;
|
||||||
const fileMd5 = element.md5HexStr;
|
const fileMd5 = element.md5HexStr;
|
||||||
const fileUuid = element.fileUuid;
|
|
||||||
|
|
||||||
if (url) {
|
if (url) {
|
||||||
const UrlParse = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接
|
const parsedUrl = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接
|
||||||
const imageAppid = UrlParse.searchParams.get('appid');
|
const imageAppid = parsedUrl.searchParams.get('appid');
|
||||||
const isNewPic = imageAppid && ['1406', '1407'].includes(imageAppid);
|
const isNTFlavoredPic = imageAppid && ['1406', '1407'].includes(imageAppid);
|
||||||
if (isNewPic) {
|
if (isNTFlavoredPic) {
|
||||||
let UrlRkey = UrlParse.searchParams.get('rkey');
|
let rkey = parsedUrl.searchParams.get('rkey');
|
||||||
if (UrlRkey) {
|
if (rkey) {
|
||||||
return IMAGE_HTTP_HOST_NT + url;
|
return IMAGE_HTTP_HOST_NT + url;
|
||||||
}
|
}
|
||||||
const rkeyData = await this.rkeyManager.getRkey();
|
const rkeyData = await this.rkeyManager.getRkey();
|
||||||
UrlRkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
|
rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
|
||||||
return IMAGE_HTTP_HOST_NT + url + `${UrlRkey}`;
|
return IMAGE_HTTP_HOST_NT + url + `${rkey}`;
|
||||||
} else {
|
} else {
|
||||||
// 老的图片url,不需要rkey
|
// 老的图片url,不需要rkey
|
||||||
return IMAGE_HTTP_HOST + url;
|
return IMAGE_HTTP_HOST + url;
|
||||||
}
|
}
|
||||||
} else if (fileMd5 || md5HexStr) {
|
} else if (fileMd5 || md5HexStr) {
|
||||||
// 没有url,需要自己拼接
|
// 没有url,需要自己拼接
|
||||||
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 || md5HexStr)!.toUpperCase()}/0`;
|
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`;
|
||||||
}
|
}
|
||||||
this.context.logger.logDebug('图片url获取失败', element);
|
this.context.logger.logDebug('图片url获取失败', element);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NTQQFileCacheApi {
|
|
||||||
context: InstanceContext;
|
|
||||||
core: NapCatCore;
|
|
||||||
|
|
||||||
constructor(context: InstanceContext, core: NapCatCore) {
|
|
||||||
this.context = context;
|
|
||||||
this.core = core;
|
|
||||||
}
|
|
||||||
|
|
||||||
async setCacheSilentScan(isSilent: boolean = true) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
getCacheSessionPathList() {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
|
|
||||||
// 参数未验证
|
|
||||||
return this.context.session.getStorageCleanService().clearCacheDataByKeys(cacheKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
addCacheScannedPaths(pathMap: object = {}) {
|
|
||||||
return this.context.session.getStorageCleanService().addCacheScanedPaths(pathMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
scanCache() {
|
|
||||||
//return (await this.context.session.getStorageCleanService().scanCache()).size;
|
|
||||||
}
|
|
||||||
|
|
||||||
getHotUpdateCachePath() {
|
|
||||||
// 未实现
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
getDesktopTmpPath() {
|
|
||||||
// 未实现
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) {
|
|
||||||
return this.context.session.getStorageCleanService().getChatCacheInfo(type, pageSize, 1, pageIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
|
|
||||||
const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
|
|
||||||
//需要五个参数
|
|
||||||
//return napCatCore.session.getStorageCleanService().getFileCacheInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
|
|
||||||
return this.context.session.getStorageCleanService().clearChatCacheInfo(chats, fileKeys);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
import { Friend, FriendV2, User } from '@/core/entities';
|
import { FriendV2 } from '@/core/entities';
|
||||||
import { BuddyListReqType, InstanceContext, NapCatCore, NodeIKernelBuddyListener, NodeIKernelBuddyService, NodeIKernelProfileService, OnBuddyChangeParams } from '@/core';
|
import { BuddyListReqType, InstanceContext, NapCatCore } from '@/core';
|
||||||
import { LimitedHashTable } from '@/common/utils/MessageUnique';
|
import { LimitedHashTable } from '@/common/message-unique';
|
||||||
|
|
||||||
export class NTQQFriendApi {
|
export class NTQQFriendApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
core: NapCatCore;
|
core: NapCatCore;
|
||||||
//friends: Map<string, Friend> = new Map<string, FriendV2>();
|
|
||||||
|
// friends: Map<string, Friend> = new Map<string, FriendV2>();
|
||||||
|
|
||||||
constructor(context: InstanceContext, core: NapCatCore) {
|
constructor(context: InstanceContext, core: NapCatCore) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@@ -15,47 +16,42 @@ export class NTQQFriendApi {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBuddyV2(refresh = false): Promise<FriendV2[]> {
|
async getBuddyV2SimpleInfoMap(refresh = false) {
|
||||||
const uids: string[] = [];
|
|
||||||
const buddyService = this.context.session.getBuddyService();
|
const buddyService = this.context.session.getBuddyService();
|
||||||
const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
|
const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
|
||||||
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids));
|
const uids = buddyListV2.data.flatMap(item => item.buddyUids);
|
||||||
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
return await this.core.eventWrapper.callNoListenerEvent(
|
||||||
'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids,
|
'NodeIKernelProfileService/getCoreAndBaseInfo',
|
||||||
|
'nodeStore',
|
||||||
|
uids,
|
||||||
);
|
);
|
||||||
return Array.from(data.values());
|
}
|
||||||
|
|
||||||
|
async getBuddyV2(refresh = false): Promise<FriendV2[]> {
|
||||||
|
return Array.from((await this.getBuddyV2SimpleInfoMap(refresh)).values());
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBuddyIdMap(refresh = false): Promise<LimitedHashTable<string, string>> {
|
async getBuddyIdMap(refresh = false): Promise<LimitedHashTable<string, string>> {
|
||||||
const uids: string[] = [];
|
|
||||||
const retMap: LimitedHashTable<string, string> = new LimitedHashTable<string, string>(5000);
|
const retMap: LimitedHashTable<string, string> = new LimitedHashTable<string, string>(5000);
|
||||||
const buddyService = this.context.session.getBuddyService();
|
const data = await this.getBuddyV2SimpleInfoMap(refresh);
|
||||||
const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
|
data.forEach((value) => retMap.set(value.uin!, value.uid!));
|
||||||
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids));
|
|
||||||
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
|
||||||
'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids,
|
|
||||||
);
|
|
||||||
data.forEach((value, key) => {
|
|
||||||
retMap.set(value.uin!, value.uid!);
|
|
||||||
});
|
|
||||||
//console.log('getBuddyIdMap', retMap.getValue);
|
|
||||||
return retMap;
|
return retMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBuddyV2ExWithCate(refresh = false) {
|
async getBuddyV2ExWithCate(refresh = false) {
|
||||||
const uids: string[] = [];
|
|
||||||
const categoryMap: Map<string, any> = new Map();
|
const categoryMap: Map<string, any> = new Map();
|
||||||
const buddyService = this.context.session.getBuddyService();
|
const buddyService = this.context.session.getBuddyService();
|
||||||
const buddyListV2 = refresh ? (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data : (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data;
|
const buddyListV2 = refresh ? (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data : (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data;
|
||||||
uids.push(
|
const uids = buddyListV2.flatMap(item => {
|
||||||
...buddyListV2.flatMap(item => {
|
item.buddyUids.forEach(uid => {
|
||||||
item.buddyUids.forEach(uid => {
|
categoryMap.set(uid, { categoryId: item.categoryId, categoryName: item.categroyName });
|
||||||
categoryMap.set(uid, { categoryId: item.categoryId, categoryName: item.categroyName });
|
});
|
||||||
});
|
return item.buddyUids;
|
||||||
return item.buddyUids;
|
});
|
||||||
}));
|
const data = await this.core.eventWrapper.callNoListenerEvent(
|
||||||
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
|
'NodeIKernelProfileService/getCoreAndBaseInfo',
|
||||||
'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids,
|
'nodeStore',
|
||||||
|
uids,
|
||||||
);
|
);
|
||||||
return buddyListV2.map(category => ({
|
return buddyListV2.map(category => ({
|
||||||
categoryId: category.categoryId,
|
categoryId: category.categoryId,
|
||||||
@@ -70,18 +66,17 @@ export class NTQQFriendApi {
|
|||||||
async isBuddy(uid: string) {
|
async isBuddy(uid: string) {
|
||||||
return this.context.session.getBuddyService().isBuddy(uid);
|
return this.context.session.getBuddyService().isBuddy(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearBuddyReqUnreadCnt() {
|
async clearBuddyReqUnreadCnt() {
|
||||||
return this.context.session.getBuddyService().clearBuddyReqUnreadCnt();
|
return this.context.session.getBuddyService().clearBuddyReqUnreadCnt();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBuddyReq() {
|
async getBuddyReq() {
|
||||||
const [, ret] = await this.core.eventWrapper.CallNormalEventV2<
|
const [, ret] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
NodeIKernelBuddyService['getBuddyReq'],
|
|
||||||
NodeIKernelBuddyListener['onBuddyReqChange']
|
|
||||||
>(
|
|
||||||
'NodeIKernelBuddyService/getBuddyReq',
|
'NodeIKernelBuddyService/getBuddyReq',
|
||||||
'NodeIKernelBuddyListener/onBuddyReqChange',
|
'NodeIKernelBuddyListener/onBuddyReqChange',
|
||||||
1,
|
[],
|
||||||
5000);
|
);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,17 +4,14 @@ import {
|
|||||||
Group,
|
Group,
|
||||||
GroupMember,
|
GroupMember,
|
||||||
GroupMemberRole,
|
GroupMemberRole,
|
||||||
GroupNotify,
|
|
||||||
GroupRequestOperateTypes,
|
GroupRequestOperateTypes,
|
||||||
InstanceContext,
|
InstanceContext,
|
||||||
KickMemberInfo,
|
KickMemberV2Req,
|
||||||
kickMemberV2Req,
|
|
||||||
MemberExtSourceType,
|
MemberExtSourceType,
|
||||||
NapCatCore,
|
NapCatCore,
|
||||||
NodeIKernelGroupListener,
|
|
||||||
NodeIKernelGroupService,
|
|
||||||
} from '@/core';
|
} from '@/core';
|
||||||
import { isNumeric, runAllWithTimeout, sleep } from '@/common/utils/helper';
|
import { isNumeric, runAllWithTimeout } from '@/common/helper';
|
||||||
|
import { LimitedHashTable } from '@/common/message-unique';
|
||||||
|
|
||||||
export class NTQQGroupApi {
|
export class NTQQGroupApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
@@ -22,40 +19,90 @@ export class NTQQGroupApi {
|
|||||||
groupCache: Map<string, Group> = new Map<string, Group>();
|
groupCache: Map<string, Group> = new Map<string, Group>();
|
||||||
groupMemberCache: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
|
groupMemberCache: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
|
||||||
groups: Group[] = [];
|
groups: Group[] = [];
|
||||||
|
essenceLRU = new LimitedHashTable<number, string>(1000);
|
||||||
|
|
||||||
constructor(context: InstanceContext, core: NapCatCore) {
|
constructor(context: InstanceContext, core: NapCatCore) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.core = core;
|
this.core = core;
|
||||||
sleep(1000).then(() => {
|
this.initCache().then().catch(context.logger.logError);
|
||||||
this.initCache().then().catch(context.logger.logError);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async initCache() {
|
async initCache() {
|
||||||
this.groups = await this.getGroups();
|
this.groups = await this.getGroups();
|
||||||
for (const group of this.groups) {
|
for (const group of this.groups) {
|
||||||
this.groupCache.set(group.groupCode, group);
|
this.groupCache.set(group.groupCode, group);
|
||||||
const data = await this.getGroupMembers(group.groupCode, 3000);
|
|
||||||
this.groupMemberCache.set(group.groupCode, data);
|
|
||||||
}
|
}
|
||||||
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
|
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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({
|
||||||
|
groupCode: groupCode,
|
||||||
|
pageStart: 0,
|
||||||
|
pageLimit: 300,
|
||||||
|
}, pskey);
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearGroupNotifiesUnreadCount(unk: boolean) {
|
||||||
|
return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(unk);
|
||||||
|
}
|
||||||
|
|
||||||
async setGroupAvatar(gc: string, filePath: string) {
|
async setGroupAvatar(gc: string, filePath: string) {
|
||||||
return this.context.session.getGroupService().setHeader(gc, filePath);
|
return this.context.session.getGroupService().setHeader(gc, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroups(forced = false) {
|
async getGroups(forced = false) {
|
||||||
type ListenerType = NodeIKernelGroupListener['onGroupListUpdate'];
|
const [, , groupList] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
const [_retData, _updateType, groupList] = await this.core.eventWrapper.CallNormalEvent<(force: boolean) => Promise<any>, ListenerType>
|
|
||||||
(
|
|
||||||
'NodeIKernelGroupService/getGroupList',
|
'NodeIKernelGroupService/getGroupList',
|
||||||
'NodeIKernelGroupListener/onGroupListUpdate',
|
'NodeIKernelGroupListener/onGroupListUpdate',
|
||||||
1,
|
[forced],
|
||||||
5000,
|
);
|
||||||
() => true,
|
|
||||||
forced,
|
|
||||||
);
|
|
||||||
return groupList;
|
return groupList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getGroupExtFE0Info(GroupCode: string[], forced = true) {
|
||||||
|
return this.context.session.getGroupService().getGroupExt0xEF0Info(
|
||||||
|
GroupCode,
|
||||||
|
[],
|
||||||
|
{
|
||||||
|
bindGuildId: 1,
|
||||||
|
blacklistExpireTime: 1,
|
||||||
|
companyId: 1,
|
||||||
|
essentialMsgPrivilege: 1,
|
||||||
|
essentialMsgSwitch: 1,
|
||||||
|
fullGroupExpansionSeq: 1,
|
||||||
|
fullGroupExpansionSwitch: 1,
|
||||||
|
gangUpId: 1,
|
||||||
|
groupAioBindGuildId: 1,
|
||||||
|
groupBindGuildIds: 1,
|
||||||
|
groupBindGuildSwitch: 1,
|
||||||
|
groupExcludeGuildIds: 1,
|
||||||
|
groupExtFlameData: 1,
|
||||||
|
groupFlagPro1: 1,
|
||||||
|
groupInfoExtSeq: 1,
|
||||||
|
groupOwnerId: 1,
|
||||||
|
groupSquareSwitch: 1,
|
||||||
|
hasGroupCustomPortrait: 1,
|
||||||
|
inviteRobotMemberExamine: 1,
|
||||||
|
inviteRobotMemberSwitch: 1,
|
||||||
|
inviteRobotSwitch: 1,
|
||||||
|
isLimitGroupRtc: 1,
|
||||||
|
lightCharNum: 1,
|
||||||
|
luckyWord: 1,
|
||||||
|
luckyWordId: 1,
|
||||||
|
msgEventSeq: 1,
|
||||||
|
qqMusicMedalSwitch: 1,
|
||||||
|
reserve: 1,
|
||||||
|
showPlayTogetherSwitch: 1,
|
||||||
|
starId: 1,
|
||||||
|
todoSeq: 1,
|
||||||
|
viewedMsgDisappearTime: 1,
|
||||||
|
},
|
||||||
|
forced,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async getGroup(groupCode: string, forced = false) {
|
async getGroup(groupCode: string, forced = false) {
|
||||||
let group = this.groupCache.get(groupCode.toString());
|
let group = this.groupCache.get(groupCode.toString());
|
||||||
if (!group) {
|
if (!group) {
|
||||||
@@ -74,62 +121,6 @@ export class NTQQGroupApi {
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupMemberLatestSendTimeCache(GroupCode: string, uids: string[]) {
|
|
||||||
return this.getGroupMemberLatestSendTime(GroupCode, uids);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过QQ自带数据库获取群成员最后发言时间(仅返回有效数据 且消耗延迟大 需要进行缓存)
|
|
||||||
* @param GroupCode 群号
|
|
||||||
* @param uids QQ号
|
|
||||||
* @returns Map<string, string> key: uin value: sendTime
|
|
||||||
* @example
|
|
||||||
* let ret = await NTQQGroupApi.getGroupMemberLastestSendTime('123456');
|
|
||||||
* for (let [uin, sendTime] of ret) {
|
|
||||||
* console.log(uin, sendTime);
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
async getGroupMemberLatestSendTime(GroupCode: string, uids: string[]) {
|
|
||||||
const getdata = async (uid: string) => {
|
|
||||||
const NTRet = await this.getLatestMsgByUids(GroupCode, [uid]);
|
|
||||||
if (NTRet.result != 0 && NTRet.msgList.length < 1) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return { sendUin: NTRet.msgList[0].senderUin, sendTime: NTRet.msgList[0].msgTime };
|
|
||||||
};
|
|
||||||
const PromiseData: Promise<({
|
|
||||||
sendUin: string;
|
|
||||||
sendTime: string;
|
|
||||||
} | undefined)>[] = [];
|
|
||||||
const ret: Map<string, string> = new Map();
|
|
||||||
for (const uid of uids) {
|
|
||||||
PromiseData.push(getdata(uid).catch(() => undefined));
|
|
||||||
}
|
|
||||||
const allRet = await runAllWithTimeout(PromiseData, 2500);
|
|
||||||
for (const PromiseDo of allRet) {
|
|
||||||
if (PromiseDo) {
|
|
||||||
ret.set(PromiseDo.sendUin, PromiseDo.sendTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getLatestMsgByUids(GroupCode: string, uids: string[]) {
|
|
||||||
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
|
|
||||||
chatInfo: {
|
|
||||||
peerUid: GroupCode,
|
|
||||||
chatType: ChatType.KCHATTYPEGROUP,
|
|
||||||
},
|
|
||||||
filterMsgType: [],
|
|
||||||
filterSendersUid: uids,
|
|
||||||
filterMsgToTime: '0',
|
|
||||||
filterMsgFromTime: '0',
|
|
||||||
isReverseOrder: false,
|
|
||||||
isIncludeCurrent: true,
|
|
||||||
pageLimit: 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getGroupMemberAll(GroupCode: string, forced = false) {
|
async getGroupMemberAll(GroupCode: string, forced = false) {
|
||||||
return this.context.session.getGroupService().getAllMemberList(GroupCode, forced);
|
return this.context.session.getGroupService().getAllMemberList(GroupCode, forced);
|
||||||
}
|
}
|
||||||
@@ -140,11 +131,10 @@ export class NTQQGroupApi {
|
|||||||
let members = this.groupMemberCache.get(groupCodeStr);
|
let members = this.groupMemberCache.get(groupCodeStr);
|
||||||
if (!members) {
|
if (!members) {
|
||||||
try {
|
try {
|
||||||
members = await this.getGroupMembers(groupCodeStr);
|
members = await this.getGroupMembersV2(groupCodeStr);
|
||||||
// 更新群成员列表
|
// 更新群成员列表
|
||||||
this.groupMemberCache.set(groupCodeStr, members);
|
this.groupMemberCache.set(groupCodeStr, members);
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,35 +152,11 @@ export class NTQQGroupApi {
|
|||||||
|
|
||||||
let member = getMember();
|
let member = getMember();
|
||||||
if (!member) {
|
if (!member) {
|
||||||
members = await this.getGroupMembers(groupCodeStr);
|
members = await this.getGroupMembersV2(groupCodeStr);
|
||||||
member = getMember();
|
member = getMember();
|
||||||
}
|
}
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLatestMsg(GroupCode: string, uins: string[]) {
|
|
||||||
const uids: Array<string> = [];
|
|
||||||
for (const uin of uins) {
|
|
||||||
const uid = await this.core.apis.UserApi.getUidByUinV2(uin);
|
|
||||||
if (uid) {
|
|
||||||
uids.push(uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
|
|
||||||
chatInfo: {
|
|
||||||
peerUid: GroupCode,
|
|
||||||
chatType: ChatType.KCHATTYPEGROUP,
|
|
||||||
},
|
|
||||||
filterMsgType: [],
|
|
||||||
filterSendersUid: uids,
|
|
||||||
filterMsgToTime: '0',
|
|
||||||
filterMsgFromTime: '0',
|
|
||||||
isReverseOrder: false,
|
|
||||||
isIncludeCurrent: true,
|
|
||||||
pageLimit: 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getGroupRecommendContactArkJson(GroupCode: string) {
|
async getGroupRecommendContactArkJson(GroupCode: string) {
|
||||||
return this.context.session.getGroupService().getGroupRecommendContactArkJson(GroupCode);
|
return this.context.session.getGroupService().getGroupRecommendContactArkJson(GroupCode);
|
||||||
}
|
}
|
||||||
@@ -208,8 +174,7 @@ export class NTQQGroupApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async addGroupEssence(GroupCode: string, msgId: string) {
|
async addGroupEssence(GroupCode: string, msgId: string) {
|
||||||
// 代码没测过
|
// 需要 ob11msgId -> msgId + (peer) -> msgSeq + msgRandom
|
||||||
// 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom
|
|
||||||
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
|
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
|
||||||
chatType: 2,
|
chatType: 2,
|
||||||
guildId: '',
|
guildId: '',
|
||||||
@@ -220,27 +185,38 @@ export class NTQQGroupApi {
|
|||||||
msgRandom: parseInt(MsgData.msgList[0].msgRandom),
|
msgRandom: parseInt(MsgData.msgList[0].msgRandom),
|
||||||
msgSeq: parseInt(MsgData.msgList[0].msgSeq),
|
msgSeq: parseInt(MsgData.msgList[0].msgSeq),
|
||||||
};
|
};
|
||||||
// GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
|
// GetMsgByShortID(shortID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
|
||||||
return this.context.session.getGroupService().addGroupEssence(param);
|
return this.context.session.getGroupService().addGroupEssence(param);
|
||||||
}
|
}
|
||||||
async kickMemberV2Inner(param: kickMemberV2Req) {
|
|
||||||
|
async kickMemberV2Inner(param: KickMemberV2Req) {
|
||||||
return this.context.session.getGroupService().kickMemberV2(param);
|
return this.context.session.getGroupService().kickMemberV2(param);
|
||||||
}
|
}
|
||||||
async deleteGroupBulletin(GroupCode: string, feedId: string) {
|
|
||||||
const _Pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
async deleteGroupBulletin(GroupCode: string, noticeId: string) {
|
||||||
return this.context.session.getGroupService().deleteGroupBulletin(GroupCode, _Pskey, feedId);
|
const psKey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
||||||
|
return this.context.session.getGroupService().deleteGroupBulletin(GroupCode, psKey, noticeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async quitGroupV2(GroupCode: string, needDeleteLocalMsg: boolean) {
|
async quitGroupV2(GroupCode: string, needDeleteLocalMsg: boolean) {
|
||||||
const param = {
|
const param = {
|
||||||
groupCode: GroupCode,
|
groupCode: GroupCode,
|
||||||
needDeleteLocalMsg: needDeleteLocalMsg
|
needDeleteLocalMsg: needDeleteLocalMsg,
|
||||||
};
|
};
|
||||||
//应该是直接返回不需要Listener的 未经测试 需测试再发布
|
//应该是直接返回不需要Listener的 未经测试 需测试再发布
|
||||||
return this.context.session.getGroupService().quitGroupV2(param);
|
return this.context.session.getGroupService().quitGroupV2(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async removeGroupEssenceBySeq(GroupCode: string, msgRandom: string, msgSeq: string) {
|
||||||
|
const param = {
|
||||||
|
groupCode: GroupCode,
|
||||||
|
msgRandom: parseInt(msgRandom),
|
||||||
|
msgSeq: parseInt(msgSeq),
|
||||||
|
};
|
||||||
|
return this.context.session.getGroupService().removeGroupEssence(param);
|
||||||
|
}
|
||||||
|
|
||||||
async removeGroupEssence(GroupCode: string, msgId: string) {
|
async removeGroupEssence(GroupCode: string, msgId: string) {
|
||||||
// 代码没测过
|
|
||||||
// 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom
|
|
||||||
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
|
const MsgData = await this.context.session.getMsgService().getMsgsIncludeSelf({
|
||||||
chatType: 2,
|
chatType: 2,
|
||||||
guildId: '',
|
guildId: '',
|
||||||
@@ -251,38 +227,33 @@ export class NTQQGroupApi {
|
|||||||
msgRandom: parseInt(MsgData.msgList[0].msgRandom),
|
msgRandom: parseInt(MsgData.msgList[0].msgRandom),
|
||||||
msgSeq: parseInt(MsgData.msgList[0].msgSeq),
|
msgSeq: parseInt(MsgData.msgList[0].msgSeq),
|
||||||
};
|
};
|
||||||
// GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
|
|
||||||
return this.context.session.getGroupService().removeGroupEssence(param);
|
return this.context.session.getGroupService().removeGroupEssence(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSingleScreenNotifies(num: number) {
|
async getSingleScreenNotifies(doubt: boolean, num: number) {
|
||||||
const [_retData, _doubt, _seq, notifies] = await this.core.eventWrapper.CallNormalEvent<(arg1: boolean, arg2: string, arg3: number) => Promise<any>, (doubt: boolean, seq: string, notifies: GroupNotify[]) => void>
|
const [, , , notifies] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
(
|
|
||||||
'NodeIKernelGroupService/getSingleScreenNotifies',
|
'NodeIKernelGroupService/getSingleScreenNotifies',
|
||||||
'NodeIKernelGroupListener/onGroupSingleScreenNotifies',
|
'NodeIKernelGroupListener/onGroupSingleScreenNotifies',
|
||||||
1,
|
[
|
||||||
5000,
|
doubt,
|
||||||
() => true,
|
'',
|
||||||
false,
|
num,
|
||||||
'',
|
],
|
||||||
num,
|
);
|
||||||
);
|
|
||||||
return notifies;
|
return notifies;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupMemberV2(GroupCode: string, uid: string, forced = false) {
|
async getGroupMemberV2(GroupCode: string, uid: string, forced = false) {
|
||||||
type EventType = NodeIKernelGroupService['getMemberInfo'];
|
const Listener = this.core.eventWrapper.registerListen(
|
||||||
const Listener = this.core.eventWrapper.RegisterListen<(params: any) => void>
|
|
||||||
(
|
|
||||||
'NodeIKernelGroupListener/onMemberInfoChange',
|
'NodeIKernelGroupListener/onMemberInfoChange',
|
||||||
1,
|
1,
|
||||||
forced ? 5000 : 250,
|
forced ? 5000 : 250,
|
||||||
(params) => {
|
(params) => params === GroupCode,
|
||||||
return params === GroupCode;
|
);
|
||||||
},
|
const retData = await (
|
||||||
);
|
this.core.eventWrapper
|
||||||
const EventFunc = this.core.eventWrapper.createEventFunction<EventType>('NodeIKernelGroupService/getMemberInfo');
|
.createEventFunction('NodeIKernelGroupService/getMemberInfo')
|
||||||
const retData = await EventFunc!(GroupCode, [uid], forced);
|
)!(GroupCode, [uid], forced);
|
||||||
if (retData.result !== 0) {
|
if (retData.result !== 0) {
|
||||||
throw new Error(`${retData.errMsg}`);
|
throw new Error(`${retData.errMsg}`);
|
||||||
}
|
}
|
||||||
@@ -295,6 +266,38 @@ export class NTQQGroupApi {
|
|||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getGroupMembersV2(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
||||||
|
const groupService = this.context.session.getGroupService();
|
||||||
|
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
||||||
|
const listener = this.core.eventWrapper.registerListen(
|
||||||
|
'NodeIKernelGroupListener/onMemberListChange',
|
||||||
|
1,
|
||||||
|
500,
|
||||||
|
(params) => params.sceneId === sceneId,
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
const [membersFromFunc, membersFromListener] = await Promise.allSettled([
|
||||||
|
groupService.getNextMemberList(sceneId, undefined, num),
|
||||||
|
listener,
|
||||||
|
]);
|
||||||
|
if (membersFromFunc.status === 'fulfilled' && membersFromListener.status === 'fulfilled') {
|
||||||
|
return new Map([
|
||||||
|
...membersFromFunc.value.result.infos,
|
||||||
|
...membersFromListener.value[0].infos,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if (membersFromFunc.status === 'fulfilled') {
|
||||||
|
return membersFromFunc.value.result.infos;
|
||||||
|
}
|
||||||
|
if (membersFromListener.status === 'fulfilled') {
|
||||||
|
return membersFromListener.value[0].infos;
|
||||||
|
}
|
||||||
|
throw new Error('获取群成员列表失败');
|
||||||
|
} finally {
|
||||||
|
groupService.destroyMemberListScene(sceneId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
||||||
const groupService = this.context.session.getGroupService();
|
const groupService = this.context.session.getGroupService();
|
||||||
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
||||||
@@ -305,36 +308,17 @@ export class NTQQGroupApi {
|
|||||||
|
|
||||||
this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`); //, Array.from(result.result.infos.values()));
|
this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`); //, Array.from(result.result.infos.values()));
|
||||||
return result.result.infos;
|
return result.result.infos;
|
||||||
/*
|
|
||||||
console.log(sceneId);
|
|
||||||
const result = await napCatCore.getGroupService().getNextMemberList(sceneId, num);
|
|
||||||
console.log(result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupNotifies() {
|
async getGroupFileCount(Gids: Array<string>) {
|
||||||
// 获取管理员变更
|
|
||||||
// 加群通知,退出通知,需要管理员权限
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
async GetGroupFileCount(Gids: Array<string>) {
|
|
||||||
return this.context.session.getRichMediaService().batchGetGroupFileCount(Gids);
|
return this.context.session.getRichMediaService().batchGetGroupFileCount(Gids);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupIgnoreNotifies() {
|
|
||||||
}
|
|
||||||
|
|
||||||
async getArkJsonGroupShare(GroupCode: string) {
|
async getArkJsonGroupShare(GroupCode: string) {
|
||||||
const ret = await this.core.eventWrapper.callNoListenerEvent<(GroupId: string) => Promise<GeneralCallResult & {
|
const ret = await this.core.eventWrapper.callNoListenerEvent(
|
||||||
arkJson: string
|
|
||||||
}>>(
|
|
||||||
'NodeIKernelGroupService/getGroupRecommendContactArkJson',
|
'NodeIKernelGroupService/getGroupRecommendContactArkJson',
|
||||||
5000,
|
|
||||||
GroupCode,
|
GroupCode,
|
||||||
);
|
) as GeneralCallResult & { arkJson: string };
|
||||||
return ret.arkJson;
|
return ret.arkJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +342,7 @@ export class NTQQGroupApi {
|
|||||||
'seq': seq, // 通知序列号
|
'seq': seq, // 通知序列号
|
||||||
'type': type,
|
'type': type,
|
||||||
'groupCode': groupCode,
|
'groupCode': groupCode,
|
||||||
'postscript': reason || ' ', // 仅传空值可能导致处理失败,故默认给个空格
|
'postscript': reason ?? ' ', // 仅传空值可能导致处理失败,故默认给个空格
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -392,19 +376,12 @@ export class NTQQGroupApi {
|
|||||||
return this.context.session.getGroupService().modifyGroupName(groupQQ, groupName, false);
|
return this.context.session.getGroupService().modifyGroupName(groupQQ, groupName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 头衔不可用
|
|
||||||
/*
|
|
||||||
async setGroupTitle(groupQQ: string, uid: string, title: string) {
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
async publishGroupBulletin(groupQQ: string, content: string, picInfo: {
|
async publishGroupBulletin(groupQQ: string, content: string, picInfo: {
|
||||||
id: string,
|
id: string,
|
||||||
width: number,
|
width: number,
|
||||||
height: number
|
height: number
|
||||||
} | undefined = undefined, pinned: number = 0, confirmRequired: number = 0) {
|
} | undefined = undefined, pinned: number = 0, confirmRequired: number = 0) {
|
||||||
const _Pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com');
|
const psKey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com');
|
||||||
//text是content内容url编码
|
//text是content内容url编码
|
||||||
const data = {
|
const data = {
|
||||||
text: encodeURI(content),
|
text: encodeURI(content),
|
||||||
@@ -413,7 +390,7 @@ export class NTQQGroupApi {
|
|||||||
pinned: pinned,
|
pinned: pinned,
|
||||||
confirmRequired: confirmRequired,
|
confirmRequired: confirmRequired,
|
||||||
};
|
};
|
||||||
return this.context.session.getGroupService().publishGroupBulletin(groupQQ, _Pskey!, data);
|
return this.context.session.getGroupService().publishGroupBulletin(groupQQ, psKey!, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupRemainAtTimes(GroupCode: string) {
|
async getGroupRemainAtTimes(GroupCode: string) {
|
||||||
|
@@ -5,4 +5,5 @@ export * from './msg';
|
|||||||
export * from './user';
|
export * from './user';
|
||||||
export * from './webapi';
|
export * from './webapi';
|
||||||
export * from './sign';
|
export * from './sign';
|
||||||
export * from './system';
|
export * from './system';
|
||||||
|
export * from './cache';
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement, SendStatusType } from '@/core/entities';
|
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement, SendStatusType } from '@/core/entities';
|
||||||
import { InstanceContext, NapCatCore } from '@/core';
|
import { InstanceContext, NapCatCore } from '@/core';
|
||||||
import { onGroupFileInfoUpdateParamType } from '@/core/listeners';
|
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
|
|
||||||
export class NTQQMsgApi {
|
export class NTQQMsgApi {
|
||||||
|
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
|
||||||
|
// nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid
|
||||||
|
// 其实以官方文档为准是最好的,https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType
|
||||||
|
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
core: NapCatCore;
|
core: NapCatCore;
|
||||||
|
|
||||||
@@ -12,6 +15,14 @@ export class NTQQMsgApi {
|
|||||||
this.core = core;
|
this.core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAioFirstViewLatestMsgs(peer: Peer, MsgCount: number) {
|
||||||
|
return this.context.session.getMsgService().getAioFirstViewLatestMsgs(peer, MsgCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getLatestDbMsgs(peer: Peer, MsgCount: number) {
|
||||||
|
return this.context.session.getMsgService().getLatestDbMsgs(peer, MsgCount);
|
||||||
|
}
|
||||||
|
|
||||||
async FetchLongMsg(peer: Peer, msgId: string) {
|
async FetchLongMsg(peer: Peer, msgId: string) {
|
||||||
return this.context.session.getMsgService().fetchLongMsg(peer, msgId);
|
return this.context.session.getMsgService().fetchLongMsg(peer, msgId);
|
||||||
}
|
}
|
||||||
@@ -19,20 +30,12 @@ export class NTQQMsgApi {
|
|||||||
async sendShowInputStatusReq(peer: Peer, eventType: number) {
|
async sendShowInputStatusReq(peer: Peer, eventType: number) {
|
||||||
return this.context.session.getMsgService().sendShowInputStatusReq(peer.chatType, eventType, peer.peerUid);
|
return this.context.session.getMsgService().sendShowInputStatusReq(peer.chatType, eventType, peer.peerUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) {
|
async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) {
|
||||||
//console.log(peer, msgSeq, emojiId, emojiType, count);
|
|
||||||
//注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa
|
//注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa
|
||||||
return this.context.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, '', false, 20);
|
return this.context.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, '', false, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// napCatCore: NapCatCore | null = null;
|
|
||||||
// enum BaseEmojiType {
|
|
||||||
// NORMAL_EMOJI,
|
|
||||||
// SUPER_EMOJI,
|
|
||||||
// RANDOM_SUPER_EMOJI,
|
|
||||||
// CHAIN_SUPER_EMOJI,
|
|
||||||
// EMOJI_EMOJI
|
|
||||||
// }
|
|
||||||
async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) {
|
async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) {
|
||||||
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
|
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
|
||||||
// nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid
|
// nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid
|
||||||
@@ -40,6 +43,7 @@ export class NTQQMsgApi {
|
|||||||
emojiId = emojiId.toString();
|
emojiId = emojiId.toString();
|
||||||
return this.context.session.getMsgService().setMsgEmojiLikes(peer, msgSeq, emojiId, emojiId.length > 3 ? '2' : '1', set);
|
return this.context.session.getMsgService().setMsgEmojiLikes(peer, msgSeq, emojiId, emojiId.length > 3 ? '2' : '1', set);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMultiMsg(peer: Peer, rootMsgId: string, parentMsgId: string): Promise<GeneralCallResult & {
|
async getMultiMsg(peer: Peer, rootMsgId: string, parentMsgId: string): Promise<GeneralCallResult & {
|
||||||
msgList: RawMessage[]
|
msgList: RawMessage[]
|
||||||
} | undefined> {
|
} | undefined> {
|
||||||
@@ -50,24 +54,10 @@ export class NTQQMsgApi {
|
|||||||
return this.context.session.getMsgService().forwardMsg(msgIds, peer, [peer], new Map());
|
return this.context.session.getMsgService().forwardMsg(msgIds, peer, [peer], new Map());
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLastestMsgByUids(peer: Peer, count: number = 20, isReverseOrder: boolean = false) {
|
|
||||||
const ret = await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
|
|
||||||
chatInfo: peer,
|
|
||||||
filterMsgType: [],
|
|
||||||
filterSendersUid: [],
|
|
||||||
filterMsgToTime: '0',
|
|
||||||
filterMsgFromTime: '0',
|
|
||||||
isReverseOrder: isReverseOrder,//此参数有点离谱 注意不是本次查询的排序 而是全部消历史信息的排序 默认false 从新消息拉取到旧消息
|
|
||||||
isIncludeCurrent: true,
|
|
||||||
pageLimit: count,
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) {
|
async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) {
|
||||||
if (!peer) throw new Error('peer is not allowed');
|
if (!peer) throw new Error('peer is not allowed');
|
||||||
if (!msgIds) throw new Error('msgIds is not allowed');
|
if (!msgIds) throw new Error('msgIds is not allowed');
|
||||||
//Mlikiowa: 参数不合规会导致NC异常崩溃 原因是TX未对进入参数判断 对应Android标记@NotNull AndroidJADX分析可得
|
//MliKiowa: 参数不合规会导致NC异常崩溃 原因是TX未对进入参数判断 对应Android标记@NotNull AndroidJADX分析可得
|
||||||
return await this.context.session.getMsgService().getMsgsByMsgId(peer, msgIds);
|
return await this.context.session.getMsgService().getMsgsByMsgId(peer, msgIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +70,8 @@ export class NTQQMsgApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) {
|
async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) {
|
||||||
const ret = await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||||||
chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa
|
chatInfo: peer,
|
||||||
filterMsgType: [],
|
filterMsgType: [],
|
||||||
filterSendersUid: [],
|
filterSendersUid: [],
|
||||||
filterMsgToTime: '0',
|
filterMsgToTime: '0',
|
||||||
@@ -90,17 +80,47 @@ export class NTQQMsgApi {
|
|||||||
isIncludeCurrent: true,
|
isIncludeCurrent: true,
|
||||||
pageLimit: 1,
|
pageLimit: 1,
|
||||||
});
|
});
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
async queryMsgsWithFilterExWithSeqV2(peer: Peer, msgSeq: string, MsgTime: string, SendersUid: string[]) {
|
||||||
|
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||||||
|
chatInfo: peer,
|
||||||
|
filterMsgType: [],
|
||||||
|
filterSendersUid: SendersUid,
|
||||||
|
filterMsgToTime: MsgTime,
|
||||||
|
filterMsgFromTime: MsgTime,
|
||||||
|
isReverseOrder: false,
|
||||||
|
isIncludeCurrent: true,
|
||||||
|
pageLimit: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async queryFirstMsgBySeq(peer: Peer, msgSeq: string) {
|
||||||
|
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||||||
|
chatInfo: peer,
|
||||||
|
filterMsgType: [],
|
||||||
|
filterSendersUid: [],
|
||||||
|
filterMsgToTime: '0',
|
||||||
|
filterMsgFromTime: '0',
|
||||||
|
isReverseOrder: true,
|
||||||
|
isIncludeCurrent: true,
|
||||||
|
pageLimit: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
|
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
|
||||||
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
|
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
|
||||||
}
|
}
|
||||||
|
async getMsgBySeqList(peer: Peer, msgSeqList: string[]) {
|
||||||
|
//坏的
|
||||||
|
return await this.context.session.getMsgService().getMsgsBySeqList(peer, msgSeqList);
|
||||||
|
}
|
||||||
|
async getMsgBySeqExFirstMsg(peer: Peer, rootMsgId: string, replyMsgId: string) {
|
||||||
|
let reply = await this.context.session.getMsgService().getSourceOfReplyMsgV2(peer, rootMsgId, replyMsgId);
|
||||||
|
console.log(reply);
|
||||||
|
}
|
||||||
async getMsgExBySeq(peer: Peer, msgSeq: string) {
|
async getMsgExBySeq(peer: Peer, msgSeq: string) {
|
||||||
const DateNow = Math.floor(Date.now() / 1000);
|
const DateNow = Math.floor(Date.now() / 1000);
|
||||||
const filterMsgFromTime = (DateNow - 300).toString();
|
const filterMsgFromTime = (DateNow - 300).toString();
|
||||||
const filterMsgToTime = DateNow.toString();
|
const filterMsgToTime = DateNow.toString();
|
||||||
const ret = await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||||||
chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa
|
chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa
|
||||||
filterMsgType: [],
|
filterMsgType: [],
|
||||||
filterSendersUid: [],
|
filterSendersUid: [],
|
||||||
@@ -110,29 +130,26 @@ export class NTQQMsgApi {
|
|||||||
isIncludeCurrent: true,
|
isIncludeCurrent: true,
|
||||||
pageLimit: 100,
|
pageLimit: 100,
|
||||||
});
|
});
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async setMsgRead(peer: Peer) {
|
async setMsgRead(peer: Peer) {
|
||||||
return this.context.session.getMsgService().setMsgRead(peer);
|
return this.context.session.getMsgService().setMsgRead(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupFileList(GroupCode: string, params: GetFileListParam) {
|
async getGroupFileList(GroupCode: string, params: GetFileListParam) {
|
||||||
const data = await this.core.eventWrapper.CallNormalEvent<
|
const [, groupFileListResult] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
(GroupCode: string, params: GetFileListParam) => Promise<unknown>,
|
'NodeIKernelRichMediaService/getGroupFileList',
|
||||||
(groupFileListResult: onGroupFileInfoUpdateParamType) => void
|
'NodeIKernelMsgListener/onGroupFileInfoUpdate',
|
||||||
>(
|
[
|
||||||
'NodeIKernelRichMediaService/getGroupFileList',
|
|
||||||
'NodeIKernelMsgListener/onGroupFileInfoUpdate',
|
|
||||||
1,
|
|
||||||
5000,
|
|
||||||
(groupFileListResult: onGroupFileInfoUpdateParamType) => {
|
|
||||||
//Developer Mlikiowa Todo: 此处有问题 无法判断是否成功
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
GroupCode,
|
GroupCode,
|
||||||
params,
|
params,
|
||||||
);
|
],
|
||||||
return data[1].item;
|
() => true,
|
||||||
|
() => true, // Todo: 应当通过 groupFileListResult 判断
|
||||||
|
1,
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
return groupFileListResult.item;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMsgHistory(peer: Peer, msgId: string, count: number, isReverseOrder: boolean = false) {
|
async getMsgHistory(peer: Peer, msgId: string, count: number, isReverseOrder: boolean = false) {
|
||||||
@@ -146,31 +163,32 @@ export class NTQQMsgApi {
|
|||||||
peerUid: peer.peerUid,
|
peerUid: peer.peerUid,
|
||||||
}, msgIds);
|
}, msgIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) {
|
async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) {
|
||||||
//By Jadx/Ida Mlikiowa
|
|
||||||
const TempGameSession = {
|
|
||||||
nickname: "",
|
|
||||||
gameAppId: "",
|
|
||||||
selfTinyId: "",
|
|
||||||
peerRoleId: "",
|
|
||||||
peerOpenId: "",
|
|
||||||
};
|
|
||||||
return this.context.session.getMsgService().prepareTempChat({
|
return this.context.session.getMsgService().prepareTempChat({
|
||||||
chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP,
|
chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP,
|
||||||
peerUid: toUserUid,
|
peerUid: toUserUid,
|
||||||
peerNickname: nickname,
|
peerNickname: nickname,
|
||||||
fromGroupCode: GroupCode,
|
fromGroupCode: GroupCode,
|
||||||
sig: "",
|
sig: '',
|
||||||
selfPhone: "",
|
selfPhone: '',
|
||||||
selfUid: this.core.selfInfo.uid,
|
selfUid: this.core.selfInfo.uid,
|
||||||
gameSession: TempGameSession
|
gameSession: {
|
||||||
|
nickname: '',
|
||||||
|
gameAppId: '',
|
||||||
|
selfTinyId: '',
|
||||||
|
peerRoleId: '',
|
||||||
|
peerOpenId: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTempChatInfo(chatType: ChatType, peerUid: string) {
|
async getTempChatInfo(chatType: ChatType, peerUid: string) {
|
||||||
return this.context.session.getMsgService().getTempChatInfo(chatType, peerUid);
|
return this.context.session.getMsgService().getTempChatInfo(chatType, peerUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
||||||
//唉? !我有个想法
|
//唉?!我有个想法
|
||||||
if (peer.chatType === ChatType.KCHATTYPETEMPC2CFROMGROUP && peer.guildId && peer.guildId !== '') {
|
if (peer.chatType === ChatType.KCHATTYPETEMPC2CFROMGROUP && peer.guildId && peer.guildId !== '') {
|
||||||
const member = await this.core.apis.GroupApi.getGroupMember(peer.guildId, peer.peerUid!);
|
const member = await this.core.apis.GroupApi.getGroupMember(peer.guildId, peer.peerUid!);
|
||||||
if (member) {
|
if (member) {
|
||||||
@@ -179,33 +197,28 @@ export class NTQQMsgApi {
|
|||||||
}
|
}
|
||||||
const msgId = await this.generateMsgUniqueId(peer.chatType, await this.getServerTime());
|
const msgId = await this.generateMsgUniqueId(peer.chatType, await this.getServerTime());
|
||||||
peer.guildId = msgId;
|
peer.guildId = msgId;
|
||||||
const data = await this.core.eventWrapper.CallNormalEvent<
|
const [, msgList] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map<any, any>) => Promise<unknown>,
|
'NodeIKernelMsgService/sendMsg',
|
||||||
(msgList: RawMessage[]) => void
|
'NodeIKernelMsgListener/onMsgInfoListUpdate',
|
||||||
>(
|
[
|
||||||
'NodeIKernelMsgService/sendMsg',
|
|
||||||
'NodeIKernelMsgListener/onMsgInfoListUpdate',
|
|
||||||
1,
|
|
||||||
timeout,
|
|
||||||
(msgRecords: RawMessage[]) => {
|
|
||||||
for (const msgRecord of msgRecords) {
|
|
||||||
if (msgRecord.guildId === msgId && msgRecord.sendStatus === SendStatusType.KSEND_STATUS_SUCCESS) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
'0',
|
'0',
|
||||||
peer,
|
peer,
|
||||||
msgElements,
|
msgElements,
|
||||||
new Map(),
|
new Map(),
|
||||||
);
|
],
|
||||||
const retMsg = data[1].find(msgRecord => {
|
(ret) => ret.result === 0,
|
||||||
if (msgRecord.guildId === msgId) {
|
msgRecords => {
|
||||||
return true;
|
for (const msgRecord of msgRecords) {
|
||||||
}
|
if (msgRecord.guildId === msgId && msgRecord.sendStatus === SendStatusType.KSEND_STATUS_SUCCESS) {
|
||||||
});
|
return true;
|
||||||
return retMsg;
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
timeout,
|
||||||
|
);
|
||||||
|
return msgList.find(msgRecord => msgRecord.guildId === msgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async generateMsgUniqueId(chatType: number, time: string) {
|
async generateMsgUniqueId(chatType: number, time: string) {
|
||||||
@@ -224,34 +237,28 @@ export class NTQQMsgApi {
|
|||||||
const msgInfos = msgIds.map(id => {
|
const msgInfos = msgIds.map(id => {
|
||||||
return { msgId: id, senderShowName: this.core.selfInfo.nick };
|
return { msgId: id, senderShowName: this.core.selfInfo.nick };
|
||||||
});
|
});
|
||||||
const data = await this.core.eventWrapper.CallNormalEvent<
|
const [, msgList] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
(msgInfo: typeof msgInfos, srcPeer: Peer, destPeer: Peer, comment: Array<any>, attr: Map<any, any>) => Promise<unknown>,
|
'NodeIKernelMsgService/multiForwardMsgWithComment',
|
||||||
(msgList: RawMessage[]) => void
|
'NodeIKernelMsgListener/onMsgInfoListUpdate',
|
||||||
>(
|
[
|
||||||
'NodeIKernelMsgService/multiForwardMsgWithComment',
|
|
||||||
'NodeIKernelMsgListener/onMsgInfoListUpdate',
|
|
||||||
1,
|
|
||||||
5000,
|
|
||||||
(msgRecords: RawMessage[]) => {
|
|
||||||
for (const msgRecord of msgRecords) {
|
|
||||||
if (msgRecord.peerUid == destPeer.peerUid && msgRecord.senderUid == this.core.selfInfo.uid) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
msgInfos,
|
msgInfos,
|
||||||
srcPeer,
|
srcPeer,
|
||||||
destPeer,
|
destPeer,
|
||||||
[],
|
[],
|
||||||
new Map(),
|
new Map(),
|
||||||
);
|
],
|
||||||
for (const msg of data[1]) {
|
() => true,
|
||||||
|
(msgRecords) => msgRecords.some(
|
||||||
|
msgRecord => msgRecord.peerUid === destPeer.peerUid
|
||||||
|
&& msgRecord.senderUid === this.core.selfInfo.uid
|
||||||
|
),
|
||||||
|
);
|
||||||
|
for (const msg of msgList) {
|
||||||
const arkElement = msg.elements.find(ele => ele.arkElement);
|
const arkElement = msg.elements.find(ele => ele.arkElement);
|
||||||
if (!arkElement) {
|
if (!arkElement) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const forwardData: any = JSON.parse(arkElement.arkElement?.bytesData || "");
|
const forwardData: any = JSON.parse(arkElement.arkElement?.bytesData ?? '');
|
||||||
if (forwardData.app != 'com.tencent.multimsg') {
|
if (forwardData.app != 'com.tencent.multimsg') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -262,7 +269,7 @@ export class NTQQMsgApi {
|
|||||||
throw new Error('转发消息超时');
|
throw new Error('转发消息超时');
|
||||||
}
|
}
|
||||||
|
|
||||||
async markallMsgAsRead() {
|
async markAllMsgAsRead() {
|
||||||
return this.context.session.getMsgService().setAllC2CAndGroupMsgRead();
|
return this.context.session.getMsgService().setAllC2CAndGroupMsgRead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,78 +1,7 @@
|
|||||||
import { RequestUtil } from '@/common/utils/request';
|
import { RequestUtil } from '@/common/request';
|
||||||
import { MiniAppLuaJsonType } from '@/core';
|
import { MiniAppLuaJsonType } from '@/core';
|
||||||
import { InstanceContext, NapCatCore } from '..';
|
import { InstanceContext, NapCatCore } from '..';
|
||||||
|
|
||||||
// let t = await napCatCore.session.getGroupService().shareDigest({
|
|
||||||
// appId: "100497308",
|
|
||||||
// appType: 1,
|
|
||||||
// msgStyle: 0,
|
|
||||||
// recvUin: "726067488",
|
|
||||||
// sendType: 1,
|
|
||||||
// clientInfo: {
|
|
||||||
// platform: 1
|
|
||||||
// },
|
|
||||||
// richMsg: {
|
|
||||||
// usingArk: true,
|
|
||||||
// title: "Bot测试title",
|
|
||||||
// summary: "Bot测试summary",
|
|
||||||
// url: "https://www.bilibili.com",
|
|
||||||
// pictureUrl: "https://y.qq.com/music/photo_new/T002R300x300M0000035DC6W4ZpSqf_1.jpg?max_age=2592000",
|
|
||||||
// brief: "Bot测试brief",
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// {
|
|
||||||
// errCode: 0,
|
|
||||||
// errMsg: '',
|
|
||||||
// rsp: {
|
|
||||||
// sendType: 1,
|
|
||||||
// recvUin: '726067488',
|
|
||||||
// recvOpenId: '',
|
|
||||||
// errCode: 901501,
|
|
||||||
// errMsg: 'imagent service_error:150_OIDB_NO_PRIV',
|
|
||||||
// extInfo: {
|
|
||||||
// wording: '消息下发失败(错误码:901501)',
|
|
||||||
// jumpResult: 0,
|
|
||||||
// jumpUrl: '',
|
|
||||||
// level: 0,
|
|
||||||
// subLevel: 0,
|
|
||||||
// developMsg: 'imagent error'
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export class MusicSign {
|
|
||||||
// private readonly url: string;
|
|
||||||
|
|
||||||
// constructor(url: string) {
|
|
||||||
// this.url = url;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// sign(postData: CustomMusicSignPostData | IdMusicSignPostData): Promise<any> {
|
|
||||||
// return new Promise((resolve, reject) => {
|
|
||||||
// fetch(this.url, {
|
|
||||||
// method: 'POST', // 指定请求方法为 POST
|
|
||||||
// headers: {
|
|
||||||
// 'Content-Type': 'application/json' // 设置请求头,指明发送的数据类型为 JSON
|
|
||||||
// },
|
|
||||||
// body: JSON.stringify(postData) // 将 JavaScript 对象转换为 JSON 字符串作为请求体
|
|
||||||
// })
|
|
||||||
// .then(response => {
|
|
||||||
// if (!response.ok) {
|
|
||||||
// reject(response.statusText); // 请求失败,返回错误信息
|
|
||||||
// }
|
|
||||||
// return response.json(); // 解析 JSON 格式的响应体
|
|
||||||
// })
|
|
||||||
// .then(data => {
|
|
||||||
// logDebug('音乐消息生成成功', data);
|
|
||||||
// resolve(data);
|
|
||||||
// })
|
|
||||||
// .catch(error => {
|
|
||||||
// reject(error);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
export class NTQQMusicSignApi {
|
export class NTQQMusicSignApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
core: NapCatCore;
|
core: NapCatCore;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { GeneralCallResult, InstanceContext, NapCatCore } from '@/core';
|
import { InstanceContext, NapCatCore } from '@/core';
|
||||||
|
|
||||||
export class NTQQSystemApi {
|
export class NTQQSystemApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
@@ -13,7 +13,7 @@ export class NTQQSystemApi {
|
|||||||
return this.core.util.hasOtherRunningQQProcess();
|
return this.core.util.hasOtherRunningQQProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
async ORCImage(filePath: string) {
|
async ocrImage(filePath: string) {
|
||||||
return this.context.session.getNodeMiscService().wantWinScreenOCR(filePath);
|
return this.context.session.getNodeMiscService().wantWinScreenOCR(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,27 +21,16 @@ export class NTQQSystemApi {
|
|||||||
return this.context.session.getRichMediaService().translateEnWordToZn(words);
|
return this.context.session.getRichMediaService().translateEnWordToZn(words);
|
||||||
}
|
}
|
||||||
|
|
||||||
//调用会超时 没灯用 (好像是通知listener的) onLineDev
|
|
||||||
async getOnlineDev() {
|
async getOnlineDev() {
|
||||||
return this.context.session.getMsgService().getOnLineDev();
|
return this.context.session.getMsgService().getOnLineDev();
|
||||||
}
|
}
|
||||||
|
|
||||||
//1-2-162b9b42-65b9-4405-a8ed-2e256ec8aa50
|
|
||||||
async getArkJsonCollection(cid: string) {
|
async getArkJsonCollection(cid: string) {
|
||||||
const ret = await this.core.eventWrapper.callNoListenerEvent<(cid: string) => Promise<GeneralCallResult & {
|
return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelCollectionService/collectionArkShare', '1717662698058');
|
||||||
arkJson: string
|
|
||||||
}>>(
|
|
||||||
'NodeIKernelCollectionService/collectionArkShare',
|
|
||||||
5000,
|
|
||||||
'1717662698058',
|
|
||||||
);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async BootMiniApp(appfile: string, params: string) {
|
async bootMiniApp(appFile: string, params: string) {
|
||||||
await this.context.session.getNodeMiscService().setMiniAppVersion('2.16.4');
|
await this.context.session.getNodeMiscService().setMiniAppVersion('2.16.4');
|
||||||
const c = await this.context.session.getNodeMiscService().getMiniAppPath();
|
return this.context.session.getNodeMiscService().startNewMiniApp(appFile, params);
|
||||||
|
|
||||||
return this.context.session.getNodeMiscService().startNewMiniApp(appfile, params);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
import type { ModifyProfileParams, User, UserDetailInfoByUin, UserDetailInfoByUinV2 } from '@/core/entities';
|
import type { ModifyProfileParams, User } from '@/core/entities';
|
||||||
import { NodeIKernelProfileListener } from '@/core/listeners';
|
import { RequestUtil } from '@/common/request';
|
||||||
import { RequestUtil } from '@/common/utils/request';
|
import { ProfileBizType, UserDetailSource } from '@/core/services';
|
||||||
import { NodeIKernelProfileService, ProfileBizType, UserDetailSource } from '@/core/services';
|
|
||||||
import { InstanceContext, NapCatCore } from '..';
|
import { InstanceContext, NapCatCore } from '..';
|
||||||
import { solveAsyncProblem } from '@/common/utils/helper';
|
import { solveAsyncProblem } from '@/common/helper';
|
||||||
|
|
||||||
export class NTQQUserApi {
|
export class NTQQUserApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
@@ -16,9 +15,7 @@ export class NTQQUserApi {
|
|||||||
|
|
||||||
async getProfileLike(uid: string) {
|
async getProfileLike(uid: string) {
|
||||||
return this.context.session.getProfileLikeService().getBuddyProfileLike({
|
return this.context.session.getProfileLikeService().getBuddyProfileLike({
|
||||||
friendUids: [
|
friendUids: [uid],
|
||||||
uid,
|
|
||||||
],
|
|
||||||
basic: 1,
|
basic: 1,
|
||||||
vote: 1,
|
vote: 1,
|
||||||
favorite: 0,
|
favorite: 0,
|
||||||
@@ -64,56 +61,18 @@ export class NTQQUserApi {
|
|||||||
return this.context.session.getGroupService().setHeader(gc, filePath);
|
return this.context.session.getGroupService().setHeader(gc, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchUserDetailInfos(uids: string[]) {
|
|
||||||
//26702 以上使用新接口 .Dev Mlikiowa
|
|
||||||
type EventService = NodeIKernelProfileService['fetchUserDetailInfo'];
|
|
||||||
type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged'];
|
|
||||||
const retData: User[] = [];
|
|
||||||
const [_retData, _retListener] = await this.core.eventWrapper.CallNormalEvent<
|
|
||||||
EventService, EventListener
|
|
||||||
>(
|
|
||||||
'NodeIKernelProfileService/fetchUserDetailInfo',
|
|
||||||
'NodeIKernelProfileListener/onUserDetailInfoChanged',
|
|
||||||
uids.length,
|
|
||||||
5000,
|
|
||||||
(profile) => {
|
|
||||||
if (uids.includes(profile.uid)) {
|
|
||||||
const RetUser: User = {
|
|
||||||
...profile.simpleInfo.coreInfo,
|
|
||||||
...profile.simpleInfo.status,
|
|
||||||
...profile.simpleInfo.vasInfo,
|
|
||||||
...profile.commonExt,
|
|
||||||
...profile.simpleInfo.baseInfo,
|
|
||||||
qqLevel: profile.commonExt.qqLevel,
|
|
||||||
pendantId: '',
|
|
||||||
};
|
|
||||||
retData.push(RetUser);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
'BuddyProfileStore',
|
|
||||||
uids,
|
|
||||||
UserDetailSource.KSERVER,
|
|
||||||
[ProfileBizType.KALL],
|
|
||||||
);
|
|
||||||
|
|
||||||
return retData;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchUserDetailInfo(uid: string, mode: UserDetailSource = UserDetailSource.KDB) {
|
async fetchUserDetailInfo(uid: string, mode: UserDetailSource = UserDetailSource.KDB) {
|
||||||
type EventService = NodeIKernelProfileService['fetchUserDetailInfo'];
|
const [_retData, profile] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged'];
|
|
||||||
const [_retData, profile] = await this.core.eventWrapper.CallNormalEvent<EventService, EventListener>(
|
|
||||||
'NodeIKernelProfileService/fetchUserDetailInfo',
|
'NodeIKernelProfileService/fetchUserDetailInfo',
|
||||||
'NodeIKernelProfileListener/onUserDetailInfoChanged',
|
'NodeIKernelProfileListener/onUserDetailInfoChanged',
|
||||||
1,
|
[
|
||||||
5000,
|
'BuddyProfileStore',
|
||||||
|
[uid],
|
||||||
|
mode,
|
||||||
|
[ProfileBizType.KALL],
|
||||||
|
],
|
||||||
|
() => true,
|
||||||
(profile) => profile.uid === uid,
|
(profile) => profile.uid === uid,
|
||||||
'BuddyProfileStore',
|
|
||||||
[uid],
|
|
||||||
mode,
|
|
||||||
[ProfileBizType.KALL],
|
|
||||||
);
|
);
|
||||||
const RetUser: User = {
|
const RetUser: User = {
|
||||||
...profile.simpleInfo.coreInfo,
|
...profile.simpleInfo.coreInfo,
|
||||||
@@ -129,7 +88,7 @@ export class NTQQUserApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getUserDetailInfo(uid: string): Promise<User> {
|
async getUserDetailInfo(uid: string): Promise<User> {
|
||||||
const retUser = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, UserDetailSource.KDB));
|
const retUser = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, UserDetailSource.KDB), uid);
|
||||||
if (retUser && retUser.uin !== '0') {
|
if (retUser && retUser.uin !== '0') {
|
||||||
return retUser;
|
return retUser;
|
||||||
}
|
}
|
||||||
@@ -146,8 +105,7 @@ export class NTQQUserApi {
|
|||||||
const ClientKeyData = await this.forceFetchClientKey();
|
const ClientKeyData = await this.forceFetchClientKey();
|
||||||
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin +
|
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin +
|
||||||
'&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
|
'&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
|
||||||
const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
|
return await RequestUtil.HttpsGetCookies(requestUrl);
|
||||||
return cookies;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPSkey(domainList: string[]) {
|
async getPSkey(domainList: string[]) {
|
||||||
@@ -161,7 +119,6 @@ export class NTQQUserApi {
|
|||||||
version: 0,
|
version: 0,
|
||||||
aioKeywordVersion: 0,
|
aioKeywordVersion: 0,
|
||||||
});
|
});
|
||||||
// console.log(robotUinRanges?.response?.robotUinRanges);
|
|
||||||
return robotUinRanges?.response?.robotUinRanges;
|
return robotUinRanges?.response?.robotUinRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,24 +127,23 @@ export class NTQQUserApi {
|
|||||||
async getQzoneCookies() {
|
async getQzoneCookies() {
|
||||||
const ClientKeyData = await this.forceFetchClientKey();
|
const ClientKeyData = await this.forceFetchClientKey();
|
||||||
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2Fuser.qzone.qq.com%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
|
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2Fuser.qzone.qq.com%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
|
||||||
const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
|
return await RequestUtil.HttpsGetCookies(requestUrl);
|
||||||
return cookies;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//需要异常处理
|
//需要异常处理
|
||||||
|
|
||||||
async getSkey(): Promise<string | undefined> {
|
async getSKey(): Promise<string | undefined> {
|
||||||
const ClientKeyData = await this.forceFetchClientKey();
|
const ClientKeyData = await this.forceFetchClientKey();
|
||||||
if (ClientKeyData.result !== 0) {
|
if (ClientKeyData.result !== 0) {
|
||||||
throw new Error('getClientKey Error');
|
throw new Error('getClientKey Error');
|
||||||
}
|
}
|
||||||
const clientKey = ClientKeyData.clientKey;
|
const clientKey = ClientKeyData.clientKey;
|
||||||
const keyIndex = ClientKeyData.keyIndex;
|
// const keyIndex = ClientKeyData.keyIndex;
|
||||||
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + '&clientkey=' + clientKey + '&u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=19%27';
|
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + '&clientkey=' + clientKey + '&u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=19%27';
|
||||||
const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
|
const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
|
||||||
const skey = cookies['skey'];
|
const skey = cookies['skey'];
|
||||||
if (!skey) {
|
if (!skey) {
|
||||||
throw new Error('getSkey Skey is Empty');
|
throw new Error('SKey is Empty');
|
||||||
}
|
}
|
||||||
return skey;
|
return skey;
|
||||||
}
|
}
|
||||||
@@ -200,8 +156,8 @@ export class NTQQUserApi {
|
|||||||
if (uid) return uid;
|
if (uid) return uid;
|
||||||
uid = (await this.context.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin);
|
uid = (await this.context.session.getUixConvertService().getUid([Uin])).uidInfo.get(Uin);
|
||||||
if (uid) return uid;
|
if (uid) return uid;
|
||||||
const unveifyUid = (await this.getUserDetailInfoByUinV2(Uin)).detail.uid;//从QQ Native 特殊转换
|
const unverifiedUid = (await this.getUserDetailInfoByUinV2(Uin)).detail.uid;//从QQ Native 特殊转换
|
||||||
if (unveifyUid.indexOf('*') == -1) uid = unveifyUid;
|
if (unverifiedUid.indexOf('*') == -1) uid = unverifiedUid;
|
||||||
//if (uid) return uid;
|
//if (uid) return uid;
|
||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
@@ -237,8 +193,10 @@ export class NTQQUserApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getUserDetailInfoByUinV2(Uin: string) {
|
async getUserDetailInfoByUinV2(Uin: string) {
|
||||||
return await this.core.eventWrapper.callNoListenerEvent<(Uin: string) => Promise<UserDetailInfoByUinV2>>
|
return await this.core.eventWrapper.callNoListenerEvent(
|
||||||
('NodeIKernelProfileService/getUserDetailInfoByUin', 5000, Uin);
|
'NodeIKernelProfileService/getUserDetailInfoByUin',
|
||||||
|
Uin
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async forceFetchClientKey() {
|
async forceFetchClientKey() {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { RequestUtil } from '@/common/utils/request';
|
import { RequestUtil } from '@/common/request';
|
||||||
import {
|
import {
|
||||||
GroupEssenceMsgRet,
|
GroupEssenceMsgRet,
|
||||||
InstanceContext,
|
InstanceContext,
|
||||||
@@ -26,35 +26,42 @@ export class NTQQWebApi {
|
|||||||
msg_seq: msgSeq,
|
msg_seq: msgSeq,
|
||||||
msg_random: msgRandom,
|
msg_random: msgRandom,
|
||||||
target_group_code: targetGroupCode,
|
target_group_code: targetGroupCode,
|
||||||
}).toString()
|
}).toString()}`;
|
||||||
}`;
|
|
||||||
try {
|
try {
|
||||||
return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async getGroupEssenceMsgAll(GroupCode: string) {
|
||||||
async getGroupEssenceMsg(GroupCode: string, page_start: string) {
|
const ret: GroupEssenceMsgRet[] = [];
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
const data = await this.getGroupEssenceMsg(GroupCode, i, 50);
|
||||||
|
if (!data) break;
|
||||||
|
ret.push(data);
|
||||||
|
if (data.data.is_end) break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
async getGroupEssenceMsg(GroupCode: string, page_start: number = 0, page_limit: number = 50) {
|
||||||
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
||||||
const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?${new URLSearchParams({
|
const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?${new URLSearchParams({
|
||||||
bkn: this.getBknFromCookie(cookieObject),
|
bkn: this.getBknFromCookie(cookieObject),
|
||||||
|
page_start: page_start.toString(),
|
||||||
|
page_limit: page_limit.toString(),
|
||||||
group_code: GroupCode,
|
group_code: GroupCode,
|
||||||
page_start,
|
}).toString()}`;
|
||||||
page_limit: '20',
|
|
||||||
}).toString()
|
|
||||||
}`;
|
|
||||||
let ret;
|
|
||||||
try {
|
try {
|
||||||
ret = await RequestUtil.HttpGetJson<GroupEssenceMsgRet>
|
const ret = await RequestUtil.HttpGetJson<GroupEssenceMsgRet>(
|
||||||
(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
url,
|
||||||
|
'GET',
|
||||||
|
'',
|
||||||
|
{ 'Cookie': this.cookieToString(cookieObject) }
|
||||||
|
);
|
||||||
|
return ret.retcode === 0 ? ret : undefined;
|
||||||
} catch {
|
} catch {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (ret.retcode !== 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupMembers(GroupCode: string, cached: boolean = true): Promise<WebApiGroupMember[]> {
|
async getGroupMembers(GroupCode: string, cached: boolean = true): Promise<WebApiGroupMember[]> {
|
||||||
@@ -62,15 +69,18 @@ export class NTQQWebApi {
|
|||||||
const memberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>();
|
const memberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>();
|
||||||
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
||||||
const retList: Promise<WebApiGroupMemberRet>[] = [];
|
const retList: Promise<WebApiGroupMemberRet>[] = [];
|
||||||
const fastRet = await RequestUtil.HttpGetJson<WebApiGroupMemberRet>
|
const fastRet = await RequestUtil.HttpGetJson<WebApiGroupMemberRet>(
|
||||||
(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
|
`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
|
||||||
st: '0',
|
st: '0',
|
||||||
end: '40',
|
end: '40',
|
||||||
sort: '1',
|
sort: '1',
|
||||||
gc: GroupCode,
|
gc: GroupCode,
|
||||||
bkn: this.getBknFromCookie(cookieObject),
|
bkn: this.getBknFromCookie(cookieObject),
|
||||||
}).toString()
|
}).toString()}`,
|
||||||
}`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) });
|
'POST',
|
||||||
|
'',
|
||||||
|
{ 'Cookie': this.cookieToString(cookieObject) }
|
||||||
|
);
|
||||||
if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) {
|
if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) {
|
||||||
return [];
|
return [];
|
||||||
} else {
|
} else {
|
||||||
@@ -82,15 +92,18 @@ export class NTQQWebApi {
|
|||||||
const PageNum = Math.ceil(fastRet.count / 40);
|
const PageNum = Math.ceil(fastRet.count / 40);
|
||||||
//遍历批量请求
|
//遍历批量请求
|
||||||
for (let i = 2; i <= PageNum; i++) {
|
for (let i = 2; i <= PageNum; i++) {
|
||||||
const ret = RequestUtil.HttpGetJson<WebApiGroupMemberRet>
|
const ret = RequestUtil.HttpGetJson<WebApiGroupMemberRet>(
|
||||||
(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
|
`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
|
||||||
st: ((i - 1) * 40).toString(),
|
st: ((i - 1) * 40).toString(),
|
||||||
end: (i * 40).toString(),
|
end: (i * 40).toString(),
|
||||||
sort: '1',
|
sort: '1',
|
||||||
gc: GroupCode,
|
gc: GroupCode,
|
||||||
bkn: this.getBknFromCookie(cookieObject),
|
bkn: this.getBknFromCookie(cookieObject),
|
||||||
}).toString()
|
}).toString()}`,
|
||||||
}`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) });
|
'POST',
|
||||||
|
'',
|
||||||
|
{ 'Cookie': this.cookieToString(cookieObject) }
|
||||||
|
);
|
||||||
retList.push(ret);
|
retList.push(ret);
|
||||||
}
|
}
|
||||||
//批量等待
|
//批量等待
|
||||||
@@ -122,16 +135,19 @@ export class NTQQWebApi {
|
|||||||
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
||||||
let ret: any = undefined;
|
let ret: any = undefined;
|
||||||
try {
|
try {
|
||||||
ret = await RequestUtil.HttpGetJson<any>
|
ret = await RequestUtil.HttpGetJson<any>(
|
||||||
(`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice${new URLSearchParams({
|
`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice${new URLSearchParams({
|
||||||
bkn: this.getBknFromCookie(cookieObject),
|
bkn: this.getBknFromCookie(cookieObject),
|
||||||
qid: GroupCode,
|
qid: GroupCode,
|
||||||
text: Content,
|
text: Content,
|
||||||
pinned: '0',
|
pinned: '0',
|
||||||
type: '1',
|
type: '1',
|
||||||
settings: '{"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}',
|
settings: '{"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}',
|
||||||
}).toString()
|
}).toString()}`,
|
||||||
}`, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
'GET',
|
||||||
|
'',
|
||||||
|
{ 'Cookie': this.cookieToString(cookieObject) }
|
||||||
|
);
|
||||||
return ret;
|
return ret;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -140,16 +156,24 @@ export class NTQQWebApi {
|
|||||||
|
|
||||||
async getGroupNotice(GroupCode: string): Promise<undefined | WebApiGroupNoticeRet> {
|
async getGroupNotice(GroupCode: string): Promise<undefined | WebApiGroupNoticeRet> {
|
||||||
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
||||||
let ret: WebApiGroupNoticeRet | undefined = undefined;
|
|
||||||
try {
|
try {
|
||||||
const url = 'https://web.qun.qq.com/cgi-bin/announce/get_t_list?bkn=' +
|
const ret = await RequestUtil.HttpGetJson<WebApiGroupNoticeRet>(
|
||||||
this.getBknFromCookie(cookieObject) + '&qid=' + GroupCode + '&ft=23&ni=1&n=1&i=1&log_read=1&platform=1&s=-1&n=20';
|
`https://web.qun.qq.com/cgi-bin/announce/get_t_list?${new URLSearchParams({
|
||||||
|
bkn: this.getBknFromCookie(cookieObject),
|
||||||
ret = await RequestUtil.HttpGetJson<WebApiGroupNoticeRet>(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
qid: GroupCode,
|
||||||
if (ret?.ec !== 0) {
|
ft: '23',
|
||||||
return undefined;
|
ni: '1',
|
||||||
}
|
n: '1',
|
||||||
return ret;
|
i: '1',
|
||||||
|
log_read: '1',
|
||||||
|
platform: '1',
|
||||||
|
s: '-1',
|
||||||
|
}).toString()}&n=20`,
|
||||||
|
'GET',
|
||||||
|
'',
|
||||||
|
{ 'Cookie': this.cookieToString(cookieObject) }
|
||||||
|
);
|
||||||
|
return ret?.ec === 0 ? ret : undefined;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -158,15 +182,18 @@ export class NTQQWebApi {
|
|||||||
async getGroupHonorInfo(groupCode: string, getType: WebHonorType) {
|
async getGroupHonorInfo(groupCode: string, getType: WebHonorType) {
|
||||||
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
||||||
const getDataInternal = async (Internal_groupCode: string, Internal_type: number) => {
|
const getDataInternal = async (Internal_groupCode: string, Internal_type: number) => {
|
||||||
const url = `https://qun.qq.com/interactive/honorlist?${new URLSearchParams({
|
|
||||||
gc: Internal_groupCode,
|
|
||||||
type: Internal_type.toString(),
|
|
||||||
}).toString()
|
|
||||||
}`;
|
|
||||||
let resJson;
|
let resJson;
|
||||||
try {
|
try {
|
||||||
const res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
const res = await RequestUtil.HttpGetText(
|
||||||
const match = res.match(/window\.__INITIAL_STATE__=(.*?);/);
|
`https://qun.qq.com/interactive/honorlist?${new URLSearchParams({
|
||||||
|
gc: Internal_groupCode,
|
||||||
|
type: Internal_type.toString(),
|
||||||
|
}).toString()}`,
|
||||||
|
'GET',
|
||||||
|
'',
|
||||||
|
{ 'Cookie': this.cookieToString(cookieObject) }
|
||||||
|
);
|
||||||
|
const match = /window\.__INITIAL_STATE__=(.*?);/.exec(res);
|
||||||
if (match) {
|
if (match) {
|
||||||
resJson = JSON.parse(match[1].trim());
|
resJson = JSON.parse(match[1].trim());
|
||||||
}
|
}
|
||||||
@@ -176,7 +203,7 @@ export class NTQQWebApi {
|
|||||||
return resJson?.actorList;
|
return resJson?.actorList;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.context.logger.logDebug('获取当前群荣耀失败', url, e);
|
this.context.logger.logDebug('获取当前群荣耀失败', e);
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
@@ -184,11 +211,8 @@ export class NTQQWebApi {
|
|||||||
const HonorInfo: any = { group_id: groupCode };
|
const HonorInfo: any = { group_id: groupCode };
|
||||||
|
|
||||||
if (getType === WebHonorType.TALKATIVE || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.TALKATIVE || getType === WebHonorType.ALL) {
|
||||||
try {
|
const RetInternal = await getDataInternal(groupCode, 1);
|
||||||
const RetInternal = await getDataInternal(groupCode, 1);
|
if (RetInternal) {
|
||||||
if (!RetInternal) {
|
|
||||||
throw new Error('获取龙王信息失败');
|
|
||||||
}
|
|
||||||
HonorInfo.current_talkative = {
|
HonorInfo.current_talkative = {
|
||||||
user_id: RetInternal[0]?.uin,
|
user_id: RetInternal[0]?.uin,
|
||||||
avatar: RetInternal[0]?.avatar,
|
avatar: RetInternal[0]?.avatar,
|
||||||
@@ -206,16 +230,13 @@ export class NTQQWebApi {
|
|||||||
nickname: talkative_ele?.name,
|
nickname: talkative_ele?.name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} else {
|
||||||
this.context.logger.logDebug(e);
|
this.context.logger.logError('获取龙王信息失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
||||||
try {
|
const RetInternal = await getDataInternal(groupCode, 2);
|
||||||
const RetInternal = await getDataInternal(groupCode, 2);
|
if (RetInternal) {
|
||||||
if (!RetInternal) {
|
|
||||||
throw new Error('获取群聊之火失败');
|
|
||||||
}
|
|
||||||
HonorInfo.performer_list = [];
|
HonorInfo.performer_list = [];
|
||||||
for (const performer_ele of RetInternal) {
|
for (const performer_ele of RetInternal) {
|
||||||
HonorInfo.performer_list.push({
|
HonorInfo.performer_list.push({
|
||||||
@@ -225,16 +246,13 @@ export class NTQQWebApi {
|
|||||||
description: performer_ele?.desc,
|
description: performer_ele?.desc,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} else {
|
||||||
this.context.logger.logDebug(e);
|
this.context.logger.logError('获取群聊之火失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
||||||
try {
|
const RetInternal = await getDataInternal(groupCode, 3);
|
||||||
const RetInternal = await getDataInternal(groupCode, 3);
|
if (RetInternal) {
|
||||||
if (!RetInternal) {
|
|
||||||
throw new Error('获取群聊炽焰失败');
|
|
||||||
}
|
|
||||||
HonorInfo.legend_list = [];
|
HonorInfo.legend_list = [];
|
||||||
for (const legend_ele of RetInternal) {
|
for (const legend_ele of RetInternal) {
|
||||||
HonorInfo.legend_list.push({
|
HonorInfo.legend_list.push({
|
||||||
@@ -244,16 +262,13 @@ export class NTQQWebApi {
|
|||||||
desc: legend_ele?.description,
|
desc: legend_ele?.description,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} else {
|
||||||
this.context.logger.logDebug('获取群聊炽焰失败', e);
|
this.context.logger.logError('获取群聊炽焰失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
||||||
try {
|
const RetInternal = await getDataInternal(groupCode, 6);
|
||||||
const RetInternal = await getDataInternal(groupCode, 6);
|
if (RetInternal) {
|
||||||
if (!RetInternal) {
|
|
||||||
throw new Error('获取快乐源泉失败');
|
|
||||||
}
|
|
||||||
HonorInfo.emotion_list = [];
|
HonorInfo.emotion_list = [];
|
||||||
for (const emotion_ele of RetInternal) {
|
for (const emotion_ele of RetInternal) {
|
||||||
HonorInfo.emotion_list.push({
|
HonorInfo.emotion_list.push({
|
||||||
@@ -263,14 +278,16 @@ export class NTQQWebApi {
|
|||||||
desc: emotion_ele.description,
|
desc: emotion_ele.description,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} else {
|
||||||
this.context.logger.logDebug('获取快乐源泉失败', e);
|
this.context.logger.logError('获取快乐源泉失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//冒尖小春笋好像已经被tx扬了
|
|
||||||
|
// 冒尖小春笋好像已经被tx扬了 R.I.P.
|
||||||
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
||||||
HonorInfo.strong_newbie_list = [];
|
HonorInfo.strong_newbie_list = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return HonorInfo;
|
return HonorInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
210
src/core/core.ts
210
src/core/core.ts
@@ -1,210 +0,0 @@
|
|||||||
import { NodeQQNTWrapperUtil, NTApiContext, WrapperNodeApi } from '@/core/wrapper';
|
|
||||||
import path from 'node:path';
|
|
||||||
import fs from 'node:fs';
|
|
||||||
import { InstanceContext } from './wrapper';
|
|
||||||
import { proxiedListenerOf } from '@/common/utils/proxy-handler';
|
|
||||||
import { GroupListener, MsgListener, ProfileListener } from './listeners';
|
|
||||||
import { GroupMember, SelfInfo } from './entities';
|
|
||||||
import { LegacyNTEventWrapper } from '@/common/framework/event-legacy';
|
|
||||||
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from './apis';
|
|
||||||
import os from 'node:os';
|
|
||||||
import { NTQQCollectionApi } from './apis/collection';
|
|
||||||
import { NapCatConfigLoader } from './helper/config';
|
|
||||||
import { LogLevel } from '@/common/utils/log';
|
|
||||||
|
|
||||||
export enum NapCatCoreWorkingEnv {
|
|
||||||
Unknown = 0,
|
|
||||||
Shell = 1,
|
|
||||||
Framework = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
|
|
||||||
let wrapperNodePath = path.resolve(path.dirname(process.execPath), './resources/app/wrapper.node');
|
|
||||||
if (!fs.existsSync(wrapperNodePath)) {
|
|
||||||
wrapperNodePath = path.join(path.dirname(process.execPath), `resources/app/versions/${QQVersion}/wrapper.node`);
|
|
||||||
}
|
|
||||||
const nativemodule: any = { exports: {} };
|
|
||||||
process.dlopen(nativemodule, wrapperNodePath);
|
|
||||||
return nativemodule.exports;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NapCatCore {
|
|
||||||
readonly context: InstanceContext;
|
|
||||||
readonly apis: NTApiContext;
|
|
||||||
readonly eventWrapper: LegacyNTEventWrapper;
|
|
||||||
// readonly eventChannel: NTEventChannel;
|
|
||||||
NapCatDataPath: string;
|
|
||||||
NapCatTempPath: string;
|
|
||||||
// runtime info, not readonly
|
|
||||||
selfInfo: SelfInfo;
|
|
||||||
util: NodeQQNTWrapperUtil;
|
|
||||||
configLoader: NapCatConfigLoader;
|
|
||||||
|
|
||||||
// 通过构造器递过去的 runtime info 应该尽量少
|
|
||||||
constructor(context: InstanceContext, selfInfo: SelfInfo) {
|
|
||||||
this.selfInfo = selfInfo;
|
|
||||||
this.context = context;
|
|
||||||
this.util = this.context.wrapper.NodeQQNTWrapperUtil;
|
|
||||||
this.eventWrapper = new LegacyNTEventWrapper(context.session);
|
|
||||||
this.apis = {
|
|
||||||
FileApi: new NTQQFileApi(this.context, this),
|
|
||||||
SystemApi: new NTQQSystemApi(this.context, this),
|
|
||||||
CollectionApi: new NTQQCollectionApi(this.context, this),
|
|
||||||
WebApi: new NTQQWebApi(this.context, this),
|
|
||||||
FriendApi: new NTQQFriendApi(this.context, this),
|
|
||||||
MsgApi: new NTQQMsgApi(this.context, this),
|
|
||||||
UserApi: new NTQQUserApi(this.context, this),
|
|
||||||
GroupApi: new NTQQGroupApi(this.context, this),
|
|
||||||
};
|
|
||||||
this.configLoader = new NapCatConfigLoader(this, this.context.pathWrapper.configPath);
|
|
||||||
this.NapCatDataPath = path.join(this.dataPath, 'NapCat');
|
|
||||||
fs.mkdirSync(this.NapCatDataPath, { recursive: true });
|
|
||||||
this.NapCatTempPath = path.join(this.NapCatDataPath, 'temp');
|
|
||||||
// 创建临时目录
|
|
||||||
if (!fs.existsSync(this.NapCatTempPath)) {
|
|
||||||
fs.mkdirSync(this.NapCatTempPath, { recursive: true });
|
|
||||||
}
|
|
||||||
this.initNapCatCoreListeners().then().catch(this.context.logger.logError);
|
|
||||||
|
|
||||||
this.context.logger.setFileLogEnabled(
|
|
||||||
this.configLoader.configData.fileLog,
|
|
||||||
);
|
|
||||||
this.context.logger.setConsoleLogEnabled(
|
|
||||||
this.configLoader.configData.consoleLog,
|
|
||||||
);
|
|
||||||
this.context.logger.setFileAndConsoleLogLevel(
|
|
||||||
this.configLoader.configData.fileLogLevel as LogLevel,
|
|
||||||
this.configLoader.configData.consoleLogLevel as LogLevel,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
get dataPath(): string {
|
|
||||||
let result = this.context.wrapper.NodeQQNTWrapperUtil.getNTUserDataInfoConfig();
|
|
||||||
if (!result) {
|
|
||||||
result = path.resolve(os.homedir(), './.config/QQ');
|
|
||||||
fs.mkdirSync(result, { recursive: true });
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Renamed from 'InitDataListener'
|
|
||||||
async initNapCatCoreListeners() {
|
|
||||||
const msgListener = new MsgListener();
|
|
||||||
msgListener.onRecvMsg = (msgs) => {
|
|
||||||
msgs.forEach(msg => this.context.logger.logMessage(msg, this.selfInfo));
|
|
||||||
};
|
|
||||||
msgListener.onAddSendMsg = (msg) => {
|
|
||||||
this.context.logger.logMessage(msg, this.selfInfo);
|
|
||||||
};
|
|
||||||
//await sleep(2500);
|
|
||||||
this.context.session.getMsgService().addKernelMsgListener(
|
|
||||||
proxiedListenerOf(msgListener, this.context.logger) as any
|
|
||||||
);
|
|
||||||
|
|
||||||
const profileListener = new ProfileListener();
|
|
||||||
profileListener.onProfileDetailInfoChanged = (profile) => {
|
|
||||||
if (profile.uid === this.selfInfo.uid) {
|
|
||||||
Object.assign(this.selfInfo, profile);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
profileListener.onSelfStatusChanged = (/* Info: SelfStatusInfo */) => {
|
|
||||||
// if (Info.status == 20) {
|
|
||||||
// log("账号状态变更为离线")
|
|
||||||
// }
|
|
||||||
};
|
|
||||||
this.context.session.getProfileService().addKernelProfileListener(
|
|
||||||
proxiedListenerOf(profileListener, this.context.logger),
|
|
||||||
);
|
|
||||||
|
|
||||||
// 群相关
|
|
||||||
const groupListener = new GroupListener();
|
|
||||||
groupListener.onGroupListUpdate = (updateType, groupList) => {
|
|
||||||
// console.log("onGroupListUpdate", updateType, groupList)
|
|
||||||
groupList.map(g => {
|
|
||||||
const existGroup = this.apis.GroupApi.groupCache.get(g.groupCode);
|
|
||||||
//群成员数量变化 应该刷新缓存
|
|
||||||
if (existGroup && g.memberCount === existGroup.memberCount) {
|
|
||||||
Object.assign(existGroup, g);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.apis.GroupApi.groupCache.set(g.groupCode, g);
|
|
||||||
// 获取群成员
|
|
||||||
}
|
|
||||||
const sceneId = this.context.session.getGroupService().createMemberListScene(g.groupCode, 'groupMemberList_MainWindow');
|
|
||||||
this.context.session.getGroupService().getNextMemberList(sceneId!, undefined, 3000).then( /* r => {
|
|
||||||
// console.log(`get group ${g.groupCode} members`, r);
|
|
||||||
// r.result.infos.forEach(member => {
|
|
||||||
// });
|
|
||||||
// groupMembers.set(g.groupCode, r.result.infos);
|
|
||||||
} */);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
groupListener.onMemberListChange = (arg) => {
|
|
||||||
// todo: 应该加一个内部自己维护的成员变动callback,用于判断成员变化通知
|
|
||||||
const groupCode = arg.sceneId.split('_')[0];
|
|
||||||
if (this.apis.GroupApi.groupMemberCache.has(groupCode)) {
|
|
||||||
const existMembers = this.apis.GroupApi.groupMemberCache.get(groupCode)!;
|
|
||||||
arg.infos.forEach((member, uid) => {
|
|
||||||
//console.log('onMemberListChange', member);
|
|
||||||
const existMember = existMembers.get(uid);
|
|
||||||
if (existMember) {
|
|
||||||
Object.assign(existMember, member);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
existMembers!.set(uid, member);
|
|
||||||
}
|
|
||||||
//移除成员
|
|
||||||
if (member.isDelete) {
|
|
||||||
existMembers.delete(uid);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.apis.GroupApi.groupMemberCache.set(groupCode, arg.infos);
|
|
||||||
}
|
|
||||||
// console.log('onMemberListChange', groupCode, arg);
|
|
||||||
};
|
|
||||||
groupListener.onMemberInfoChange = (groupCode, changeType, members) => {
|
|
||||||
//console.log('onMemberInfoChange', groupCode, changeType, members);
|
|
||||||
if (changeType === 0 && members.get(this.selfInfo.uid)?.isDelete) {
|
|
||||||
// 自身退群或者被踢退群 5s用于Api操作 之后不再出现
|
|
||||||
setTimeout(() => {
|
|
||||||
this.apis.GroupApi.groupCache.delete(groupCode);
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
}
|
|
||||||
const existMembers = this.apis.GroupApi.groupMemberCache.get(groupCode);
|
|
||||||
if (existMembers) {
|
|
||||||
members.forEach((member, uid) => {
|
|
||||||
const existMember = existMembers.get(uid);
|
|
||||||
if (existMember) {
|
|
||||||
// 检查管理变动
|
|
||||||
member.isChangeRole = this.checkAdminEvent(groupCode, member, existMember);
|
|
||||||
// 更新成员信息
|
|
||||||
Object.assign(existMember, member);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
existMembers.set(uid, member);
|
|
||||||
}
|
|
||||||
//移除成员
|
|
||||||
if (member.isDelete) {
|
|
||||||
existMembers.delete(uid);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.apis.GroupApi.groupMemberCache.set(groupCode, members);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.context.session.getGroupService().addKernelGroupListener(
|
|
||||||
proxiedListenerOf(groupListener, this.context.logger) as any
|
|
||||||
);
|
|
||||||
}
|
|
||||||
checkAdminEvent(groupCode: string, memberNew: GroupMember, memberOld: GroupMember | undefined): boolean {
|
|
||||||
if (memberNew.role !== memberOld?.role) {
|
|
||||||
this.context.logger.logDebug(`群 ${groupCode} ${memberNew.nick} 角色变更为 ${memberNew.role === 3 ? '管理员' : '群员'}`);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,30 +1,84 @@
|
|||||||
import { QQLevel, Sex, User } from './user';
|
import { QQLevel, Sex } from './user';
|
||||||
|
|
||||||
export interface KickMemberInfo {
|
export interface KickMemberInfo {
|
||||||
optFlag: number,
|
optFlag: number,
|
||||||
optOperate: number,
|
optOperate: number,
|
||||||
optMemberUid: string,
|
optMemberUid: string,
|
||||||
optBytesMsg: string,
|
optBytesMsg: string,
|
||||||
}
|
}
|
||||||
export interface kickMemberV2Req{
|
//getGroupDetailInfo GroupCode,GroupInfoSource
|
||||||
|
export enum GroupInfoSource {
|
||||||
|
KUNSPECIFIED,
|
||||||
|
KBIGDATACARD,
|
||||||
|
KDATACARD,
|
||||||
|
KNOTICE,
|
||||||
|
KAIO,
|
||||||
|
KRECENTCONTACT,
|
||||||
|
KMOREPANEL
|
||||||
|
}
|
||||||
|
export interface GroupExt0xEF0InfoFilter {
|
||||||
|
bindGuildId: number;
|
||||||
|
blacklistExpireTime: number;
|
||||||
|
companyId: number;
|
||||||
|
essentialMsgPrivilege: number;
|
||||||
|
essentialMsgSwitch: number;
|
||||||
|
fullGroupExpansionSeq: number;
|
||||||
|
fullGroupExpansionSwitch: number;
|
||||||
|
gangUpId: number;
|
||||||
|
groupAioBindGuildId: number;
|
||||||
|
groupBindGuildIds: number;
|
||||||
|
groupBindGuildSwitch: number;
|
||||||
|
groupExcludeGuildIds: number;
|
||||||
|
groupExtFlameData: number;
|
||||||
|
groupFlagPro1: number;
|
||||||
|
groupInfoExtSeq: number;
|
||||||
|
groupOwnerId: number;
|
||||||
|
groupSquareSwitch: number;
|
||||||
|
hasGroupCustomPortrait: number;
|
||||||
|
inviteRobotMemberExamine: number;
|
||||||
|
inviteRobotMemberSwitch: number;
|
||||||
|
inviteRobotSwitch: number;
|
||||||
|
isLimitGroupRtc: number;
|
||||||
|
lightCharNum: number;
|
||||||
|
luckyWord: number;
|
||||||
|
luckyWordId: number;
|
||||||
|
msgEventSeq: number;
|
||||||
|
qqMusicMedalSwitch: number;
|
||||||
|
reserve: number;
|
||||||
|
showPlayTogetherSwitch: number;
|
||||||
|
starId: number;
|
||||||
|
todoSeq: number;
|
||||||
|
viewedMsgDisappearTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KickMemberV2Req {
|
||||||
groupCode: string,
|
groupCode: string,
|
||||||
kickFlag: number,
|
kickFlag: number,
|
||||||
kickList: Array<KickMemberInfo>,
|
kickList: Array<KickMemberInfo>,
|
||||||
kickListUids: Array<string>,
|
kickListUids: Array<string>,
|
||||||
kickMsg: string
|
kickMsg: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum DataSource {
|
||||||
|
LOCAL,
|
||||||
|
REMOTE
|
||||||
|
}
|
||||||
|
|
||||||
export enum GroupListUpdateType {
|
export enum GroupListUpdateType {
|
||||||
REFRESHALL,
|
REFRESHALL,
|
||||||
GETALL,
|
GETALL,
|
||||||
MODIFIED,
|
MODIFIED,
|
||||||
REMOVE
|
REMOVE
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupMemberCache {
|
export interface GroupMemberCache {
|
||||||
group: {
|
group: {
|
||||||
data: GroupMember[];
|
data: GroupMember[];
|
||||||
isExpired: boolean;
|
isExpired: boolean;
|
||||||
}
|
};
|
||||||
isExpired: boolean;
|
isExpired: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Group {
|
export interface Group {
|
||||||
groupCode: string,
|
groupCode: string,
|
||||||
createTime?: string,//高版本才有
|
createTime?: string,//高版本才有
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { GroupMemberRole } from './group';
|
import { GroupMemberRole } from '@/core';
|
||||||
|
|
||||||
export interface Peer {
|
export interface Peer {
|
||||||
chatType: ChatType;
|
chatType: ChatType;
|
||||||
@@ -22,6 +22,7 @@ export interface GetFileListParam {
|
|||||||
startIndex: number;
|
startIndex: number;
|
||||||
sortOrder: number;
|
sortOrder: number;
|
||||||
showOnlinedocFolder: number;
|
showOnlinedocFolder: number;
|
||||||
|
folderId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ElementType {
|
export enum ElementType {
|
||||||
@@ -145,6 +146,7 @@ export interface TaskTopMsgElement {
|
|||||||
iconUrl: string;
|
iconUrl: string;
|
||||||
topMsgType: number;
|
topMsgType: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NTMsgType {
|
export enum NTMsgType {
|
||||||
KMSGTYPEARKSTRUCT = 11,
|
KMSGTYPEARKSTRUCT = 11,
|
||||||
KMSGTYPEFACEBUBBLE = 24,
|
KMSGTYPEFACEBUBBLE = 24,
|
||||||
@@ -168,6 +170,7 @@ export enum NTMsgType {
|
|||||||
KMSGTYPEVIDEO = 7,
|
KMSGTYPEVIDEO = 7,
|
||||||
KMSGTYPEWALLET = 10
|
KMSGTYPEWALLET = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SendTaskTopMsgElement {
|
export interface SendTaskTopMsgElement {
|
||||||
elementType: ElementType.TASKTOPMSG;
|
elementType: ElementType.TASKTOPMSG;
|
||||||
elementId: string;
|
elementId: string;
|
||||||
@@ -355,6 +358,7 @@ export enum NTMsgAtType {
|
|||||||
ATTYPESUMMONROLE = 256,
|
ATTYPESUMMONROLE = 256,
|
||||||
ATTYPEUNKNOWN = 0
|
ATTYPEUNKNOWN = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SendPicElement {
|
export interface SendPicElement {
|
||||||
elementType: ElementType.PIC;
|
elementType: ElementType.PIC;
|
||||||
elementId: string;
|
elementId: string;
|
||||||
@@ -366,7 +370,8 @@ export interface ReplyElement {
|
|||||||
replayMsgSeq: string;
|
replayMsgSeq: string;
|
||||||
replayMsgId: string;
|
replayMsgId: string;
|
||||||
senderUin: string;
|
senderUin: string;
|
||||||
senderUinStr: string;
|
senderUidStr?: string;
|
||||||
|
replyMsgTime?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SendReplyElement {
|
export interface SendReplyElement {
|
||||||
@@ -411,7 +416,7 @@ export interface ShareLocationElement {
|
|||||||
ext: string;
|
ext: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface sendShareLocationElement {
|
export interface SendShareLocationElement {
|
||||||
elementType: ElementType.SHARELOCATION;
|
elementType: ElementType.SHARELOCATION;
|
||||||
elementId: string;
|
elementId: string;
|
||||||
shareLocationElement?: ShareLocationElement;
|
shareLocationElement?: ShareLocationElement;
|
||||||
@@ -461,7 +466,7 @@ export interface SendMarkdownElement {
|
|||||||
|
|
||||||
export type SendMessageElement = SendTextElement | SendPttElement |
|
export type SendMessageElement = SendTextElement | SendPttElement |
|
||||||
SendPicElement | SendReplyElement | SendFaceElement | SendMarketFaceElement | SendFileElement |
|
SendPicElement | SendReplyElement | SendFaceElement | SendMarketFaceElement | SendFileElement |
|
||||||
SendVideoElement | SendArkElement | SendMarkdownElement | sendShareLocationElement;
|
SendVideoElement | SendArkElement | SendMarkdownElement | SendShareLocationElement;
|
||||||
|
|
||||||
export interface TextElement {
|
export interface TextElement {
|
||||||
content: string;
|
content: string;
|
||||||
@@ -511,6 +516,7 @@ export enum AtType {
|
|||||||
atAll = 1,
|
atAll = 1,
|
||||||
atUser = 2
|
atUser = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// 来自Android分析
|
// 来自Android分析
|
||||||
export enum ChatType {
|
export enum ChatType {
|
||||||
KCHATTYPEADELIE = 42,
|
KCHATTYPEADELIE = 42,
|
||||||
@@ -589,6 +595,7 @@ export const IMAGE_HTTP_HOST_NT = 'https://multimedia.nt.qq.com.cn';
|
|||||||
|
|
||||||
export interface PicElement {
|
export interface PicElement {
|
||||||
md5HexStr?: string;
|
md5HexStr?: string;
|
||||||
|
filePath?: string;
|
||||||
fileSize: number | string;//number
|
fileSize: number | string;//number
|
||||||
picWidth: number;
|
picWidth: number;
|
||||||
picHeight: number;
|
picHeight: number;
|
||||||
@@ -626,6 +633,7 @@ export enum NTGrayTipElementSubTypeV2 {
|
|||||||
GRAYTIP_ELEMENT_SUBTYPE_WALLET = 16,
|
GRAYTIP_ELEMENT_SUBTYPE_WALLET = 16,
|
||||||
GRAYTIP_ELEMENT_SUBTYPE_XMLMSG = 12,
|
GRAYTIP_ELEMENT_SUBTYPE_XMLMSG = 12,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GrayTipElement {
|
export interface GrayTipElement {
|
||||||
subElementType: NTGrayTipElementSubTypeV2;
|
subElementType: NTGrayTipElementSubTypeV2;
|
||||||
revokeElement: {
|
revokeElement: {
|
||||||
@@ -848,12 +856,14 @@ export interface MultiForwardMsgElement {
|
|||||||
resId: string;
|
resId: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SendStatusType {
|
export enum SendStatusType {
|
||||||
KSEND_STATUS_FAILED = 0,
|
KSEND_STATUS_FAILED = 0,
|
||||||
KSEND_STATUS_SENDING = 1,
|
KSEND_STATUS_SENDING = 1,
|
||||||
KSEND_STATUS_SUCCESS = 2,
|
KSEND_STATUS_SUCCESS = 2,
|
||||||
KSEND_STATUS_SUCCESS_NOSEQ = 3
|
KSEND_STATUS_SUCCESS_NOSEQ = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RawMessage {
|
export interface RawMessage {
|
||||||
parentMsgPeer: Peer;
|
parentMsgPeer: Peer;
|
||||||
|
|
||||||
@@ -923,4 +933,4 @@ export interface RawMessage {
|
|||||||
records: RawMessage[];
|
records: RawMessage[];
|
||||||
|
|
||||||
elements: MessageElement[];
|
elements: MessageElement[];
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ export enum GroupNotifyMsgType {
|
|||||||
TRANSFER_GROUP_NOTIFY_OLDOWNER,
|
TRANSFER_GROUP_NOTIFY_OLDOWNER,
|
||||||
TRANSFER_GROUP_NOTIFY_ADMIN
|
TRANSFER_GROUP_NOTIFY_ADMIN
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupNotifies {
|
export interface GroupNotifies {
|
||||||
doubt: boolean;
|
doubt: boolean;
|
||||||
nextStartSeq: string;
|
nextStartSeq: string;
|
||||||
@@ -29,17 +30,20 @@ export enum GroupNotifyMsgStatus {
|
|||||||
KREFUSED,//拒绝
|
KREFUSED,//拒绝
|
||||||
KIGNORED//忽略
|
KIGNORED//忽略
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum GroupInviteStatus {
|
export enum GroupInviteStatus {
|
||||||
INIT,
|
INIT,
|
||||||
WAIT_TO_APPROVE,
|
WAIT_TO_APPROVE,
|
||||||
JOINED,
|
JOINED,
|
||||||
REFUSED_BY_ADMINI_STRATOR
|
REFUSED_BY_ADMINI_STRATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum GroupInviteType {
|
export enum GroupInviteType {
|
||||||
BYBUDDY,
|
BYBUDDY,
|
||||||
BYGROUPMEMBER,
|
BYGROUPMEMBER,
|
||||||
BYDISCUSSMEMBER
|
BYDISCUSSMEMBER
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupNotify {
|
export interface GroupNotify {
|
||||||
seq: string; // 通知序列号
|
seq: string; // 通知序列号
|
||||||
type: GroupNotifyMsgType;
|
type: GroupNotifyMsgType;
|
||||||
|
@@ -57,7 +57,7 @@ export interface WebApiGroupMemberRet {
|
|||||||
|
|
||||||
export interface WebApiGroupNoticeFeed {
|
export interface WebApiGroupNoticeFeed {
|
||||||
u: number;//发送者
|
u: number;//发送者
|
||||||
fid: string;//fid
|
fid: string;//fid,notice_id
|
||||||
pubt: number;//时间
|
pubt: number;//时间
|
||||||
msg: {
|
msg: {
|
||||||
text: string
|
text: string
|
||||||
|
34
src/core/external/appid.json
vendored
34
src/core/external/appid.json
vendored
@@ -1,30 +1,10 @@
|
|||||||
{
|
{
|
||||||
"3.2.12-27187": {
|
"3.2.12-27597": {
|
||||||
"appid": 537240645,
|
"appid": 537243600,
|
||||||
"qua": "V1_LNX_NQ_3.2.12_27187_GW_B"
|
"qua": "V1_LNX_NQ_3.2.12_27597_GW_B"
|
||||||
},
|
},
|
||||||
"3.2.12-27206": {
|
"9.9.15-27597": {
|
||||||
"appid": 537240645,
|
"appid": 537243441,
|
||||||
"qua": "V1_LNX_NQ_3.2.12_27206_GW_B"
|
"qua": "V1_WIN_NQ_9.9.15_27597_GW_B"
|
||||||
},
|
|
||||||
"3.2.12-27254":{
|
|
||||||
"appid": 537240795,
|
|
||||||
"qua": "V1_LNX_NQ_3.2.12_27254_GW_B"
|
|
||||||
},
|
|
||||||
"9.9.15-27187":{
|
|
||||||
"appid": 537240610,
|
|
||||||
"qua": "V1_WIN_NQ_9.9.15_27187_GW_B"
|
|
||||||
},
|
|
||||||
"9.9.15-27206":{
|
|
||||||
"appid": 537240610,
|
|
||||||
"qua": "V1_WIN_NQ_9.9.15_27206_GW_B"
|
|
||||||
},
|
|
||||||
"9.9.15-27254":{
|
|
||||||
"appid": 537240709,
|
|
||||||
"qua": "V1_WIN_NQ_9.9.15_27254_GW_B"
|
|
||||||
},
|
|
||||||
"9.9.15-27333": {
|
|
||||||
"appid": 537240709,
|
|
||||||
"qua": "V1_WIN_NQ_9.9.15_27333_GW_B"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,11 @@
|
|||||||
import { ConfigBase } from "@/common/utils/ConfigBase";
|
import { ConfigBase } from '@/common/config-base';
|
||||||
import napCatDefaultConfig from '@/core/external/napcat.json';
|
import napCatDefaultConfig from '@/core/external/napcat.json';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
||||||
export type NapCatConfig = typeof napCatDefaultConfig;
|
export type NapCatConfig = typeof napCatDefaultConfig;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
||||||
export class NapCatConfigLoader extends ConfigBase<NapCatConfig> {
|
export class NapCatConfigLoader extends ConfigBase<NapCatConfig> {
|
||||||
constructor(coreContext: NapCatCore, configPath: string) {
|
constructor(core: NapCatCore, configPath: string) {
|
||||||
super('napcat', coreContext, configPath);
|
super('napcat', core, configPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { LogWrapper } from '@/common/utils/log';
|
import { LogWrapper } from '@/common/log';
|
||||||
import { RequestUtil } from '@/common/utils/request';
|
import { RequestUtil } from '@/common/request';
|
||||||
|
|
||||||
interface ServerRkeyData {
|
interface ServerRkeyData {
|
||||||
group_rkey: string;
|
group_rkey: string;
|
||||||
|
@@ -1,5 +1,306 @@
|
|||||||
export * from './core';
|
import {
|
||||||
|
NTQQFileApi,
|
||||||
|
NTQQFriendApi,
|
||||||
|
NTQQGroupApi,
|
||||||
|
NTQQMsgApi,
|
||||||
|
NTQQSystemApi,
|
||||||
|
NTQQUserApi,
|
||||||
|
NTQQWebApi,
|
||||||
|
} from '@/core/apis';
|
||||||
|
import { NTQQCollectionApi } from '@/core/apis/collection';
|
||||||
|
import {
|
||||||
|
NodeIQQNTWrapperSession,
|
||||||
|
NodeQQNTWrapperUtil,
|
||||||
|
PlatformType,
|
||||||
|
VendorType,
|
||||||
|
WrapperNodeApi,
|
||||||
|
WrapperSessionInitConfig,
|
||||||
|
} from '@/core/wrapper';
|
||||||
|
import { LogLevel, LogWrapper } from '@/common/log';
|
||||||
|
import { NodeIKernelLoginService } from '@/core/services';
|
||||||
|
import { QQBasicInfoWrapper } from '@/common/qq-basic-info';
|
||||||
|
import { NapCatPathWrapper } from '@/common/path';
|
||||||
|
import path from 'node:path';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import { getMachineId, hostname, systemName, systemVersion } from '@/common/system';
|
||||||
|
import { NTEventWrapper } from '@/common/event';
|
||||||
|
import { DataSource, GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/entities';
|
||||||
|
import { NapCatConfigLoader } from '@/core/helper/config';
|
||||||
|
import os from 'node:os';
|
||||||
|
import { NodeIKernelGroupListener, NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners';
|
||||||
|
import { proxiedListenerOf } from '@/common/proxy-handler';
|
||||||
|
|
||||||
export * from './wrapper';
|
export * from './wrapper';
|
||||||
export * from './entities';
|
export * from './entities';
|
||||||
export * from './services';
|
export * from './services';
|
||||||
export * from './listeners';
|
export * from './listeners';
|
||||||
|
|
||||||
|
export enum NapCatCoreWorkingEnv {
|
||||||
|
Unknown = 0,
|
||||||
|
Shell = 1,
|
||||||
|
Framework = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
|
||||||
|
let wrapperNodePath = path.resolve(path.dirname(process.execPath), './resources/app/wrapper.node');
|
||||||
|
if (!fs.existsSync(wrapperNodePath)) {
|
||||||
|
wrapperNodePath = path.join(path.dirname(process.execPath), `resources/app/versions/${QQVersion}/wrapper.node`);
|
||||||
|
}
|
||||||
|
const nativemodule: any = { exports: {} };
|
||||||
|
process.dlopen(nativemodule, wrapperNodePath);
|
||||||
|
return nativemodule.exports;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NapCatCore {
|
||||||
|
readonly context: InstanceContext;
|
||||||
|
readonly apis: StableNTApiWrapper;
|
||||||
|
readonly eventWrapper: NTEventWrapper;
|
||||||
|
// readonly eventChannel: NTEventChannel;
|
||||||
|
NapCatDataPath: string;
|
||||||
|
NapCatTempPath: string;
|
||||||
|
// runtime info, not readonly
|
||||||
|
selfInfo: SelfInfo;
|
||||||
|
util: NodeQQNTWrapperUtil;
|
||||||
|
configLoader: NapCatConfigLoader;
|
||||||
|
|
||||||
|
// 通过构造器递过去的 runtime info 应该尽量少
|
||||||
|
constructor(context: InstanceContext, selfInfo: SelfInfo) {
|
||||||
|
this.selfInfo = selfInfo;
|
||||||
|
this.context = context;
|
||||||
|
this.util = this.context.wrapper.NodeQQNTWrapperUtil;
|
||||||
|
this.eventWrapper = new NTEventWrapper(context.session);
|
||||||
|
this.apis = {
|
||||||
|
FileApi: new NTQQFileApi(this.context, this),
|
||||||
|
SystemApi: new NTQQSystemApi(this.context, this),
|
||||||
|
CollectionApi: new NTQQCollectionApi(this.context, this),
|
||||||
|
WebApi: new NTQQWebApi(this.context, this),
|
||||||
|
FriendApi: new NTQQFriendApi(this.context, this),
|
||||||
|
MsgApi: new NTQQMsgApi(this.context, this),
|
||||||
|
UserApi: new NTQQUserApi(this.context, this),
|
||||||
|
GroupApi: new NTQQGroupApi(this.context, this),
|
||||||
|
};
|
||||||
|
this.configLoader = new NapCatConfigLoader(this, this.context.pathWrapper.configPath);
|
||||||
|
this.NapCatDataPath = path.join(this.dataPath, 'NapCat');
|
||||||
|
fs.mkdirSync(this.NapCatDataPath, { recursive: true });
|
||||||
|
this.NapCatTempPath = path.join(this.NapCatDataPath, 'temp');
|
||||||
|
// 创建临时目录
|
||||||
|
if (!fs.existsSync(this.NapCatTempPath)) {
|
||||||
|
fs.mkdirSync(this.NapCatTempPath, { recursive: true });
|
||||||
|
}
|
||||||
|
this.initNapCatCoreListeners().then().catch(this.context.logger.logError);
|
||||||
|
|
||||||
|
this.context.logger.setFileLogEnabled(
|
||||||
|
this.configLoader.configData.fileLog,
|
||||||
|
);
|
||||||
|
this.context.logger.setConsoleLogEnabled(
|
||||||
|
this.configLoader.configData.consoleLog,
|
||||||
|
);
|
||||||
|
this.context.logger.setFileAndConsoleLogLevel(
|
||||||
|
this.configLoader.configData.fileLogLevel as LogLevel,
|
||||||
|
this.configLoader.configData.consoleLogLevel as LogLevel,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get dataPath(): string {
|
||||||
|
let result = this.context.wrapper.NodeQQNTWrapperUtil.getNTUserDataInfoConfig();
|
||||||
|
if (!result) {
|
||||||
|
result = path.resolve(os.homedir(), './.config/QQ');
|
||||||
|
fs.mkdirSync(result, { recursive: true });
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renamed from 'InitDataListener'
|
||||||
|
async initNapCatCoreListeners() {
|
||||||
|
const msgListener = new NodeIKernelMsgListener();
|
||||||
|
msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => {
|
||||||
|
// 下线通知
|
||||||
|
this.context.logger.logError('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc);
|
||||||
|
this.selfInfo.online = false;
|
||||||
|
};
|
||||||
|
msgListener.onRecvMsg = (msgs) => {
|
||||||
|
msgs.forEach(msg => this.context.logger.logMessage(msg, this.selfInfo));
|
||||||
|
};
|
||||||
|
msgListener.onAddSendMsg = (msg) => {
|
||||||
|
this.context.logger.logMessage(msg, this.selfInfo);
|
||||||
|
};
|
||||||
|
//await sleep(2500);
|
||||||
|
this.context.session.getMsgService().addKernelMsgListener(
|
||||||
|
proxiedListenerOf(msgListener, this.context.logger) as any,
|
||||||
|
);
|
||||||
|
|
||||||
|
const profileListener = new NodeIKernelProfileListener();
|
||||||
|
profileListener.onProfileDetailInfoChanged = (profile) => {
|
||||||
|
if (profile.uid === this.selfInfo.uid) {
|
||||||
|
Object.assign(this.selfInfo, profile);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
profileListener.onSelfStatusChanged = (Info: SelfStatusInfo) => {
|
||||||
|
if (Info.status == 20) {
|
||||||
|
this.selfInfo.online = false;
|
||||||
|
this.context.logger.log("账号状态变更为离线");
|
||||||
|
}
|
||||||
|
this.selfInfo.online = true;
|
||||||
|
};
|
||||||
|
this.context.session.getProfileService().addKernelProfileListener(
|
||||||
|
proxiedListenerOf(profileListener, this.context.logger),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 群相关
|
||||||
|
const groupListener = new NodeIKernelGroupListener();
|
||||||
|
groupListener.onGroupListUpdate = (updateType, groupList) => {
|
||||||
|
// console.log("onGroupListUpdate", updateType, groupList)
|
||||||
|
groupList.map(g => {
|
||||||
|
const existGroup = this.apis.GroupApi.groupCache.get(g.groupCode);
|
||||||
|
//群成员数量变化 应该刷新缓存
|
||||||
|
if (existGroup && g.memberCount === existGroup.memberCount) {
|
||||||
|
Object.assign(existGroup, g);
|
||||||
|
} else {
|
||||||
|
this.apis.GroupApi.groupCache.set(g.groupCode, g);
|
||||||
|
// 获取群成员
|
||||||
|
}
|
||||||
|
const sceneId = this.context.session.getGroupService().createMemberListScene(g.groupCode, 'groupMemberList_MainWindow');
|
||||||
|
this.context.session.getGroupService().getNextMemberList(sceneId, undefined, 3000).then( /* r => {
|
||||||
|
// console.log(`get group ${g.groupCode} members`, r);
|
||||||
|
// r.result.infos.forEach(member => {
|
||||||
|
// });
|
||||||
|
// groupMembers.set(g.groupCode, r.result.infos);
|
||||||
|
} */);
|
||||||
|
this.context.session.getGroupService().destroyMemberListScene(sceneId);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
groupListener.onMemberListChange = (arg) => {
|
||||||
|
// todo: 应该加一个内部自己维护的成员变动callback,用于判断成员变化通知
|
||||||
|
const groupCode = arg.sceneId.split('_')[0];
|
||||||
|
if (this.apis.GroupApi.groupMemberCache.has(groupCode)) {
|
||||||
|
const existMembers = this.apis.GroupApi.groupMemberCache.get(groupCode)!;
|
||||||
|
arg.infos.forEach((member, uid) => {
|
||||||
|
//console.log('onMemberListChange', member);
|
||||||
|
const existMember = existMembers.get(uid);
|
||||||
|
if (existMember) {
|
||||||
|
Object.assign(existMember, member);
|
||||||
|
} else {
|
||||||
|
existMembers!.set(uid, member);
|
||||||
|
}
|
||||||
|
//移除成员
|
||||||
|
if (member.isDelete) {
|
||||||
|
existMembers.delete(uid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.apis.GroupApi.groupMemberCache.set(groupCode, arg.infos);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
groupListener.onMemberInfoChange = (groupCode, dataSource, members) => {
|
||||||
|
if (dataSource === DataSource.LOCAL && members.get(this.selfInfo.uid)?.isDelete) {
|
||||||
|
// 自身退群或者被踢退群 5s用于Api操作 之后不再出现
|
||||||
|
setTimeout(() => {
|
||||||
|
this.apis.GroupApi.groupCache.delete(groupCode);
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
}
|
||||||
|
const existMembers = this.apis.GroupApi.groupMemberCache.get(groupCode);
|
||||||
|
if (existMembers) {
|
||||||
|
members.forEach((member, uid) => {
|
||||||
|
const existMember = existMembers.get(uid);
|
||||||
|
if (existMember) {
|
||||||
|
// 检查管理变动
|
||||||
|
member.isChangeRole = this.checkAdminEvent(groupCode, member, existMember);
|
||||||
|
// 更新成员信息
|
||||||
|
Object.assign(existMember, member);
|
||||||
|
} else {
|
||||||
|
existMembers.set(uid, member);
|
||||||
|
}
|
||||||
|
//移除成员
|
||||||
|
if (member.isDelete) {
|
||||||
|
existMembers.delete(uid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.apis.GroupApi.groupMemberCache.set(groupCode, members);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.context.session.getGroupService().addKernelGroupListener(
|
||||||
|
proxiedListenerOf(groupListener, this.context.logger) as any,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkAdminEvent(groupCode: string, memberNew: GroupMember, memberOld: GroupMember | undefined): boolean {
|
||||||
|
if (memberNew.role !== memberOld?.role) {
|
||||||
|
this.context.logger.logDebug(`群 ${groupCode} ${memberNew.nick} 角色变更为 ${memberNew.role === 3 ? '管理员' : '群员'}`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function genSessionConfig(QQVersionAppid: string, QQVersion: string, selfUin: string, selfUid: string, account_path: string): Promise<WrapperSessionInitConfig> {
|
||||||
|
const downloadPath = path.join(account_path, 'NapCat', 'temp');
|
||||||
|
fs.mkdirSync(downloadPath, { recursive: true });
|
||||||
|
const guid: string = await getMachineId();//26702 支持JS获取guid值 在LoginService中获取 TODO mlikiow a
|
||||||
|
return {
|
||||||
|
selfUin,
|
||||||
|
selfUid,
|
||||||
|
desktopPathConfig: {
|
||||||
|
account_path, // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
||||||
|
},
|
||||||
|
clientVer: QQVersion, // 9.9.8-22355
|
||||||
|
a2: '',
|
||||||
|
d2: '',
|
||||||
|
d2Key: '',
|
||||||
|
machineId: '',
|
||||||
|
platform: PlatformType.KWINDOWS, // 3是Windows?
|
||||||
|
platVer: systemVersion, // 系统版本号, 应该可以固定
|
||||||
|
appid: QQVersionAppid,
|
||||||
|
rdeliveryConfig: {
|
||||||
|
appKey: '',
|
||||||
|
systemId: 0,
|
||||||
|
appId: '',
|
||||||
|
logicEnvironment: '',
|
||||||
|
platform: PlatformType.KWINDOWS,
|
||||||
|
language: '',
|
||||||
|
sdkVersion: '',
|
||||||
|
userId: '',
|
||||||
|
appVersion: '',
|
||||||
|
osVersion: '',
|
||||||
|
bundleId: '',
|
||||||
|
serverUrl: '',
|
||||||
|
fixedAfterHitKeys: [''],
|
||||||
|
},
|
||||||
|
defaultFileDownloadPath: downloadPath,
|
||||||
|
deviceInfo: {
|
||||||
|
guid,
|
||||||
|
buildVer: QQVersion,
|
||||||
|
localId: 2052,
|
||||||
|
devName: hostname,
|
||||||
|
devType: systemName,
|
||||||
|
vendorName: '',
|
||||||
|
osVer: systemVersion,
|
||||||
|
vendorOsName: systemName,
|
||||||
|
setMute: false,
|
||||||
|
vendorType: VendorType.KNOSETONIOS,
|
||||||
|
},
|
||||||
|
deviceConfig: '{"appearance":{"isSplitViewMode":true},"msg":{}}',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InstanceContext {
|
||||||
|
readonly workingEnv: NapCatCoreWorkingEnv;
|
||||||
|
readonly wrapper: WrapperNodeApi;
|
||||||
|
readonly session: NodeIQQNTWrapperSession;
|
||||||
|
readonly logger: LogWrapper;
|
||||||
|
readonly loginService: NodeIKernelLoginService;
|
||||||
|
readonly basicInfoWrapper: QQBasicInfoWrapper;
|
||||||
|
readonly pathWrapper: NapCatPathWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StableNTApiWrapper {
|
||||||
|
FileApi: NTQQFileApi,
|
||||||
|
SystemApi: NTQQSystemApi,
|
||||||
|
CollectionApi: NTQQCollectionApi,
|
||||||
|
WebApi: NTQQWebApi,
|
||||||
|
FriendApi: NTQQFriendApi,
|
||||||
|
MsgApi: NTQQMsgApi,
|
||||||
|
UserApi: NTQQUserApi,
|
||||||
|
GroupApi: NTQQGroupApi
|
||||||
|
}
|
||||||
|
@@ -1,53 +1,9 @@
|
|||||||
import { BuddyCategoryType, FriendRequestNotify } from '@/core/entities';
|
import { BuddyCategoryType, FriendRequestNotify } from '@/core/entities';
|
||||||
|
|
||||||
export type OnBuddyChangeParams = BuddyCategoryType[]
|
export type OnBuddyChangeParams = BuddyCategoryType[];
|
||||||
|
|
||||||
interface IBuddyListener {
|
export class NodeIKernelBuddyListener {
|
||||||
onBuddyListChangedV2(arg: unknown): void,//V2版本 还没兼容
|
|
||||||
|
|
||||||
onBuddyListChange(arg: OnBuddyChangeParams): void,
|
|
||||||
|
|
||||||
onBuddyInfoChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onBuddyDetailInfoChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onNickUpdated(arg: unknown): void,
|
|
||||||
|
|
||||||
onBuddyRemarkUpdated(arg: unknown): void,
|
|
||||||
|
|
||||||
onAvatarUrlUpdated(arg: unknown): void,
|
|
||||||
|
|
||||||
onBuddyReqChange(arg: FriendRequestNotify): void,
|
|
||||||
|
|
||||||
onBuddyReqUnreadCntChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onCheckBuddySettingResult(arg: unknown): void,
|
|
||||||
|
|
||||||
onAddBuddyNeedVerify(arg: unknown): void,
|
|
||||||
|
|
||||||
onSmartInfos(arg: unknown): void,
|
|
||||||
|
|
||||||
onSpacePermissionInfos(arg: unknown): void,
|
|
||||||
|
|
||||||
onDoubtBuddyReqChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onDoubtBuddyReqUnreadNumChange(arg: unknown): void,
|
|
||||||
|
|
||||||
onBlockChanged(arg: unknown): void,
|
|
||||||
|
|
||||||
onAddMeSettingChanged(arg: unknown): void,
|
|
||||||
|
|
||||||
onDelBatchBuddyInfos(arg: unknown): void
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelBuddyListener extends IBuddyListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IBuddyListener): NodeIKernelBuddyListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class BuddyListener implements IBuddyListener {
|
|
||||||
onBuddyListChangedV2(arg: unknown): void {
|
onBuddyListChangedV2(arg: unknown): void {
|
||||||
//throw new Error('Method not implemented.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onAddBuddyNeedVerify(arg: unknown) {
|
onAddBuddyNeedVerify(arg: unknown) {
|
||||||
|
@@ -1,22 +1,13 @@
|
|||||||
export interface IKernelFileAssistantListener {
|
export class NodeIKernelFileAssistantListener {
|
||||||
onFileStatusChanged(...args: unknown[]): unknown;
|
onFileStatusChanged(fileStatus: {
|
||||||
|
id: string,
|
||||||
onSessionListChanged(...args: unknown[]): unknown;
|
fileStatus: number,
|
||||||
|
fileProgress: `${number}`,
|
||||||
onSessionChanged(...args: unknown[]): unknown;
|
fileSize: `${number}`,
|
||||||
|
fileSpeed: number,
|
||||||
onFileListChanged(...args: unknown[]): unknown;
|
thumbPath: string | null,
|
||||||
|
filePath: string | null,
|
||||||
onFileSearch(...args: unknown[]): unknown;
|
}) {
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelFileAssistantListener extends IKernelFileAssistantListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IKernelFileAssistantListener): NodeIKernelFileAssistantListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class KernelFileAssistantListener implements IKernelFileAssistantListener {
|
|
||||||
onFileStatusChanged(...args: unknown[]) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSessionListChanged(...args: unknown[]) {
|
onSessionListChanged(...args: unknown[]) {
|
||||||
@@ -28,6 +19,42 @@ export class KernelFileAssistantListener implements IKernelFileAssistantListener
|
|||||||
onFileListChanged(...args: unknown[]) {
|
onFileListChanged(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onFileSearch(...args: unknown[]) {
|
onFileSearch(searchResult: SearchResultWrapper) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SearchResultWrapper = {
|
||||||
|
searchId: number,
|
||||||
|
resultId: number,
|
||||||
|
hasMore: boolean,
|
||||||
|
resultItems: SearchResultItem[],
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SearchResultItem = {
|
||||||
|
id: string,
|
||||||
|
fileName: string,
|
||||||
|
fileNameHits: string[],
|
||||||
|
fileStatus: number,
|
||||||
|
fileSize: string,
|
||||||
|
isSend: boolean,
|
||||||
|
source: number,
|
||||||
|
fileTime: string,
|
||||||
|
expTime: string,
|
||||||
|
session: {
|
||||||
|
context: null,
|
||||||
|
uid: string,
|
||||||
|
nick: string,
|
||||||
|
remark: string,
|
||||||
|
memberCard: string,
|
||||||
|
groupCode: string,
|
||||||
|
groupName: string,
|
||||||
|
groupRemark: string,
|
||||||
|
count: number,
|
||||||
|
},
|
||||||
|
thumbPath: string,
|
||||||
|
filePath: string,
|
||||||
|
msgId: string,
|
||||||
|
chatType: number,
|
||||||
|
peerUid: string,
|
||||||
|
fileType: number,
|
||||||
|
};
|
||||||
|
@@ -1,68 +1,7 @@
|
|||||||
import { Group, GroupListUpdateType, GroupMember, GroupNotify } from '@/core/entities';
|
import { DataSource, Group, GroupListUpdateType, GroupMember, GroupNotify } from '@/core/entities';
|
||||||
|
|
||||||
export interface IGroupListener {
|
export class NodeIKernelGroupListener {
|
||||||
onGroupListUpdate(updateType: GroupListUpdateType, groupList: Group[]): void;
|
onGroupListInited(listEmpty: boolean): void { }
|
||||||
|
|
||||||
onGroupExtListUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]): void;
|
|
||||||
|
|
||||||
onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]): void;
|
|
||||||
|
|
||||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupDetailInfoChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupAllInfoChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupsMsgMaskResult(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupConfMemberChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupBulletinChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGetGroupBulletinListResult(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onMemberListChange(arg: {
|
|
||||||
sceneId: string,
|
|
||||||
ids: string[],
|
|
||||||
infos: Map<string, GroupMember>,
|
|
||||||
finish: boolean,
|
|
||||||
hasRobot: boolean
|
|
||||||
}): void;
|
|
||||||
|
|
||||||
onMemberInfoChange(groupCode: string, changeType: number, members: Map<string, GroupMember>): void;
|
|
||||||
|
|
||||||
onSearchMemberChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupBulletinRichMediaDownloadComplete(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupBulletinRichMediaProgressUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupStatisticInfoChange(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onJoinGroupNotify(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onShutUpMemberListChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupBulletinRemindNotify(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupFirstBulletinNotify(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onJoinGroupNoVerifyFlag(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onGroupArkInviteStateResult(...args: unknown[]): void;
|
|
||||||
|
|
||||||
// 发现于Win 9.9.9 23159
|
|
||||||
onGroupMemberLevelInfoChange(...args: unknown[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelGroupListener extends IGroupListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IGroupListener): NodeIKernelGroupListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GroupListener implements IGroupListener {
|
|
||||||
// 发现于Win 9.9.9 23159
|
// 发现于Win 9.9.9 23159
|
||||||
onGroupMemberLevelInfoChange(...args: unknown[]): void {
|
onGroupMemberLevelInfoChange(...args: unknown[]): void {
|
||||||
|
|
||||||
@@ -125,7 +64,7 @@ export class GroupListener implements IGroupListener {
|
|||||||
onJoinGroupNoVerifyFlag(...args: unknown[]) {
|
onJoinGroupNoVerifyFlag(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onMemberInfoChange(groupCode: string, changeType: number, members: Map<string, GroupMember>) {
|
onMemberInfoChange(groupCode: string, dateSource: DataSource, members: Map<string, GroupMember>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onMemberListChange(arg: {
|
onMemberListChange(arg: {
|
||||||
@@ -142,102 +81,4 @@ export class GroupListener implements IGroupListener {
|
|||||||
|
|
||||||
onShutUpMemberListChanged(...args: unknown[]) {
|
onShutUpMemberListChanged(...args: unknown[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DebugGroupListener implements IGroupListener {
|
|
||||||
onGroupMemberLevelInfoChange(...args: unknown[]): void {
|
|
||||||
console.log('onGroupMemberLevelInfoChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGetGroupBulletinListResult(...args: unknown[]) {
|
|
||||||
console.log('onGetGroupBulletinListResult:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupAllInfoChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupAllInfoChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupBulletinChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupBulletinChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupBulletinRemindNotify(...args: unknown[]) {
|
|
||||||
console.log('onGroupBulletinRemindNotify:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupArkInviteStateResult(...args: unknown[]) {
|
|
||||||
console.log('onGroupArkInviteStateResult:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupBulletinRichMediaDownloadComplete(...args: unknown[]) {
|
|
||||||
console.log('onGroupBulletinRichMediaDownloadComplete:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupConfMemberChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupConfMemberChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupDetailInfoChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupDetailInfoChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupExtListUpdate(...args: unknown[]) {
|
|
||||||
console.log('onGroupExtListUpdate:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupFirstBulletinNotify(...args: unknown[]) {
|
|
||||||
console.log('onGroupFirstBulletinNotify:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupListUpdate(...args: unknown[]) {
|
|
||||||
console.log('onGroupListUpdate:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupNotifiesUpdated(...args: unknown[]) {
|
|
||||||
console.log('onGroupNotifiesUpdated:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupBulletinRichMediaProgressUpdate(...args: unknown[]) {
|
|
||||||
console.log('onGroupBulletinRichMediaProgressUpdate:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]) {
|
|
||||||
console.log('onGroupNotifiesUnreadCountUpdated:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]) {
|
|
||||||
console.log('onGroupSingleScreenNotifies:');
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupsMsgMaskResult(...args: unknown[]) {
|
|
||||||
console.log('onGroupsMsgMaskResult:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGroupStatisticInfoChange(...args: unknown[]) {
|
|
||||||
console.log('onGroupStatisticInfoChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onJoinGroupNotify(...args: unknown[]) {
|
|
||||||
console.log('onJoinGroupNotify:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onJoinGroupNoVerifyFlag(...args: unknown[]) {
|
|
||||||
console.log('onJoinGroupNoVerifyFlag:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMemberInfoChange(groupCode: string, changeType: number, members: Map<string, GroupMember>) {
|
|
||||||
console.log('onMemberInfoChange:', groupCode, changeType, members);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMemberListChange(...args: unknown[]) {
|
|
||||||
console.log('onMemberListChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onSearchMemberChange(...args: unknown[]) {
|
|
||||||
console.log('onSearchMemberChange:', ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
onShutUpMemberListChanged(...args: unknown[]) {
|
|
||||||
console.log('onShutUpMemberListChanged:', ...args);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,45 +1,4 @@
|
|||||||
export interface IKernelLoginListener {
|
export class NodeIKernelLoginListener {
|
||||||
onLoginConnected(...args: any[]): void;
|
|
||||||
|
|
||||||
onLoginDisConnected(...args: any[]): void;
|
|
||||||
|
|
||||||
onLoginConnecting(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeGetPicture(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeLoginPollingStarted(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeSessionUserScaned(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeLoginSucceed(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeSessionFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onLoginFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onLogoutSucceed(...args: any[]): void;
|
|
||||||
|
|
||||||
onLogoutFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onUserLoggedIn(...args: any[]): void;
|
|
||||||
|
|
||||||
onQRCodeSessionQuickLoginFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onPasswordLoginFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
OnConfirmUnusualDeviceFailed(...args: any[]): void;
|
|
||||||
|
|
||||||
onQQLoginNumLimited(...args: any[]): void;
|
|
||||||
|
|
||||||
onLoginState(...args: any[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelLoginListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IKernelLoginListener): NodeIKernelLoginListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LoginListener implements IKernelLoginListener {
|
|
||||||
onLoginConnected(...args: any[]): void {
|
onLoginConnected(...args: any[]): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { ChatType, RawMessage } from '@/core/entities';
|
import { ChatType, RawMessage } from '@/core/entities';
|
||||||
|
import { CommonFileInfo } from '@/core';
|
||||||
|
|
||||||
export interface OnRichMediaDownloadCompleteParams {
|
export interface OnRichMediaDownloadCompleteParams {
|
||||||
fileModelId: string,
|
fileModelId: string,
|
||||||
@@ -15,7 +16,7 @@ export interface OnRichMediaDownloadCompleteParams {
|
|||||||
totalSize: string,
|
totalSize: string,
|
||||||
trasferStatus: number,
|
trasferStatus: number,
|
||||||
step: number,
|
step: number,
|
||||||
commonFileInfo: unknown | null,
|
commonFileInfo?: CommonFileInfo,
|
||||||
fileSrvErrCode: string,
|
fileSrvErrCode: string,
|
||||||
clientMsg: string,
|
clientMsg: string,
|
||||||
businessId: number,
|
businessId: number,
|
||||||
@@ -23,12 +24,52 @@ export interface OnRichMediaDownloadCompleteParams {
|
|||||||
userUsedSpacePerDay: unknown | null
|
userUsedSpacePerDay: unknown | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface onGroupFileInfoUpdateParamType {
|
export interface GroupFileInfoUpdateParamType {
|
||||||
retCode: number;
|
retCode: number;
|
||||||
retMsg: string;
|
retMsg: string;
|
||||||
clientWording: string;
|
clientWording: string;
|
||||||
isEnd: boolean;
|
isEnd: boolean;
|
||||||
item: Array<any>;
|
item: Array<{
|
||||||
|
peerId: string;
|
||||||
|
type: number;
|
||||||
|
folderInfo?: {
|
||||||
|
folderId: string;
|
||||||
|
parentFolderId: string;
|
||||||
|
folderName: string;
|
||||||
|
createTime: number;
|
||||||
|
modifyTime: number;
|
||||||
|
createUin: string;
|
||||||
|
creatorName: string;
|
||||||
|
totalFileCount: number;
|
||||||
|
modifyUin: string;
|
||||||
|
modifyName: string;
|
||||||
|
usedSpace: string;
|
||||||
|
},
|
||||||
|
fileInfo?: {
|
||||||
|
fileModelId: string;
|
||||||
|
fileId: string;
|
||||||
|
fileName: string;
|
||||||
|
fileSize: string;
|
||||||
|
busId: number;
|
||||||
|
uploadedSize: string;
|
||||||
|
uploadTime: number;
|
||||||
|
deadTime: number;
|
||||||
|
modifyTime: number;
|
||||||
|
downloadTimes: number;
|
||||||
|
sha: string;
|
||||||
|
sha3: string;
|
||||||
|
md5: string;
|
||||||
|
uploaderLocalPath: string;
|
||||||
|
uploaderName: string;
|
||||||
|
uploaderUin: string;
|
||||||
|
parentFolderId: string;
|
||||||
|
localPath: string;
|
||||||
|
transStatus: number;
|
||||||
|
transType: number;
|
||||||
|
elementId: string;
|
||||||
|
isFolder: boolean;
|
||||||
|
},
|
||||||
|
}>;
|
||||||
allFileCount: string;
|
allFileCount: string;
|
||||||
nextIndex: string;
|
nextIndex: string;
|
||||||
reqId: string;
|
reqId: string;
|
||||||
@@ -52,199 +93,7 @@ export interface TempOnRecvParams {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IKernelMsgListener {
|
export class NodeIKernelMsgListener {
|
||||||
onAddSendMsg(msgRecord: RawMessage): void;
|
|
||||||
|
|
||||||
onBroadcastHelperDownloadComplete(broadcastHelperTransNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onBroadcastHelperProgressUpdate(broadcastHelperTransNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onChannelFreqLimitInfoUpdate(contact: unknown, z: unknown, freqLimitInfo: unknown): void;
|
|
||||||
|
|
||||||
onContactUnreadCntUpdate(hashMap: unknown): void;
|
|
||||||
|
|
||||||
onCustomWithdrawConfigUpdate(customWithdrawConfig: unknown): void;
|
|
||||||
|
|
||||||
onDraftUpdate(contact: unknown, arrayList: unknown, j2: unknown): void;
|
|
||||||
|
|
||||||
onEmojiDownloadComplete(emojiNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onEmojiResourceUpdate(emojiResourceInfo: unknown): void;
|
|
||||||
|
|
||||||
onFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onFileMsgCome(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onFirstViewDirectMsgUpdate(firstViewDirectMsgNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onFirstViewGroupGuildMapping(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onGrabPasswordRedBag(i2: unknown, str: unknown, i3: unknown, recvdOrder: unknown, msgRecord: unknown): void;
|
|
||||||
|
|
||||||
onGroupFileInfoAdd(groupItem: unknown): void;
|
|
||||||
|
|
||||||
onGroupFileInfoUpdate(groupFileListResult: onGroupFileInfoUpdateParamType): void;
|
|
||||||
|
|
||||||
onGroupGuildUpdate(groupGuildNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onGroupTransferInfoAdd(groupItem: unknown): void;
|
|
||||||
|
|
||||||
onGroupTransferInfoUpdate(groupFileListResult: unknown): void;
|
|
||||||
|
|
||||||
onGuildInteractiveUpdate(guildInteractiveNotificationItem: unknown): void;
|
|
||||||
|
|
||||||
onGuildMsgAbFlagChanged(guildMsgAbFlag: unknown): void;
|
|
||||||
|
|
||||||
onGuildNotificationAbstractUpdate(guildNotificationAbstractInfo: unknown): void;
|
|
||||||
|
|
||||||
onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: unknown): void;
|
|
||||||
|
|
||||||
onHitEmojiKeywordResult(hitRelatedEmojiWordsResult: unknown): void;
|
|
||||||
|
|
||||||
onHitRelatedEmojiResult(relatedWordEmojiInfo: unknown): void;
|
|
||||||
|
|
||||||
onImportOldDbProgressUpdate(importOldDbMsgNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onInputStatusPush(inputStatusInfo: {
|
|
||||||
chatType: number;
|
|
||||||
eventType: number;
|
|
||||||
fromUin: string;
|
|
||||||
interval: string;
|
|
||||||
showTime: string;
|
|
||||||
statusText: string;
|
|
||||||
timestamp: string;
|
|
||||||
toUin: string;
|
|
||||||
}): void;
|
|
||||||
|
|
||||||
onKickedOffLine(kickedInfo: unknown): void;
|
|
||||||
|
|
||||||
onLineDev(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onLogLevelChanged(j2: unknown): void;
|
|
||||||
|
|
||||||
onMsgAbstractUpdate(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onMsgBoxChanged(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onMsgDelete(contact: unknown, arrayList: unknown): void;
|
|
||||||
|
|
||||||
onMsgEventListUpdate(hashMap: unknown): void;
|
|
||||||
|
|
||||||
onMsgInfoListAdd(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onMsgInfoListUpdate(msgList: RawMessage[]): void;
|
|
||||||
|
|
||||||
onMsgQRCodeStatusChanged(i2: unknown): void;
|
|
||||||
|
|
||||||
onMsgRecall(i2: unknown, str: unknown, j2: unknown): void;
|
|
||||||
|
|
||||||
onMsgSecurityNotify(msgRecord: unknown): void;
|
|
||||||
|
|
||||||
onMsgSettingUpdate(msgSetting: unknown): void;
|
|
||||||
|
|
||||||
onNtFirstViewMsgSyncEnd(): void;
|
|
||||||
|
|
||||||
onNtMsgSyncEnd(): void;
|
|
||||||
|
|
||||||
onNtMsgSyncStart(): void;
|
|
||||||
|
|
||||||
onReadFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onRecvGroupGuildFlag(i2: unknown): void;
|
|
||||||
|
|
||||||
onRecvMsg(...arrayList: unknown[]): void;
|
|
||||||
|
|
||||||
onRecvMsgSvrRspTransInfo(j2: unknown, contact: unknown, i2: unknown, i3: unknown, str: unknown, bArr: unknown): void;
|
|
||||||
|
|
||||||
onRecvOnlineFileMsg(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onRecvS2CMsg(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onRecvSysMsg(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onRecvUDCFlag(i2: unknown): void;
|
|
||||||
|
|
||||||
onRichMediaDownloadComplete(fileTransNotifyInfo: OnRichMediaDownloadCompleteParams): void;
|
|
||||||
|
|
||||||
onRichMediaProgerssUpdate(fileTransNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onRichMediaUploadComplete(fileTransNotifyInfo: unknown): void;
|
|
||||||
|
|
||||||
onSearchGroupFileInfoUpdate(searchGroupFileResult:
|
|
||||||
{
|
|
||||||
result: {
|
|
||||||
retCode: number,
|
|
||||||
retMsg: string,
|
|
||||||
clientWording: string
|
|
||||||
},
|
|
||||||
syncCookie: string,
|
|
||||||
totalMatchCount: number,
|
|
||||||
ownerMatchCount: number,
|
|
||||||
isEnd: boolean,
|
|
||||||
reqId: number,
|
|
||||||
item: Array<{
|
|
||||||
groupCode: string,
|
|
||||||
groupName: string,
|
|
||||||
uploaderUin: string,
|
|
||||||
uploaderName: string,
|
|
||||||
matchUin: string,
|
|
||||||
matchWords: Array<unknown>,
|
|
||||||
fileNameHits: Array<{
|
|
||||||
start: number,
|
|
||||||
end: number
|
|
||||||
}>,
|
|
||||||
fileModelId: string,
|
|
||||||
fileId: string,
|
|
||||||
fileName: string,
|
|
||||||
fileSize: string,
|
|
||||||
busId: number,
|
|
||||||
uploadTime: number,
|
|
||||||
modifyTime: number,
|
|
||||||
deadTime: number,
|
|
||||||
downloadTimes: number,
|
|
||||||
localPath: string
|
|
||||||
}>
|
|
||||||
}): void;
|
|
||||||
|
|
||||||
onSendMsgError(j2: unknown, contact: unknown, i2: unknown, str: unknown): void;
|
|
||||||
|
|
||||||
onSysMsgNotification(i2: unknown, j2: unknown, j3: unknown, arrayList: unknown): void;
|
|
||||||
|
|
||||||
onTempChatInfoUpdate(tempChatInfo: TempOnRecvParams): void;
|
|
||||||
|
|
||||||
onUnreadCntAfterFirstView(hashMap: unknown): void;
|
|
||||||
|
|
||||||
onUnreadCntUpdate(hashMap: unknown): void;
|
|
||||||
|
|
||||||
onUserChannelTabStatusChanged(z: unknown): void;
|
|
||||||
|
|
||||||
onUserOnlineStatusChanged(z: unknown): void;
|
|
||||||
|
|
||||||
onUserTabStatusChanged(arrayList: unknown): void;
|
|
||||||
|
|
||||||
onlineStatusBigIconDownloadPush(i2: unknown, j2: unknown, str: unknown): void;
|
|
||||||
|
|
||||||
onlineStatusSmallIconDownloadPush(i2: unknown, j2: unknown, str: unknown): void;
|
|
||||||
|
|
||||||
// 第一次发现于Linux
|
|
||||||
onUserSecQualityChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onMsgWithRichLinkInfoUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onRedTouchChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
// 第一次发现于Win 9.9.9 23159
|
|
||||||
onBroadcastHelperProgerssUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelMsgListener extends IKernelMsgListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IKernelMsgListener): NodeIKernelMsgListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export class MsgListener implements IKernelMsgListener {
|
|
||||||
onAddSendMsg(msgRecord: RawMessage) {
|
onAddSendMsg(msgRecord: RawMessage) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -305,7 +154,7 @@ export class MsgListener implements IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupFileInfoUpdate(groupFileListResult: onGroupFileInfoUpdateParamType) {
|
onGroupFileInfoUpdate(groupFileListResult: GroupFileInfoUpdateParamType) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +300,7 @@ export class MsgListener implements IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onRecvSysMsg(arrayList: unknown) {
|
onRecvSysMsg(arrayList: Array<number>) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,25 +1,6 @@
|
|||||||
import { User, UserDetailInfoListenerArg } from '@/core/entities';
|
import { User, UserDetailInfoListenerArg } from '@/core/entities';
|
||||||
|
|
||||||
interface IProfileListener {
|
export class NodeIKernelProfileListener {
|
||||||
onProfileSimpleChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void;
|
|
||||||
|
|
||||||
onProfileDetailInfoChanged(profile: User): void;
|
|
||||||
|
|
||||||
onStatusUpdate(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onSelfStatusChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onStrangerRemarkChanged(...args: unknown[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelProfileListener extends IProfileListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IProfileListener): NodeIKernelProfileListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ProfileListener implements IProfileListener {
|
|
||||||
onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void {
|
onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,47 +25,47 @@ export class ProfileListener implements IProfileListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMemberListChange(...args: unknown[]){
|
onMemberListChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMemberInfoChange(...args: unknown[]){
|
onMemberInfoChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupListUpdate(...args: unknown[]){
|
onGroupListUpdate(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupAllInfoChange(...args: unknown[]){
|
onGroupAllInfoChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupDetailInfoChange(...args: unknown[]){
|
onGroupDetailInfoChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupConfMemberChange(...args: unknown[]){
|
onGroupConfMemberChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupExtListUpdate(...args: unknown[]){
|
onGroupExtListUpdate(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupNotifiesUpdated(...args: unknown[]){
|
onGroupNotifiesUpdated(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]){
|
onGroupNotifiesUnreadCountUpdated(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupMemberLevelInfoChange(...args: unknown[]){
|
onGroupMemberLevelInfoChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupBulletinChange(...args: unknown[]){
|
onGroupBulletinChange(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,28 +1,9 @@
|
|||||||
interface IKernelRecentContactListener {
|
export class NodeIKernelRecentContactListener {
|
||||||
onDeletedContactsNotify(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onRecentContactNotification(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onMsgUnreadCountUpdate(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onGuildDisplayRecentContactListChanged(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onRecentContactListChanged(...args: unknown[]): unknown;
|
|
||||||
|
|
||||||
onRecentContactListChangedVer2(...args: unknown[]): unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelRecentContactListener extends IKernelRecentContactListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(listener: IKernelRecentContactListener): NodeIKernelRecentContactListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class KernelRecentContactListener implements IKernelRecentContactListener {
|
|
||||||
onDeletedContactsNotify(...args: unknown[]) {
|
onDeletedContactsNotify(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onRecentContactNotification(...args: unknown[]) {
|
onRecentContactNotification(msgList: any, arg0: { msgListUnreadCnt: string }, arg1: number) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,17 +1,4 @@
|
|||||||
export interface IKernelRobotListener {
|
export class NodeIKernelRobotListener {
|
||||||
onRobotFriendListChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onRobotListChanged(...args: unknown[]): void;
|
|
||||||
|
|
||||||
onRobotProfileChanged(...args: unknown[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelRobotListener extends IKernelRobotListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IKernelRobotListener): NodeIKernelRobotListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class KernelRobotListener implements IKernelRobotListener {
|
|
||||||
onRobotFriendListChanged(...args: unknown[]) {
|
onRobotFriendListChanged(...args: unknown[]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
39
src/core/listeners/NodeIKernelSearchListener_Polyfill.ts
Normal file
39
src/core/listeners/NodeIKernelSearchListener_Polyfill.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
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;
|
||||||
|
}
|
@@ -1,23 +1,4 @@
|
|||||||
export interface ISessionListener {
|
export class NodeIKernelSessionListener {
|
||||||
onNTSessionCreate(args: unknown): void;
|
|
||||||
|
|
||||||
onGProSessionCreate(args: unknown): void;
|
|
||||||
|
|
||||||
onSessionInitComplete(args: unknown): void;
|
|
||||||
|
|
||||||
onOpentelemetryInit(args: unknown): void;
|
|
||||||
|
|
||||||
onUserOnlineResult(args: unknown): void;
|
|
||||||
|
|
||||||
onGetSelfTinyId(args: unknown): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelSessionListener extends ISessionListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: ISessionListener): NodeIKernelSessionListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SessionListener implements ISessionListener {
|
|
||||||
onNTSessionCreate(args: unknown) {
|
onNTSessionCreate(args: unknown) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,22 +1,4 @@
|
|||||||
export interface IStorageCleanListener {
|
export class NodeIKernelStorageCleanListener {
|
||||||
onCleanCacheProgressChanged(args: unknown): void;
|
|
||||||
|
|
||||||
onScanCacheProgressChanged(args: unknown): void;
|
|
||||||
|
|
||||||
onCleanCacheStorageChanged(args: unknown): void;
|
|
||||||
|
|
||||||
onFinishScan(args: unknown): void;
|
|
||||||
|
|
||||||
onChatCleanDone(args: unknown): void;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelStorageCleanListener extends IStorageCleanListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IStorageCleanListener): NodeIKernelStorageCleanListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StorageCleanListener implements IStorageCleanListener {
|
|
||||||
onCleanCacheProgressChanged(args: unknown) {
|
onCleanCacheProgressChanged(args: unknown) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,2 @@
|
|||||||
export interface IKernelTicketListener {
|
export class NodeIKernelTicketListener {
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeIKernelTicketListener extends IKernelTicketListener {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
|
||||||
new(adapter: IKernelTicketListener): NodeIKernelTicketListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class KernelTicketListener implements IKernelTicketListener {
|
|
||||||
}
|
}
|
||||||
|
@@ -9,4 +9,32 @@ export * from './NodeIKernelProfileListener';
|
|||||||
export * from './NodeIKernelTicketListener';
|
export * from './NodeIKernelTicketListener';
|
||||||
export * from './NodeIKernelStorageCleanListener';
|
export * from './NodeIKernelStorageCleanListener';
|
||||||
export * from './NodeIKernelFileAssistantListener';
|
export * from './NodeIKernelFileAssistantListener';
|
||||||
|
export * from './NodeIKernelSearchListener_Polyfill';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
NodeIKernelBuddyListener,
|
||||||
|
NodeIKernelFileAssistantListener,
|
||||||
|
NodeIKernelGroupListener,
|
||||||
|
NodeIKernelLoginListener,
|
||||||
|
NodeIKernelMsgListener,
|
||||||
|
NodeIKernelProfileListener,
|
||||||
|
NodeIKernelRobotListener,
|
||||||
|
NodeIKernelSearchListener_Polyfill,
|
||||||
|
NodeIKernelSessionListener,
|
||||||
|
NodeIKernelStorageCleanListener,
|
||||||
|
NodeIKernelTicketListener,
|
||||||
|
} from '.';
|
||||||
|
|
||||||
|
export type ListenerNamingMapping = {
|
||||||
|
NodeIKernelSessionListener: NodeIKernelSessionListener;
|
||||||
|
NodeIKernelLoginListener: NodeIKernelLoginListener;
|
||||||
|
NodeIKernelMsgListener: NodeIKernelMsgListener;
|
||||||
|
NodeIKernelGroupListener: NodeIKernelGroupListener;
|
||||||
|
NodeIKernelBuddyListener: NodeIKernelBuddyListener;
|
||||||
|
NodeIKernelProfileListener: NodeIKernelProfileListener;
|
||||||
|
NodeIKernelRobotListener: NodeIKernelRobotListener;
|
||||||
|
NodeIKernelTicketListener: NodeIKernelTicketListener;
|
||||||
|
NodeIKernelStorageCleanListener: NodeIKernelStorageCleanListener;
|
||||||
|
NodeIKernelFileAssistantListener: NodeIKernelFileAssistantListener;
|
||||||
|
NodeIKernelSearchListener: NodeIKernelSearchListener_Polyfill;
|
||||||
|
};
|
||||||
|
31
src/core/proto/EmojiLikeToOthers.proto
Normal file
31
src/core/proto/EmojiLikeToOthers.proto
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
syntax = 'proto3';
|
||||||
|
package SysMessage;
|
||||||
|
|
||||||
|
message EmojiLikeToOthersWrapper1 {
|
||||||
|
EmojiLikeToOthersWrapper2 wrapper = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EmojiLikeToOthersWrapper2 {
|
||||||
|
EmojiLikeToOthersWrapper3 body = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EmojiLikeToOthersWrapper3 {
|
||||||
|
EmojiLikeToOthersMsgSpec msgSpec = 2;
|
||||||
|
EmojiLikeToOthersAttributes attributes = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EmojiLikeToOthersMsgSpec {
|
||||||
|
uint32 msgSeq = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EmojiLikeToOthersAttributes {
|
||||||
|
enum Operation {
|
||||||
|
FALLBACK = 0;
|
||||||
|
LIKE = 1;
|
||||||
|
UNLIKE = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
string emojiId = 1;
|
||||||
|
string senderUid = 4;
|
||||||
|
Operation operation = 5;
|
||||||
|
}
|
341
src/core/proto/EmojiLikeToOthers.ts
Normal file
341
src/core/proto/EmojiLikeToOthers.ts
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
// @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();
|
9
src/core/proto/GreyTipWrapper.proto
Normal file
9
src/core/proto/GreyTipWrapper.proto
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
syntax = 'proto3';
|
||||||
|
package SysMessage;
|
||||||
|
|
||||||
|
message GreyTipWrapper {
|
||||||
|
uint32 subTypeId = 1;
|
||||||
|
uint32 groupCode = 4;
|
||||||
|
uint32 subTypeIdMinusOne = 13;
|
||||||
|
bytes rest = 44;
|
||||||
|
}
|
104
src/core/proto/GreyTipWrapper.ts
Normal file
104
src/core/proto/GreyTipWrapper.ts
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
// @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();
|
36
src/core/proto/SysMessage.proto
Normal file
36
src/core/proto/SysMessage.proto
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
syntax = 'proto3';
|
||||||
|
package SysMessage;
|
||||||
|
|
||||||
|
message SysMessage {
|
||||||
|
repeated SysMessageHeader header = 1;
|
||||||
|
repeated SysMessageMsgSpec msgSpec = 2;
|
||||||
|
SysMessageBodyWrapper bodyWrapper = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SysMessageHeader {
|
||||||
|
uint32 PeerNumber = 1;
|
||||||
|
string PeerString = 2;
|
||||||
|
uint32 Uin = 5;
|
||||||
|
optional string Uid = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SysMessageMsgSpec {
|
||||||
|
uint32 msgType = 1;
|
||||||
|
uint32 subType = 2;
|
||||||
|
uint32 subSubType = 3;
|
||||||
|
uint32 msgSeq = 5;
|
||||||
|
uint32 time = 6;
|
||||||
|
uint64 msgId = 12;
|
||||||
|
uint32 other = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SysMessageBodyWrapper {
|
||||||
|
bytes wrappedBody = 2;
|
||||||
|
// Find the first [08], or ignore the first 7 bytes?
|
||||||
|
// And it becomes another ProtoBuf message.
|
||||||
|
}
|
||||||
|
|
||||||
|
message KeyValuePair {
|
||||||
|
string key = 1;
|
||||||
|
string value = 2;
|
||||||
|
}
|
435
src/core/proto/SysMessage.ts
Normal file
435
src/core/proto/SysMessage.ts
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
// @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();
|
@@ -1,5 +1,7 @@
|
|||||||
|
import { NodeIKernelFileAssistantListener } from '@/core';
|
||||||
|
|
||||||
export interface NodeIKernelFileAssistantService {
|
export interface NodeIKernelFileAssistantService {
|
||||||
addKernelFileAssistantListener(arg1: unknown[]): unknown;
|
addKernelFileAssistantListener(listener: NodeIKernelFileAssistantListener): unknown;
|
||||||
|
|
||||||
removeKernelFileAssistantListener(arg1: unknown[]): unknown;
|
removeKernelFileAssistantListener(arg1: unknown[]): unknown;
|
||||||
|
|
||||||
@@ -9,7 +11,7 @@ export interface NodeIKernelFileAssistantService {
|
|||||||
|
|
||||||
getFileSessionList(): unknown;
|
getFileSessionList(): unknown;
|
||||||
|
|
||||||
searchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
searchFile(keywords: string[], params: { resultType: number, pageLimit: number }, resultId: number): number;
|
||||||
|
|
||||||
resetSearchFileSortType(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
resetSearchFileSortType(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||||
|
|
||||||
@@ -17,7 +19,7 @@ export interface NodeIKernelFileAssistantService {
|
|||||||
|
|
||||||
cancelSearchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
cancelSearchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||||
|
|
||||||
downloadFile(arg1: unknown[]): unknown;
|
downloadFile(fileIds: string[]): { result: number, errMsg: string };
|
||||||
|
|
||||||
forwardFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
forwardFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||||
|
|
||||||
@@ -32,4 +34,4 @@ export interface NodeIKernelFileAssistantService {
|
|||||||
saveAsWithRename(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
saveAsWithRename(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||||
|
|
||||||
isNull(): boolean;
|
isNull(): boolean;
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +1,24 @@
|
|||||||
import { IGroupListener, NodeIKernelGroupListener } from '@/core/listeners/NodeIKernelGroupListener';
|
import { NodeIKernelGroupListener } from '@/core/listeners/NodeIKernelGroupListener';
|
||||||
import {
|
import {
|
||||||
|
GroupExt0xEF0InfoFilter,
|
||||||
GroupExtParam,
|
GroupExtParam,
|
||||||
|
GroupInfoSource,
|
||||||
GroupMember,
|
GroupMember,
|
||||||
GroupMemberRole,
|
GroupMemberRole,
|
||||||
GroupNotifyMsgType,
|
GroupNotifyMsgType,
|
||||||
GroupRequestOperateTypes,
|
GroupRequestOperateTypes,
|
||||||
kickMemberV2Req,
|
KickMemberV2Req,
|
||||||
} from '@/core/entities';
|
} from '@/core/entities';
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
|
|
||||||
//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底
|
//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底
|
||||||
|
|
||||||
export interface NodeIKernelGroupService {
|
export interface NodeIKernelGroupService {
|
||||||
kickMemberV2(param: kickMemberV2Req): Promise<GeneralCallResult>;
|
getGroupExt0xEF0Info(enableGroupCodes: string[], bannedGroupCodes: string[], filter: GroupExt0xEF0InfoFilter, forceFetch: boolean):
|
||||||
|
Promise<GeneralCallResult & { result: { groupExtInfos: Map<string, any> } }>;
|
||||||
|
|
||||||
|
kickMemberV2(param: KickMemberV2Req): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
quitGroupV2(param: { groupCode: string; needDeleteLocalMsg: boolean; }): Promise<GeneralCallResult>;
|
quitGroupV2(param: { groupCode: string; needDeleteLocalMsg: boolean; }): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
getMemberCommonInfo(Req: {
|
getMemberCommonInfo(Req: {
|
||||||
@@ -34,11 +40,11 @@ export interface NodeIKernelGroupService {
|
|||||||
realSpecialTitleFlag: number
|
realSpecialTitleFlag: number
|
||||||
}): Promise<unknown>;
|
}): Promise<unknown>;
|
||||||
|
|
||||||
//26702
|
|
||||||
getGroupMemberLevelInfo(groupCode: string): Promise<unknown>;
|
getGroupMemberLevelInfo(groupCode: string): Promise<unknown>;
|
||||||
|
|
||||||
//26702
|
getGroupInfoForJoinGroup(groupCode: string, needPrivilegeFlag: boolean, serviceType: number): Promise<unknown>;
|
||||||
getGroupHonorList(groupCodes: Array<string>): unknown;
|
|
||||||
|
getGroupHonorList(req: { groupCodes: Array<string> }): Promise<unknown>;
|
||||||
|
|
||||||
getUinByUids(uins: string[]): Promise<{
|
getUinByUids(uins: string[]): Promise<{
|
||||||
errCode: number,
|
errCode: number,
|
||||||
@@ -52,13 +58,10 @@ export interface NodeIKernelGroupService {
|
|||||||
uids: Map<string, string>
|
uids: Map<string, string>
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
checkGroupMemberCache(arrayList: Array<string>): Promise<unknown>;
|
checkGroupMemberCache(arrayList: Array<string>): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
getGroupLatestEssenceList(groupCode: string): Promise<unknown>;
|
getGroupLatestEssenceList(groupCode: string): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
shareDigest(Req: {
|
shareDigest(Req: {
|
||||||
appId: string,
|
appId: string,
|
||||||
appType: number,
|
appType: number,
|
||||||
@@ -78,20 +81,17 @@ export interface NodeIKernelGroupService {
|
|||||||
}
|
}
|
||||||
}): Promise<unknown>;
|
}): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
fetchGroupEssenceList(Req: {
|
fetchGroupEssenceList(Req: {
|
||||||
groupCode: string,
|
groupCode: string,
|
||||||
pageStart: number,
|
pageStart: number,
|
||||||
pageLimit: number
|
pageLimit: number
|
||||||
}, Arg: unknown): Promise<unknown>;
|
}, Arg: unknown): Promise<unknown>;
|
||||||
|
|
||||||
//26702
|
|
||||||
getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{
|
getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{
|
||||||
errCode: number,
|
errCode: number,
|
||||||
errMsg: string,
|
errMsg: string,
|
||||||
@@ -108,7 +108,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
setHeader(uid: string, path: string): unknown;
|
setHeader(uid: string, path: string): unknown;
|
||||||
|
|
||||||
addKernelGroupListener(listener: IGroupListener): number;
|
addKernelGroupListener(listener: NodeIKernelGroupListener): number;
|
||||||
|
|
||||||
removeKernelGroupListener(listenerId: unknown): void;
|
removeKernelGroupListener(listenerId: unknown): void;
|
||||||
|
|
||||||
@@ -130,8 +130,6 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
getMemberInfo(group_id: string, uids: string[], forceFetch: boolean): Promise<GeneralCallResult>;
|
getMemberInfo(group_id: string, uids: string[], forceFetch: boolean): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
//getMemberInfo [ '56729xxxx', [ 'u_4Nj08cwW5Hxxxxx' ], true ]
|
|
||||||
|
|
||||||
kickMember(groupCode: string, memberUids: string[], refuseForever: boolean, kickReason: string): Promise<void>;
|
kickMember(groupCode: string, memberUids: string[], refuseForever: boolean, kickReason: string): Promise<void>;
|
||||||
|
|
||||||
modifyMemberRole(groupCode: string, uid: string, role: GroupMemberRole): void;
|
modifyMemberRole(groupCode: string, uid: string, role: GroupMemberRole): void;
|
||||||
@@ -146,7 +144,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
getGroupExtList(force: boolean): Promise<GeneralCallResult>;
|
getGroupExtList(force: boolean): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
getGroupDetailInfo(groupCode: string): unknown;
|
getGroupDetailInfo(groupCode: string, groupInfoSource: GroupInfoSource): Promise<unknown>;
|
||||||
|
|
||||||
getMemberExtInfo(param: GroupExtParam): Promise<unknown>;//req
|
getMemberExtInfo(param: GroupExtParam): Promise<unknown>;//req
|
||||||
|
|
||||||
@@ -184,14 +182,13 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
destroyGroup(groupCode: string): void;
|
destroyGroup(groupCode: string): void;
|
||||||
|
|
||||||
//获取单屏群通知列表
|
getSingleScreenNotifies(doubted: boolean, start_seq: string, num: number): Promise<GeneralCallResult>;
|
||||||
getSingleScreenNotifies(force: boolean, start_seq: string, num: number): Promise<GeneralCallResult>;
|
|
||||||
|
|
||||||
clearGroupNotifies(groupCode: string): void;
|
clearGroupNotifies(groupCode: string): void;
|
||||||
|
|
||||||
getGroupNotifiesUnreadCount(unknown: boolean): Promise<GeneralCallResult>;
|
getGroupNotifiesUnreadCount(unknown: boolean): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
clearGroupNotifiesUnreadCount(groupCode: string): void;
|
clearGroupNotifiesUnreadCount(unknown: boolean): void;
|
||||||
|
|
||||||
operateSysNotify(
|
operateSysNotify(
|
||||||
doubt: boolean,
|
doubt: boolean,
|
||||||
@@ -209,7 +206,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
getGroupBulletin(groupCode: string): unknown;
|
getGroupBulletin(groupCode: string): unknown;
|
||||||
|
|
||||||
deleteGroupBulletin(groupCode: string, seq: string, feedId: string): void;
|
deleteGroupBulletin(groupCode: string, seq: string, noticeId: string): void;
|
||||||
|
|
||||||
publishGroupBulletin(groupCode: string, pskey: string, data: any): Promise<GeneralCallResult>;
|
publishGroupBulletin(groupCode: string, pskey: string, data: any): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ export interface LoginInitConfig {
|
|||||||
hostName: string;
|
hostName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface passwordLoginRetType {
|
export interface PasswordLoginRetType {
|
||||||
result: string,
|
result: string,
|
||||||
loginErrorInfo: {
|
loginErrorInfo: {
|
||||||
step: number;
|
step: number;
|
||||||
@@ -23,7 +23,7 @@ export interface passwordLoginRetType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface passwordLoginArgType {
|
export interface PasswordLoginArgType {
|
||||||
uin: string;
|
uin: string;
|
||||||
passwordMd5: string;//passwMD5
|
passwordMd5: string;//passwMD5
|
||||||
step: number;//猜测是需要二次认证 参数 一次为0
|
step: number;//猜测是需要二次认证 参数 一次为0
|
||||||
@@ -77,7 +77,7 @@ export interface NodeIKernelLoginService {
|
|||||||
|
|
||||||
quickLoginWithUin(uin: string): Promise<QuickLoginResult>;
|
quickLoginWithUin(uin: string): Promise<QuickLoginResult>;
|
||||||
|
|
||||||
passwordLogin(param: passwordLoginArgType): Promise<any>;
|
passwordLogin(param: PasswordLoginArgType): Promise<any>;
|
||||||
|
|
||||||
getQRCodePicture(): boolean;
|
getQRCodePicture(): boolean;
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@ export interface QueryMsgsParams {
|
|||||||
isReverseOrder: boolean,
|
isReverseOrder: boolean,
|
||||||
isIncludeCurrent: boolean
|
isIncludeCurrent: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TmpChatInfoApi {
|
export interface TmpChatInfoApi {
|
||||||
errMsg: string;
|
errMsg: string;
|
||||||
result: number;
|
result: number;
|
||||||
@@ -166,11 +167,17 @@ export interface NodeIKernelMsgService {
|
|||||||
|
|
||||||
getAllOnlineFileMsgs(...args: unknown[]): unknown;
|
getAllOnlineFileMsgs(...args: unknown[]): unknown;
|
||||||
|
|
||||||
getLatestDbMsgs(peer: Peer, cnt: number): Promise<unknown>;
|
getLatestDbMsgs(peer: Peer, cnt: number): Promise<GeneralCallResult & {
|
||||||
|
msgList: RawMessage[]
|
||||||
|
}>;
|
||||||
|
|
||||||
getLastMessageList(peer: Peer[]): Promise<unknown>;
|
getLastMessageList(peer: Peer[]): Promise<GeneralCallResult & {
|
||||||
|
msgList: RawMessage[]
|
||||||
|
}>;
|
||||||
|
|
||||||
getAioFirstViewLatestMsgs(peer: Peer, num: number): unknown;
|
getAioFirstViewLatestMsgs(peer: Peer, num: number): Promise<GeneralCallResult & {
|
||||||
|
msgList: RawMessage[]
|
||||||
|
}>;
|
||||||
|
|
||||||
getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise<unknown>;
|
getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise<unknown>;
|
||||||
|
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { AnyCnameRecord } from 'node:dns';
|
import { AnyCnameRecord } from 'node:dns';
|
||||||
import { BizKey, ModifyProfileParams, SimpleInfo, UserDetailInfoByUin } from '../entities';
|
import { BizKey, ModifyProfileParams, NodeIKernelProfileListener, SimpleInfo, UserDetailInfoByUinV2 } from '@/core';
|
||||||
import { NodeIKernelProfileListener, ProfileListener } from '../listeners';
|
|
||||||
import { GeneralCallResult } from '@/core/services/common';
|
import { GeneralCallResult } from '@/core/services/common';
|
||||||
|
|
||||||
export enum UserDetailSource {
|
export enum UserDetailSource {
|
||||||
@@ -35,7 +34,7 @@ export interface NodeIKernelProfileService {
|
|||||||
|
|
||||||
fetchUserDetailInfo(trace: string, uids: string[], arg2: number, arg3: number[]): Promise<unknown>;
|
fetchUserDetailInfo(trace: string, uids: string[], arg2: number, arg3: number[]): Promise<unknown>;
|
||||||
|
|
||||||
addKernelProfileListener(listener: ProfileListener): number;
|
addKernelProfileListener(listener: NodeIKernelProfileListener): number;
|
||||||
|
|
||||||
removeKernelProfileListener(listenerId: number): void;
|
removeKernelProfileListener(listenerId: number): void;
|
||||||
|
|
||||||
@@ -86,7 +85,7 @@ export interface NodeIKernelProfileService {
|
|||||||
|
|
||||||
getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise<GeneralCallResult>;
|
getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUin>;
|
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUinV2>;
|
||||||
|
|
||||||
getZplanAvatarInfos(args: string[]): Promise<unknown>;
|
getZplanAvatarInfos(args: string[]): Promise<unknown>;
|
||||||
|
|
||||||
|
@@ -155,7 +155,7 @@ export interface NodeIKernelRichMediaService {
|
|||||||
}): unknown;
|
}): unknown;
|
||||||
|
|
||||||
//arg3为“”
|
//arg3为“”
|
||||||
downloadFileForModelId(peer: Peer, ModelId: string[], arg3: string): unknown;
|
downloadFileForModelId(peer: Peer, ModelId: string[], unknown: string): Promise<unknown>;
|
||||||
|
|
||||||
//第三个参数 Array<Type>
|
//第三个参数 Array<Type>
|
||||||
// this.fileId = "";
|
// this.fileId = "";
|
||||||
|
@@ -14,3 +14,45 @@ export * from './NodeIKernelRobotService';
|
|||||||
export * from './NodeIKernelRichMediaService';
|
export * from './NodeIKernelRichMediaService';
|
||||||
export * from './NodeIKernelDbToolsService';
|
export * from './NodeIKernelDbToolsService';
|
||||||
export * from './NodeIKernelTipOffService';
|
export * from './NodeIKernelTipOffService';
|
||||||
|
export * from './NodeIKernelSearchService';
|
||||||
|
export * from './NodeIKernelCollectionService';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
NodeIKernelAvatarService,
|
||||||
|
NodeIKernelBuddyService,
|
||||||
|
NodeIKernelCollectionService,
|
||||||
|
NodeIKernelDbToolsService,
|
||||||
|
NodeIKernelFileAssistantService,
|
||||||
|
NodeIKernelGroupService,
|
||||||
|
NodeIKernelLoginService,
|
||||||
|
NodeIKernelMsgService,
|
||||||
|
NodeIKernelOnlineStatusService,
|
||||||
|
NodeIKernelProfileLikeService,
|
||||||
|
NodeIKernelProfileService,
|
||||||
|
NodeIKernelRichMediaService,
|
||||||
|
NodeIKernelRobotService,
|
||||||
|
NodeIKernelSearchService,
|
||||||
|
NodeIKernelStorageCleanService,
|
||||||
|
NodeIKernelTicketService,
|
||||||
|
NodeIKernelTipOffService,
|
||||||
|
} from '.';
|
||||||
|
|
||||||
|
export type ServiceNamingMapping = {
|
||||||
|
NodeIKernelAvatarService: NodeIKernelAvatarService;
|
||||||
|
NodeIKernelBuddyService: NodeIKernelBuddyService;
|
||||||
|
NodeIKernelFileAssistantService: NodeIKernelFileAssistantService;
|
||||||
|
NodeIKernelGroupService: NodeIKernelGroupService;
|
||||||
|
NodeIKernelLoginService: NodeIKernelLoginService;
|
||||||
|
NodeIKernelMsgService: NodeIKernelMsgService;
|
||||||
|
NodeIKernelOnlineStatusService: NodeIKernelOnlineStatusService;
|
||||||
|
NodeIKernelProfileLikeService: NodeIKernelProfileLikeService;
|
||||||
|
NodeIKernelProfileService: NodeIKernelProfileService;
|
||||||
|
NodeIKernelTicketService: NodeIKernelTicketService;
|
||||||
|
NodeIKernelStorageCleanService: NodeIKernelStorageCleanService;
|
||||||
|
NodeIKernelRobotService: NodeIKernelRobotService;
|
||||||
|
NodeIKernelRichMediaService: NodeIKernelRichMediaService;
|
||||||
|
NodeIKernelDbToolsService: NodeIKernelDbToolsService;
|
||||||
|
NodeIKernelTipOffService: NodeIKernelTipOffService;
|
||||||
|
NodeIKernelSearchService: NodeIKernelSearchService,
|
||||||
|
NodeIKernelCollectionService: NodeIKernelCollectionService;
|
||||||
|
};
|
||||||
|
@@ -1,12 +1,4 @@
|
|||||||
import { NodeIDependsAdapter, NodeIDispatcherAdapter, NodeIGlobalAdapter } from '../adapters';
|
import { NodeIDependsAdapter, NodeIDispatcherAdapter, NodeIGlobalAdapter } from './adapters';
|
||||||
import {
|
|
||||||
NodeIKernelBuddyListener,
|
|
||||||
NodeIKernelGroupListener,
|
|
||||||
NodeIKernelLoginListener,
|
|
||||||
NodeIKernelMsgListener,
|
|
||||||
NodeIKernelProfileListener,
|
|
||||||
NodeIKernelSessionListener,
|
|
||||||
} from '../listeners';
|
|
||||||
import {
|
import {
|
||||||
NodeIKernelAvatarService,
|
NodeIKernelAvatarService,
|
||||||
NodeIKernelBuddyService,
|
NodeIKernelBuddyService,
|
||||||
@@ -16,26 +8,28 @@ import {
|
|||||||
NodeIKernelProfileLikeService,
|
NodeIKernelProfileLikeService,
|
||||||
NodeIKernelProfileService,
|
NodeIKernelProfileService,
|
||||||
NodeIKernelRichMediaService,
|
NodeIKernelRichMediaService,
|
||||||
|
NodeIKernelRobotService,
|
||||||
|
NodeIKernelSessionListener,
|
||||||
|
NodeIKernelStorageCleanService,
|
||||||
NodeIKernelTicketService,
|
NodeIKernelTicketService,
|
||||||
NodeIKernelTipOffService,
|
NodeIKernelTipOffService,
|
||||||
} from '../services';
|
} from '@/core/index';
|
||||||
import { NodeIKernelStorageCleanService } from '../services/NodeIKernelStorageCleanService';
|
import { NodeIKernelNodeMiscService } from './services/NodeIKernelNodeMiscService';
|
||||||
import { NodeIKernelRobotService } from '../services/NodeIKernelRobotService';
|
import { NodeIKernelUixConvertService } from './services/NodeIKernelUixConvertService';
|
||||||
import { NodeIKernelNodeMiscService } from '../services/NodeIKernelNodeMiscService';
|
import { NodeIKernelMsgBackupService } from './services/NodeIKernelMsgBackupService';
|
||||||
import { NodeIKernelUixConvertService } from '../services/NodeIKernelUixConvertService';
|
import { NodeIKernelAlbumService } from './services/NodeIKernelAlbumService';
|
||||||
import { NodeIKernelMsgBackupService } from '../services/NodeIKernelMsgBackupService';
|
import { NodeIKernelTianShuService } from './services/NodeIKernelTianShuService';
|
||||||
import { NodeIKernelAlbumService } from '../services/NodeIKernelAlbumService';
|
import { NodeIKernelUnitedConfigService } from './services/NodeIKernelUnitedConfigService';
|
||||||
import { NodeIKernelTianShuService } from '../services/NodeIKernelTianShuService';
|
import { NodeIKernelSearchService } from './services/NodeIKernelSearchService';
|
||||||
import { NodeIKernelUnitedConfigService } from '../services/NodeIKernelUnitedConfigService';
|
import { NodeIKernelCollectionService } from './services/NodeIKernelCollectionService';
|
||||||
import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService';
|
import { NodeIKernelRecentContactService } from './services/NodeIKernelRecentContactService';
|
||||||
import { NodeIKernelCollectionService } from '../services/NodeIKernelCollectionService';
|
import { NodeIKernelMSFService } from './services/NodeIKernelMSFService';
|
||||||
import { NodeIKernelRecentContactService } from '../services/NodeIKernelRecentContactService';
|
import { NodeIkernelTestPerformanceService } from './services/NodeIkernelTestPerformanceService';
|
||||||
import { NodeIKernelMSFService } from '../services/NodeIKernelMSFService';
|
import { NodeIKernelECDHService } from './services/NodeIKernelECDHService';
|
||||||
import { NodeIkernelTestPerformanceService } from '../services/NodeIkernelTestPerformanceService';
|
|
||||||
import { NodeIKernelECDHService } from '../services/NodeIKernelECDHService';
|
|
||||||
|
|
||||||
export interface NodeQQNTWrapperUtil {
|
export interface NodeQQNTWrapperUtil {
|
||||||
get(): unknown;
|
get(): unknown;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||||
new(): NodeQQNTWrapperUtil;
|
new(): NodeQQNTWrapperUtil;
|
||||||
|
|
||||||
@@ -278,20 +272,11 @@ export interface NodeIQQNTWrapperEngine {
|
|||||||
export interface WrapperNodeApi {
|
export interface WrapperNodeApi {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
|
||||||
NodeIKernelBuddyListener: NodeIKernelBuddyListener;
|
|
||||||
NodeIKernelGroupListener: NodeIKernelGroupListener;
|
|
||||||
NodeQQNTWrapperUtil: NodeQQNTWrapperUtil;
|
NodeQQNTWrapperUtil: NodeQQNTWrapperUtil;
|
||||||
NodeIQQNTWrapperSession: NodeIQQNTWrapperSession;
|
NodeIQQNTWrapperSession: NodeIQQNTWrapperSession;
|
||||||
NodeIKernelMsgListener: NodeIKernelMsgListener;
|
|
||||||
NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine;
|
NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine;
|
||||||
NodeIGlobalAdapter: NodeIGlobalAdapter;
|
|
||||||
NodeIDependsAdapter: NodeIDependsAdapter;
|
|
||||||
NodeIDispatcherAdapter: NodeIDispatcherAdapter;
|
|
||||||
NodeIKernelSessionListener: NodeIKernelSessionListener;
|
|
||||||
NodeIKernelLoginService: NodeIKernelLoginService;
|
NodeIKernelLoginService: NodeIKernelLoginService;
|
||||||
NodeIKernelLoginListener: NodeIKernelLoginListener;
|
|
||||||
NodeIKernelProfileService: NodeIKernelProfileService;
|
NodeIKernelProfileService: NodeIKernelProfileService;
|
||||||
NodeIKernelProfileListener: NodeIKernelProfileListener;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PlatformType {
|
export enum PlatformType {
|
@@ -1,27 +0,0 @@
|
|||||||
import { LogWrapper } from '@/common/utils/log';
|
|
||||||
import { QQBasicInfoWrapper } from '@/common/utils/QQBasicInfo';
|
|
||||||
import { NapCatCoreWorkingEnv, NodeIKernelLoginService, NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core';
|
|
||||||
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from '../apis';
|
|
||||||
import { NTQQCollectionApi } from '../apis/collection';
|
|
||||||
import { NapCatPathWrapper } from '@/common/framework/napcat';
|
|
||||||
|
|
||||||
export interface InstanceContext {
|
|
||||||
readonly workingEnv: NapCatCoreWorkingEnv;
|
|
||||||
readonly wrapper: WrapperNodeApi;
|
|
||||||
readonly session: NodeIQQNTWrapperSession;
|
|
||||||
readonly logger: LogWrapper;
|
|
||||||
readonly loginService: NodeIKernelLoginService;
|
|
||||||
readonly basicInfoWrapper: QQBasicInfoWrapper;
|
|
||||||
readonly pathWrapper: NapCatPathWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NTApiContext {
|
|
||||||
FileApi: NTQQFileApi,
|
|
||||||
SystemApi: NTQQSystemApi,
|
|
||||||
CollectionApi: NTQQCollectionApi,
|
|
||||||
WebApi: NTQQWebApi,
|
|
||||||
FriendApi: NTQQFriendApi,
|
|
||||||
MsgApi: NTQQMsgApi,
|
|
||||||
UserApi: NTQQUserApi,
|
|
||||||
GroupApi: NTQQGroupApi
|
|
||||||
}
|
|
@@ -1,55 +0,0 @@
|
|||||||
import path from 'node:path';
|
|
||||||
import fs from 'node:fs';
|
|
||||||
import { PlatformType, VendorType, WrapperSessionInitConfig } from './wrapper';
|
|
||||||
import { getMachineId, hostname, systemName, systemVersion } from '@/common/utils/system';
|
|
||||||
|
|
||||||
export async function genSessionConfig(QQVersionAppid: string, QQVersion: string, selfUin: string, selfUid: string, account_path: string): Promise<WrapperSessionInitConfig> {
|
|
||||||
const downloadPath = path.join(account_path, 'NapCat', 'temp');
|
|
||||||
fs.mkdirSync(downloadPath, { recursive: true });
|
|
||||||
const guid: string = await getMachineId();//26702 支持JS获取guid值 在LoginService中获取 TODO mlikiow a
|
|
||||||
const config: WrapperSessionInitConfig = {
|
|
||||||
selfUin,
|
|
||||||
selfUid,
|
|
||||||
desktopPathConfig: {
|
|
||||||
account_path, // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
|
||||||
},
|
|
||||||
clientVer: QQVersion, // 9.9.8-22355
|
|
||||||
a2: '',
|
|
||||||
d2: '',
|
|
||||||
d2Key: '',
|
|
||||||
machineId: '',
|
|
||||||
platform: PlatformType.KWINDOWS, // 3是Windows?
|
|
||||||
platVer: systemVersion, // 系统版本号, 应该可以固定
|
|
||||||
appid: QQVersionAppid,
|
|
||||||
rdeliveryConfig: {
|
|
||||||
appKey: '',
|
|
||||||
systemId: 0,
|
|
||||||
appId: '',
|
|
||||||
logicEnvironment: '',
|
|
||||||
platform: PlatformType.KWINDOWS,
|
|
||||||
language: '',
|
|
||||||
sdkVersion: '',
|
|
||||||
userId: '',
|
|
||||||
appVersion: '',
|
|
||||||
osVersion: '',
|
|
||||||
bundleId: '',
|
|
||||||
serverUrl: '',
|
|
||||||
fixedAfterHitKeys: [''],
|
|
||||||
},
|
|
||||||
defaultFileDownloadPath: downloadPath,
|
|
||||||
deviceInfo: {
|
|
||||||
guid,
|
|
||||||
buildVer: QQVersion,
|
|
||||||
localId: 2052,
|
|
||||||
devName: hostname,
|
|
||||||
devType: systemName,
|
|
||||||
vendorName: '',
|
|
||||||
osVer: systemVersion,
|
|
||||||
vendorOsName: systemName,
|
|
||||||
setMute: false,
|
|
||||||
vendorType: VendorType.KNOSETONIOS,
|
|
||||||
},
|
|
||||||
deviceConfig: '{"appearance":{"isSplitViewMode":true},"msg":{}}',
|
|
||||||
};
|
|
||||||
return config;
|
|
||||||
}
|
|
@@ -1,3 +0,0 @@
|
|||||||
export * from './wrapper';
|
|
||||||
export * from './helper';
|
|
||||||
export * from './context';
|
|
@@ -1,6 +1,6 @@
|
|||||||
//LiteLoader需要提供部分IPC接口,以便于其他插件调用
|
//LiteLoader需要提供部分IPC接口,以便于其他插件调用
|
||||||
const { ipcMain } = require('electron');
|
const { ipcMain } = require('electron');
|
||||||
const napcat= require('./napcat.cjs');
|
const napcat = require('./napcat.cjs');
|
||||||
ipcMain.handle("napcat_get_webtoken", async (event, arg) => {
|
ipcMain.handle('napcat_get_webtoken', async (event, arg) => {
|
||||||
return napcat.NCgetWebUiUrl();
|
return napcat.NCgetWebUiUrl();
|
||||||
});
|
});
|
||||||
|
@@ -1,21 +1,21 @@
|
|||||||
import { NapCatPathWrapper } from '@/common/framework/napcat';
|
import { NapCatPathWrapper } from '@/common/path';
|
||||||
import { LogWrapper } from '@/common/utils/log';
|
import { LogWrapper } from '@/common/log';
|
||||||
import { proxiedListenerOf } from '@/common/utils/proxy-handler';
|
import { proxiedListenerOf } from '@/common/proxy-handler';
|
||||||
import { QQBasicInfoWrapper } from '@/common/utils/QQBasicInfo';
|
import { QQBasicInfoWrapper } from '@/common/qq-basic-info';
|
||||||
import { loadQQWrapper, NapCatCore, NapCatCoreWorkingEnv } from '@/core/core';
|
import { InstanceContext, loadQQWrapper, NapCatCore, NapCatCoreWorkingEnv } from '@/core';
|
||||||
import { InstanceContext } from '@/core';
|
|
||||||
import { SelfInfo } from '@/core/entities';
|
import { SelfInfo } from '@/core/entities';
|
||||||
import { LoginListener } from '@/core/listeners';
|
import { NodeIKernelLoginListener } from '@/core/listeners';
|
||||||
import { NodeIKernelLoginService } from '@/core/services';
|
import { NodeIKernelLoginService } from '@/core/services';
|
||||||
import { NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core/wrapper/wrapper';
|
import { NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core/wrapper';
|
||||||
import { InitWebUi, WebUiConfig } from '@/webui';
|
import { InitWebUi, WebUiConfig } from '@/webui';
|
||||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||||
|
|
||||||
//Framework ES入口文件
|
//Framework ES入口文件
|
||||||
export async function getWebUiUrl() {
|
export async function getWebUiUrl() {
|
||||||
const WebUiConfigData = (await WebUiConfig.GetWebUIConfig());
|
const WebUiConfigData = (await WebUiConfig.GetWebUIConfig());
|
||||||
return "http://127.0.0.1:" + WebUiConfigData.port + '/webui/?token=' + WebUiConfigData.token;
|
return 'http://127.0.0.1:' + WebUiConfigData.port + '/webui/?token=' + WebUiConfigData.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function NCoreInitFramework(
|
export async function NCoreInitFramework(
|
||||||
session: NodeIQQNTWrapperSession,
|
session: NodeIQQNTWrapperSession,
|
||||||
loginService: NodeIKernelLoginService,
|
loginService: NodeIKernelLoginService,
|
||||||
@@ -29,7 +29,7 @@ export async function NCoreInitFramework(
|
|||||||
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
||||||
//直到登录成功后,执行下一步
|
//直到登录成功后,执行下一步
|
||||||
const selfInfo = await new Promise<SelfInfo>((resolveSelfInfo) => {
|
const selfInfo = await new Promise<SelfInfo>((resolveSelfInfo) => {
|
||||||
const loginListener = new LoginListener();
|
const loginListener = new NodeIKernelLoginListener();
|
||||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
||||||
await new Promise<void>(resolvePendingInit => {
|
await new Promise<void>(resolvePendingInit => {
|
||||||
registerInitCallback(() => resolvePendingInit());
|
registerInitCallback(() => resolvePendingInit());
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
|
const { contextBridge } = require('electron');
|
||||||
const { contextBridge } = require('electron')
|
const { ipcRenderer } = require('electron');
|
||||||
const { ipcRenderer } = require('electron')
|
|
||||||
|
|
||||||
const napcat = {
|
const napcat = {
|
||||||
getWebUiUrl: async () => {
|
getWebUiUrl: async () => {
|
||||||
return ipcRenderer.invoke("napcat_get_webtoken")
|
return ipcRenderer.invoke('napcat_get_webtoken');
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
// 在window对象下导出只读对象
|
// 在window对象下导出只读对象
|
||||||
contextBridge.exposeInMainWorld('napcat', napcat)
|
contextBridge.exposeInMainWorld('napcat', napcat);
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
export const onSettingWindowCreated = async (view) => {
|
export const onSettingWindowCreated = async (view) => {
|
||||||
|
|
||||||
// view.style.width = "100%";
|
// view.style.width = "100%";
|
||||||
// view.style.height = "100%";
|
// view.style.height = "100%";
|
||||||
// //添加iframe
|
// //添加iframe
|
||||||
@@ -14,7 +13,7 @@ export const onSettingWindowCreated = async (view) => {
|
|||||||
// //有滚动条何尝不是一种美
|
// //有滚动条何尝不是一种美
|
||||||
// view.appendChild(iframe);
|
// view.appendChild(iframe);
|
||||||
let webui = await window.napcat.getWebUiUrl();
|
let webui = await window.napcat.getWebUiUrl();
|
||||||
let panel = `
|
view.innerHTML = `
|
||||||
<setting-section data-title="">
|
<setting-section data-title="">
|
||||||
<setting-panel>
|
<setting-panel>
|
||||||
<setting-list data-direction="column">
|
<setting-list data-direction="column">
|
||||||
@@ -30,9 +29,8 @@ export const onSettingWindowCreated = async (view) => {
|
|||||||
</setting-panel>
|
</setting-panel>
|
||||||
</setting-section>
|
</setting-section>
|
||||||
`;
|
`;
|
||||||
view.innerHTML = panel;
|
view.querySelector('.nc_openwebui').addEventListener('click', () => {
|
||||||
view.querySelector(".nc_openwebui").addEventListener("click", () => {
|
window.open(webui, '_blank');
|
||||||
window.open(webui, "_blank");
|
|
||||||
});
|
});
|
||||||
view.querySelector(".nc_webui").innerText = webui;
|
view.querySelector('.nc_webui').innerText = webui;
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +0,0 @@
|
|||||||
# NewWebui
|
|
||||||
基于Vue3实现的现代化轻量化NapCat管理面板
|
|
||||||
## 进度
|
|
||||||
画饼
|
|
@@ -8,19 +8,19 @@ import { NapCatOneBot11Adapter } from '@/onebot';
|
|||||||
|
|
||||||
abstract class BaseAction<PayloadType, ReturnDataType> {
|
abstract class BaseAction<PayloadType, ReturnDataType> {
|
||||||
actionName: ActionName = ActionName.Unknown;
|
actionName: ActionName = ActionName.Unknown;
|
||||||
CoreContext: NapCatCore;
|
core: NapCatCore;
|
||||||
private validate: undefined | ValidateFunction<any> = undefined;
|
private validate: undefined | ValidateFunction<any> = undefined;
|
||||||
PayloadSchema: any = undefined;
|
payloadSchema: any = undefined;
|
||||||
OneBotContext: NapCatOneBot11Adapter;
|
obContext: NapCatOneBot11Adapter;
|
||||||
|
|
||||||
constructor(onebotContext: NapCatOneBot11Adapter, coreContext: NapCatCore) {
|
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
||||||
this.OneBotContext = onebotContext;
|
this.obContext = obContext;
|
||||||
this.CoreContext = coreContext;
|
this.core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async check(payload: PayloadType): Promise<BaseCheckResult> {
|
protected async check(payload: PayloadType): Promise<BaseCheckResult> {
|
||||||
if (this.PayloadSchema) {
|
if (this.payloadSchema) {
|
||||||
this.validate = new Ajv({ allowUnionTypes: true }).compile(this.PayloadSchema);
|
this.validate = new Ajv({ allowUnionTypes: true }).compile(this.payloadSchema);
|
||||||
}
|
}
|
||||||
if (this.validate && !this.validate(payload)) {
|
if (this.validate && !this.validate(payload)) {
|
||||||
const errors = this.validate.errors as ErrorObject[];
|
const errors = this.validate.errors as ErrorObject[];
|
||||||
@@ -46,7 +46,7 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
|
|||||||
const resData = await this._handle(payload);
|
const resData = await this._handle(payload);
|
||||||
return OB11Response.ok(resData);
|
return OB11Response.ok(resData);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.CoreContext.context.logger.logError('发生错误', e);
|
this.core.context.logger.logError('发生错误', e);
|
||||||
return OB11Response.error(e?.toString() || e?.stack?.toString() || '未知错误,可能操作超时', 200);
|
return OB11Response.error(e?.toString() || e?.stack?.toString() || '未知错误,可能操作超时', 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,13 +54,13 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
|
|||||||
public async websocketHandle(payload: PayloadType, echo: any): Promise<OB11Return<ReturnDataType | null>> {
|
public async websocketHandle(payload: PayloadType, echo: any): Promise<OB11Return<ReturnDataType | null>> {
|
||||||
const result = await this.check(payload);
|
const result = await this.check(payload);
|
||||||
if (!result.valid) {
|
if (!result.valid) {
|
||||||
return OB11Response.error(result.message, 1400);
|
return OB11Response.error(result.message, 1400, echo);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const resData = await this._handle(payload);
|
const resData = await this._handle(payload);
|
||||||
return OB11Response.ok(resData, echo);
|
return OB11Response.ok(resData, echo);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.CoreContext.context.logger.logError('发生错误', e);
|
this.core.context.logger.logError('发生错误', e);
|
||||||
return OB11Response.error(e.stack?.toString() || e.toString(), 1200, echo);
|
return OB11Response.error(e.stack?.toString() || e.toString(), 1200, echo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { OB11Return } from '../types';
|
import { OB11Return } from '../types';
|
||||||
|
|
||||||
import { isNull } from '../../common/utils/helper';
|
import { isNull } from '../../common/helper';
|
||||||
|
|
||||||
export class OB11Response {
|
export class OB11Response {
|
||||||
static res<T>(data: T, status: string, retcode: number, message: string = ''): OB11Return<T> {
|
static res<T>(data: T, status: string, retcode: number, message: string = ''): OB11Return<T> {
|
||||||
|
@@ -15,13 +15,13 @@ type Payload = FromSchema<typeof SchemaData>;
|
|||||||
|
|
||||||
export class CreateCollection extends BaseAction<Payload, any> {
|
export class CreateCollection extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.CreateCollection;
|
actionName = ActionName.CreateCollection;
|
||||||
PayloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
return await this.CoreContext.apis.CollectionApi.createCollection(
|
return await this.core.apis.CollectionApi.createCollection(
|
||||||
this.CoreContext.selfInfo.uin,
|
this.core.selfInfo.uin,
|
||||||
this.CoreContext.selfInfo.uid,
|
this.core.selfInfo.uid,
|
||||||
this.CoreContext.selfInfo.nick,
|
this.core.selfInfo.nick,
|
||||||
payload.brief, payload.rawData,
|
payload.brief, payload.rawData,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -13,11 +13,11 @@ type Payload = FromSchema<typeof SchemaData>;
|
|||||||
|
|
||||||
export class FetchCustomFace extends BaseAction<Payload, string[]> {
|
export class FetchCustomFace extends BaseAction<Payload, string[]> {
|
||||||
actionName = ActionName.FetchCustomFace;
|
actionName = ActionName.FetchCustomFace;
|
||||||
PayloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
//48 可能正好是QQ需要的一个页面的数量 Tagged Mlikiowa
|
//48 可能正好是QQ需要的一个页面的数量 Tagged Mlikiowa
|
||||||
const ret = await this.CoreContext.apis.MsgApi.fetchFavEmojiList(parseInt((payload.count || '0').toString()) || 48);
|
const ret = await this.core.apis.MsgApi.fetchFavEmojiList(+(payload.count ?? 48));
|
||||||
return ret.emojiInfoList.map(e => e.url);
|
return ret.emojiInfoList.map(e => e.url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
import { MessageUnique } from '@/common/message-unique';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -21,12 +21,12 @@ type Payload = FromSchema<typeof SchemaData>;
|
|||||||
|
|
||||||
export class FetchEmojiLike extends BaseAction<Payload, any> {
|
export class FetchEmojiLike extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.FetchEmojiLike;
|
actionName = ActionName.FetchEmojiLike;
|
||||||
PayloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
|
|
||||||
const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
|
const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
|
||||||
if (!msgIdPeer) throw new Error('消息不存在');
|
if (!msgIdPeer) throw new Error('消息不存在');
|
||||||
const msg = (await NTQQMsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0];
|
const msg = (await this.core.apis.MsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0];
|
||||||
return await NTQQMsgApi.getMsgEmojiLikesList(msgIdPeer.Peer, msg.msgSeq, payload.emojiId, payload.emojiType, parseInt((payload.count || '0').toString()) || 20);
|
return await this.core.apis.MsgApi.getMsgEmojiLikesList(msgIdPeer.Peer, msg.msgSeq, payload.emojiId, payload.emojiType, +(payload.count ?? 20));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,9 +15,9 @@ type Payload = FromSchema<typeof SchemaData>;
|
|||||||
|
|
||||||
export class GetCollectionList extends BaseAction<Payload, any> {
|
export class GetCollectionList extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.GetCollectionList;
|
actionName = ActionName.GetCollectionList;
|
||||||
PayloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQCollectionApi = this.CoreContext.apis.CollectionApi;
|
return await this.core.apis.CollectionApi.getAllCollection(parseInt(payload.category.toString()), +(payload.count ?? 1));
|
||||||
return await NTQQCollectionApi.getAllCollection(parseInt(payload.category.toString()), parseInt(payload.count.toString()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
import { OB11Constructor } from '@/onebot/helper/converter';
|
import { OB11Entities } from '@/onebot/entities';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
|
|
||||||
export class GetFriendWithCategory extends BaseAction<void, any> {
|
export class GetFriendWithCategory extends BaseAction<void, any> {
|
||||||
actionName = ActionName.GetFriendsWithCategory;
|
actionName = ActionName.GetFriendsWithCategory;
|
||||||
|
|
||||||
async _handle(payload: void) {
|
async _handle(payload: void) {
|
||||||
return (await this.CoreContext.apis.FriendApi.getBuddyV2ExWithCate(true)).map(category => ({
|
return (await this.core.apis.FriendApi.getBuddyV2ExWithCate(true)).map(category => ({
|
||||||
...category,
|
...category,
|
||||||
buddyList: OB11Constructor.friendsV2(category.buddyList),
|
buddyList: OB11Entities.friendsV2(category.buddyList),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@ export default class GetGroupAddRequest extends BaseAction<null, OB11GroupReques
|
|||||||
actionName = ActionName.GetGroupIgnoreAddRequest;
|
actionName = ActionName.GetGroupIgnoreAddRequest;
|
||||||
|
|
||||||
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
|
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
|
||||||
const data = await this.CoreContext.apis.GroupApi.getGroupIgnoreNotifies();
|
const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies();
|
||||||
// log(data);
|
// log(data);
|
||||||
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE);
|
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE);
|
||||||
// const returnData: OB11GroupRequestNotify[] = [];
|
// const returnData: OB11GroupRequestNotify[] = [];
|
||||||
|
22
src/onebot/action/extends/GetGroupInfoEx.ts
Normal file
22
src/onebot/action/extends/GetGroupInfoEx.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
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'] },
|
||||||
|
},
|
||||||
|
required: ['group_id'],
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export class GetGroupInfoEx extends BaseAction<Payload, any> {
|
||||||
|
actionName = ActionName.GetGroupInfoEx;
|
||||||
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
|
async _handle(payload: Payload) {
|
||||||
|
return (await this.core.apis.GroupApi.getGroupExtFE0Info([payload.group_id.toString()])).result.groupExtInfos.get(payload.group_id.toString());
|
||||||
|
}
|
||||||
|
}
|
@@ -5,11 +5,10 @@ export class GetProfileLike extends BaseAction<void, any> {
|
|||||||
actionName = ActionName.GetProfileLike;
|
actionName = ActionName.GetProfileLike;
|
||||||
|
|
||||||
async _handle(payload: void) {
|
async _handle(payload: void) {
|
||||||
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
const ret = await this.core.apis.UserApi.getProfileLike(this.core.selfInfo.uid);
|
||||||
const ret = await NTQQUserApi.getProfileLike(this.CoreContext.selfInfo.uid);
|
|
||||||
const listdata: any[] = ret.info.userLikeInfos[0].favoriteInfo.userInfos;
|
const listdata: any[] = ret.info.userLikeInfos[0].favoriteInfo.userInfos;
|
||||||
for (let i = 0; i < listdata.length; i++) {
|
for (let i = 0; i < listdata.length; i++) {
|
||||||
listdata[i].uin = parseInt((await NTQQUserApi.getUinByUidV2(listdata[i].uid)) || '');
|
listdata[i].uin = parseInt((await this.core.apis.UserApi.getUinByUidV2(listdata[i].uid)) || '');
|
||||||
}
|
}
|
||||||
return listdata;
|
return listdata;
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,6 @@ export class GetRobotUinRange extends BaseAction<void, Array<any>> {
|
|||||||
actionName = ActionName.GetRobotUinRange;
|
actionName = ActionName.GetRobotUinRange;
|
||||||
|
|
||||||
async _handle(payload: void) {
|
async _handle(payload: void) {
|
||||||
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
return await this.core.apis.UserApi.getRobotUinRange();
|
||||||
return await NTQQUserApi.getRobotUinRange();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { checkFileReceived, uri2local } from '@/common/utils/file';
|
import { checkFileReceived, uri2local } from '@/common/file';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@@ -15,17 +16,16 @@ type Payload = FromSchema<typeof SchemaData>;
|
|||||||
|
|
||||||
export class OCRImage extends BaseAction<Payload, any> {
|
export class OCRImage extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.OCRImage;
|
actionName = ActionName.OCRImage;
|
||||||
PayloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQSystemApi = this.CoreContext.apis.SystemApi;
|
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.image));
|
||||||
const { path, isLocal, errMsg, success } = (await uri2local(this.CoreContext.NapCatTempPath, payload.image));
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
throw `OCR ${payload.image}失败,image字段可能格式不正确`;
|
throw `OCR ${payload.image}失败,image字段可能格式不正确`;
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
||||||
const ret = await NTQQSystemApi.ORCImage(path);
|
const ret = await this.core.apis.SystemApi.ocrImage(path);
|
||||||
if (!isLocal) {
|
if (!isLocal) {
|
||||||
fs.unlink(path, () => {
|
fs.unlink(path, () => {
|
||||||
});
|
});
|
||||||
|
@@ -8,7 +8,7 @@ const SchemaData = {
|
|||||||
properties: {
|
properties: {
|
||||||
eventType: { type: 'string' },
|
eventType: { type: 'string' },
|
||||||
group_id: { type: 'string' },
|
group_id: { type: 'string' },
|
||||||
user_id: { type: 'string' }
|
user_id: { type: 'string' },
|
||||||
},
|
},
|
||||||
required: ['eventType'],
|
required: ['eventType'],
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
@@ -19,26 +19,23 @@ export class SetInputStatus extends BaseAction<Payload, any> {
|
|||||||
actionName = ActionName.SetInputStatus;
|
actionName = ActionName.SetInputStatus;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
|
||||||
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
|
|
||||||
let peer: Peer;
|
let peer: Peer;
|
||||||
if (payload.group_id) {
|
if (payload.group_id) {
|
||||||
peer = {
|
peer = {
|
||||||
chatType: ChatType.KCHATTYPEGROUP,
|
chatType: ChatType.KCHATTYPEGROUP,
|
||||||
peerUid: payload.group_id
|
peerUid: payload.group_id,
|
||||||
};
|
};
|
||||||
} else if (payload.user_id) {
|
} else if (payload.user_id) {
|
||||||
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id);
|
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id);
|
||||||
if (!uid) throw new Error('uid is empty');
|
if (!uid) throw new Error('uid is empty');
|
||||||
peer = {
|
peer = {
|
||||||
chatType: ChatType.KCHATTYPEC2C,
|
chatType: ChatType.KCHATTYPEC2C,
|
||||||
peerUid: uid
|
peerUid: uid,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
throw new Error('请指定 group_id 或 user_id');
|
throw new Error('请指定 group_id 或 user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
const ret = await NTQQMsgApi.sendShowInputStatusReq(peer, parseInt(payload.eventType));
|
return await this.core.apis.MsgApi.sendShowInputStatusReq(peer, parseInt(payload.eventType));
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,11 +14,9 @@ type Payload = FromSchema<typeof SchemaData>;
|
|||||||
|
|
||||||
export class SetLongNick extends BaseAction<Payload, any> {
|
export class SetLongNick extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.SetLongNick;
|
actionName = ActionName.SetLongNick;
|
||||||
PayloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
return await this.core.apis.UserApi.setLongNick(payload.longNick);
|
||||||
const ret = await NTQQUserApi.setLongNick(payload.longNick);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,24 +7,23 @@ const SchemaData = {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
status: { type: ['number', 'string'] },
|
status: { type: ['number', 'string'] },
|
||||||
extStatus: { type: ['number', 'string'] },
|
ext_status: { type: ['number', 'string'] },
|
||||||
batteryStatus: { type: ['number', 'string'] },
|
battery_status: { type: ['number', 'string'] },
|
||||||
},
|
},
|
||||||
required: ['status', 'extStatus', 'batteryStatus'],
|
required: ['status', 'ext_status', 'battery_status'],
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
type Payload = FromSchema<typeof SchemaData>;
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
export class SetOnlineStatus extends BaseAction<Payload, null> {
|
export class SetOnlineStatus extends BaseAction<Payload, null> {
|
||||||
actionName = ActionName.SetOnlineStatus;
|
actionName = ActionName.SetOnlineStatus;
|
||||||
PayloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
const ret = await this.core.apis.UserApi.setSelfOnlineStatus(
|
||||||
const ret = await NTQQUserApi.setSelfOnlineStatus(
|
|
||||||
parseInt(payload.status.toString()),
|
parseInt(payload.status.toString()),
|
||||||
parseInt(payload.extStatus.toString()),
|
parseInt(payload.ext_status.toString()),
|
||||||
parseInt(payload.batteryStatus.toString())
|
parseInt(payload.battery_status.toString()),
|
||||||
);
|
);
|
||||||
if (ret.result !== 0) {
|
if (ret.result !== 0) {
|
||||||
throw new Error('设置在线状态失败');
|
throw new Error('设置在线状态失败');
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName, BaseCheckResult } from '../types';
|
import { ActionName, BaseCheckResult } from '../types';
|
||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
import { checkFileReceived, uri2local } from '@/common/utils/file';
|
import { checkFileReceived, uri2local } from '@/common/file';
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
file: string;
|
file: string;
|
||||||
@@ -24,14 +24,13 @@ export default class SetAvatar extends BaseAction<Payload, null> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<null> {
|
async _handle(payload: Payload): Promise<null> {
|
||||||
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
|
||||||
const { path, isLocal, errMsg, success } = (await uri2local(this.CoreContext.NapCatTempPath, payload.file));
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断
|
||||||
const ret = await NTQQUserApi.setQQAvatar(path);
|
const ret = await this.core.apis.UserApi.setQQAvatar(path);
|
||||||
if (!isLocal) {
|
if (!isLocal) {
|
||||||
fs.unlink(path, () => {
|
fs.unlink(path, () => {
|
||||||
});
|
});
|
||||||
|
@@ -16,15 +16,13 @@ type Payload = FromSchema<typeof SchemaData>;
|
|||||||
|
|
||||||
export class SharePeer extends BaseAction<Payload, any> {
|
export class SharePeer extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.SharePeer;
|
actionName = ActionName.SharePeer;
|
||||||
PayloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQUserApi = this.CoreContext.apis.UserApi;
|
|
||||||
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
|
|
||||||
if (payload.group_id) {
|
if (payload.group_id) {
|
||||||
return await NTQQGroupApi.getGroupRecommendContactArkJson(payload.group_id);
|
return await this.core.apis.GroupApi.getGroupRecommendContactArkJson(payload.group_id);
|
||||||
} else if (payload.user_id) {
|
} else if (payload.user_id) {
|
||||||
return await NTQQUserApi.getBuddyRecommendContactArkJson(payload.user_id, payload.phoneNumber || '');
|
return await this.core.apis.UserApi.getBuddyRecommendContactArkJson(payload.user_id, payload.phoneNumber || '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,10 +39,9 @@ type PayloadGroupEx = FromSchema<typeof SchemaDataGroupEx>;
|
|||||||
|
|
||||||
export class ShareGroupEx extends BaseAction<PayloadGroupEx, any> {
|
export class ShareGroupEx extends BaseAction<PayloadGroupEx, any> {
|
||||||
actionName = ActionName.ShareGroupEx;
|
actionName = ActionName.ShareGroupEx;
|
||||||
PayloadSchema = SchemaDataGroupEx;
|
payloadSchema = SchemaDataGroupEx;
|
||||||
|
|
||||||
async _handle(payload: PayloadGroupEx) {
|
async _handle(payload: PayloadGroupEx) {
|
||||||
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
|
return await this.core.apis.GroupApi.getArkJsonGroupShare(payload.group_id);
|
||||||
return await NTQQGroupApi.getArkJsonGroupShare(payload.group_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user