mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
50 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
236bec11ed | ||
![]() |
de48b0f940 | ||
![]() |
4885d4db86 | ||
![]() |
0c7bbda936 | ||
![]() |
fa07c2c1fb | ||
![]() |
5d17a191f6 | ||
![]() |
67fb74d3c2 | ||
![]() |
dc04cfc1b3 | ||
![]() |
d61d481965 | ||
![]() |
6b346ee1de | ||
![]() |
d0f248aaf9 | ||
![]() |
85c9227515 | ||
![]() |
73b6d3be84 | ||
![]() |
1ff6ce2343 | ||
![]() |
c145935d46 | ||
![]() |
e9ede6924e | ||
![]() |
515a21761d | ||
![]() |
8d6397028b | ||
![]() |
7e74578312 | ||
![]() |
bd295a4632 | ||
![]() |
166c30fe2c | ||
![]() |
66c1bab629 | ||
![]() |
66656304f9 | ||
![]() |
07f66e379d | ||
![]() |
7ae8fd60c4 | ||
![]() |
7275066994 | ||
![]() |
385adec186 | ||
![]() |
96b5bec5ab | ||
![]() |
6a9ec4e5f0 | ||
![]() |
d9851493df | ||
![]() |
efdb520414 | ||
![]() |
5548644aeb | ||
![]() |
e3fcd91b2d | ||
![]() |
2cae30ba88 | ||
![]() |
58cd38c4a8 | ||
![]() |
3300304feb | ||
![]() |
f0e376d06b | ||
![]() |
16f7bb48f2 | ||
![]() |
7f383dd29b | ||
![]() |
3dc529edf4 | ||
![]() |
45dedb4872 | ||
![]() |
afcdd01c0d | ||
![]() |
1164877e9a | ||
![]() |
fe92a449ba | ||
![]() |
401b0e2bd0 | ||
![]() |
cf9c71fcc1 | ||
![]() |
15a2400069 | ||
![]() |
d68a39b49e | ||
![]() |
066ca22e24 | ||
![]() |
0418b926fe |
Binary file not shown.
Binary file not shown.
@@ -9,7 +9,7 @@ if %errorLevel% == 0 (
|
|||||||
exit
|
exit
|
||||||
)
|
)
|
||||||
|
|
||||||
set NAPCAT_PATCH_PATH=%cd%\patchNapCat.js
|
set NAPCAT_PATCH_PACKAGE=%cd%\qqnt.json
|
||||||
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
|
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
|
||||||
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
|
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
|
||||||
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
|
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
|
||||||
|
@@ -9,7 +9,7 @@ if %errorLevel% == 0 (
|
|||||||
exit
|
exit
|
||||||
)
|
)
|
||||||
|
|
||||||
set NAPCAT_PATCH_PATH=%cd%\patchNapCat.js
|
set NAPCAT_PATCH_PACKAGE=%cd%\qqnt.json
|
||||||
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
|
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
|
||||||
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
|
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
|
||||||
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
|
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
require('./launcher.node').load('external_index', module);
|
|
23
launcher/qqnt.json
Normal file
23
launcher/qqnt.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "qq-chat",
|
||||||
|
"version": "9.9.15-28060",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"description": "QQ",
|
||||||
|
"productName": "QQ",
|
||||||
|
"author": {
|
||||||
|
"name": "Tencent",
|
||||||
|
"email": "QQ-Team@tencent.com"
|
||||||
|
},
|
||||||
|
"homepage": "https://im.qq.com",
|
||||||
|
"sideEffects": true,
|
||||||
|
"bin": {
|
||||||
|
"qd": "externals/devtools/cli/index.js"
|
||||||
|
},
|
||||||
|
"main": "./loadNapCat.js",
|
||||||
|
"buildVersion": "28060",
|
||||||
|
"isPureShell": true,
|
||||||
|
"isByteCodeShell": true,
|
||||||
|
"platform": "win32",
|
||||||
|
"eleArch": "x64"
|
||||||
|
}
|
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "2.5.0",
|
"version": "2.5.4",
|
||||||
"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.5.0",
|
"version": "2.5.4",
|
||||||
"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",
|
||||||
|
@@ -40,12 +40,14 @@ async function convert(filePath: string, pcmPath: string, logger: LogWrapper): P
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleWavFile(file: Buffer, filePath: string, pcmPath: string, logger: LogWrapper): Promise<Buffer> {
|
async function handleWavFile(
|
||||||
|
file: Buffer, filePath: string, pcmPath: string, logger: LogWrapper
|
||||||
|
): Promise<{input: Buffer, sampleRate: number}> {
|
||||||
const { fmt } = getWavFileInfo(file);
|
const { fmt } = getWavFileInfo(file);
|
||||||
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
|
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
|
||||||
return await convert(filePath, pcmPath, logger);
|
return {input: await convert(filePath, pcmPath, logger), sampleRate: 24000};
|
||||||
}
|
}
|
||||||
return file;
|
return {input: file, sampleRate: fmt.sampleRate};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) {
|
export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: LogWrapper) {
|
||||||
@@ -55,8 +57,10 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
|||||||
if (!isSilk(file)) {
|
if (!isSilk(file)) {
|
||||||
logger.log(`语音文件${filePath}需要转换成silk`);
|
logger.log(`语音文件${filePath}需要转换成silk`);
|
||||||
const pcmPath = `${pttPath}.pcm`;
|
const pcmPath = `${pttPath}.pcm`;
|
||||||
const input = isWav(file) ? await handleWavFile(file, filePath, pcmPath, logger) : await convert(filePath, pcmPath, logger);
|
const { input, sampleRate } = isWav(file)
|
||||||
const silk = await encode(input, 24000);
|
? (await handleWavFile(file, filePath, pcmPath, logger))
|
||||||
|
: {input: await convert(filePath, pcmPath, logger), sampleRate: 24000};
|
||||||
|
const silk = await encode(input, sampleRate);
|
||||||
await fsPromise.writeFile(pttPath, silk.data);
|
await fsPromise.writeFile(pttPath, silk.data);
|
||||||
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
||||||
return {
|
return {
|
||||||
|
@@ -163,34 +163,45 @@ 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-27597',
|
baseVersion: '3.2.12.28060',
|
||||||
curVersion: '3.2.12-27597',
|
curVersion: '3.2.12.28060',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '27597',
|
buildId: '27254',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (os.platform() === 'darwin') {
|
||||||
|
return {
|
||||||
|
baseVersion: '6.9.53.28060',
|
||||||
|
curVersion: '6.9.53.28060',
|
||||||
|
prevVersion: '',
|
||||||
|
onErrorVersions: [],
|
||||||
|
buildId: '28060',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
baseVersion: '9.9.15-27597',
|
baseVersion: '9.9.15-28060',
|
||||||
curVersion: '9.9.15-27597',
|
curVersion: '9.9.15-28060',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '27597',
|
buildId: '28060',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getQQPackageInfoPath(exePath: string = ''): string {
|
export function getQQPackageInfoPath(exePath: string = '', version: string): string {
|
||||||
if (os.platform() === 'darwin') {
|
if (os.platform() === 'darwin') {
|
||||||
return path.join(path.dirname(exePath), '..', 'Resources', 'app', 'package.json');
|
return path.join(path.dirname(exePath), '..', 'Resources', 'app', 'package.json');
|
||||||
|
} else if (os.platform() === 'linux') {
|
||||||
|
return path.join(path.dirname(exePath), './resources/app/package.json');
|
||||||
} else {
|
} else {
|
||||||
return path.join(path.dirname(exePath), 'resources', 'app', 'package.json');
|
return path.join(path.dirname(exePath), './versions/' + version + '/resources/app/package.json');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getQQVersionConfigPath(exePath: string = ''): string | undefined {
|
export function getQQVersionConfigPath(exePath: string = ''): string | undefined {
|
||||||
let configVersionInfoPath;
|
let configVersionInfoPath;
|
||||||
if (os.platform() === 'win32') {
|
if (os.platform() === 'win32') {
|
||||||
configVersionInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'versions', 'config.json');
|
configVersionInfoPath = path.join(path.dirname(exePath), 'versions', 'config.json');
|
||||||
} else if (os.platform() === 'darwin') {
|
} else if (os.platform() === 'darwin') {
|
||||||
const userPath = os.homedir();
|
const userPath = os.homedir();
|
||||||
const appDataPath = path.resolve(userPath, './Library/Application Support/QQ');
|
const appDataPath = path.resolve(userPath, './Library/Application Support/QQ');
|
||||||
|
@@ -19,14 +19,16 @@ export class QQBasicInfoWrapper {
|
|||||||
//基础目录获取
|
//基础目录获取
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.QQMainPath = process.execPath;
|
this.QQMainPath = process.execPath;
|
||||||
this.QQPackageInfoPath = getQQPackageInfoPath(this.QQMainPath);
|
|
||||||
this.QQVersionConfigPath = getQQVersionConfigPath(this.QQMainPath);
|
this.QQVersionConfigPath = getQQVersionConfigPath(this.QQMainPath);
|
||||||
|
|
||||||
|
|
||||||
//基础信息获取 无快更则启用默认模板填充
|
//基础信息获取 无快更则启用默认模板填充
|
||||||
this.isQuickUpdate = !!this.QQVersionConfigPath;
|
this.isQuickUpdate = !!this.QQVersionConfigPath;
|
||||||
this.QQVersionConfig = this.isQuickUpdate
|
this.QQVersionConfig = this.isQuickUpdate
|
||||||
? JSON.parse(fs.readFileSync(this.QQVersionConfigPath!).toString())
|
? JSON.parse(fs.readFileSync(this.QQVersionConfigPath!).toString())
|
||||||
: getDefaultQQVersionConfigInfo();
|
: getDefaultQQVersionConfigInfo();
|
||||||
|
|
||||||
|
this.QQPackageInfoPath = getQQPackageInfoPath(this.QQMainPath, this.QQVersionConfig?.curVersion!);
|
||||||
this.QQPackageInfo = JSON.parse(fs.readFileSync(this.QQPackageInfoPath).toString());
|
this.QQPackageInfo = JSON.parse(fs.readFileSync(this.QQPackageInfoPath).toString());
|
||||||
const { appid: IQQVersionAppid, qua: IQQVersionQua } = this.getAppidV2();
|
const { appid: IQQVersionAppid, qua: IQQVersionQua } = this.getAppidV2();
|
||||||
this.QQVersionAppid = IQQVersionAppid;
|
this.QQVersionAppid = IQQVersionAppid;
|
||||||
@@ -53,23 +55,23 @@ export class QQBasicInfoWrapper {
|
|||||||
//此方法不要直接使用
|
//此方法不要直接使用
|
||||||
getQUAInternal() {
|
getQUAInternal() {
|
||||||
switch (systemPlatform) {
|
switch (systemPlatform) {
|
||||||
case 'linux':
|
case 'linux':
|
||||||
return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||||
default:
|
default:
|
||||||
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getAppidInternal() {
|
getAppidInternal() {
|
||||||
switch (systemPlatform) {
|
switch (systemPlatform) {
|
||||||
case 'linux':
|
case 'linux':
|
||||||
return '537243600';
|
return '537246140';
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
return '537243441';
|
return '537246140';
|
||||||
default:
|
default:
|
||||||
return '537243538';
|
return '537246092';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '2.5.0';
|
export const napCatVersion = '2.5.4';
|
||||||
|
@@ -34,7 +34,13 @@ export class NTQQGroupApi {
|
|||||||
}
|
}
|
||||||
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
|
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
|
||||||
}
|
}
|
||||||
|
async getCoreAndBaseInfo(uids: string[]) {
|
||||||
|
return await this.core.eventWrapper.callNoListenerEvent(
|
||||||
|
'NodeIKernelProfileService/getCoreAndBaseInfo',
|
||||||
|
'nodeStore',
|
||||||
|
uids,
|
||||||
|
);
|
||||||
|
}
|
||||||
async fetchGroupEssenceList(groupCode: string) {
|
async fetchGroupEssenceList(groupCode: string) {
|
||||||
const pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
const pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
||||||
return this.context.session.getGroupService().fetchGroupEssenceList({
|
return this.context.session.getGroupService().fetchGroupEssenceList({
|
||||||
|
16
src/core/external/appid.json
vendored
16
src/core/external/appid.json
vendored
@@ -1,14 +1,10 @@
|
|||||||
{
|
{
|
||||||
"3.2.12-27597": {
|
"9.9.15-28060":{
|
||||||
"appid": 537243600,
|
"appid": 537246092,
|
||||||
"qua": "V1_LNX_NQ_3.2.12_27597_GW_B"
|
"qua": "V1_WIN_NQ_9.9.15_28060_GW_B"
|
||||||
},
|
},
|
||||||
"9.9.15-27597": {
|
"3.2.12-28060":{
|
||||||
"appid": 537243441,
|
"appid": 537246140,
|
||||||
"qua": "V1_WIN_NQ_9.9.15_27597_GW_B"
|
"qua": "V1_LNX_NQ_3.2.12_28060_GW_B"
|
||||||
},
|
|
||||||
"6.9.53-27597": {
|
|
||||||
"appid": 537243538,
|
|
||||||
"qua": "V1_MAC_NQ_6.9.53_27597_GW_B"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,12 +45,14 @@ export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
|
|||||||
let appPath;
|
let appPath;
|
||||||
if (os.platform() === 'darwin') {
|
if (os.platform() === 'darwin') {
|
||||||
appPath = path.resolve(path.dirname(process.execPath), '../Resources/app');
|
appPath = path.resolve(path.dirname(process.execPath), '../Resources/app');
|
||||||
} else {
|
} else if (os.platform() === 'linux') {
|
||||||
appPath = path.resolve(path.dirname(process.execPath), './resources/app');
|
appPath = path.resolve(path.dirname(process.execPath), './resources/app');
|
||||||
|
} else {
|
||||||
|
appPath = path.resolve(path.dirname(process.execPath), `./versions/${QQVersion}/`);
|
||||||
}
|
}
|
||||||
let wrapperNodePath = path.resolve(appPath, 'wrapper.node');
|
let wrapperNodePath = path.resolve(appPath, 'wrapper.node');
|
||||||
if (!fs.existsSync(wrapperNodePath)) {
|
if (!fs.existsSync(wrapperNodePath)) {
|
||||||
wrapperNodePath = path.join(appPath, `versions/${QQVersion}/wrapper.node`);
|
wrapperNodePath = path.join(appPath, `./resources/app/wrapper.node`);
|
||||||
}
|
}
|
||||||
const nativemodule: any = { exports: {} };
|
const nativemodule: any = { exports: {} };
|
||||||
process.dlopen(nativemodule, wrapperNodePath);
|
process.dlopen(nativemodule, wrapperNodePath);
|
||||||
|
@@ -14,9 +14,15 @@ export interface LikeMsgType {
|
|||||||
detail: LikeDetailType;
|
detail: LikeDetailType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProfileLikeTipType {
|
export interface profileLikeSubTipType {
|
||||||
msg: LikeMsgType;
|
msg: LikeMsgType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProfileLikeTipType {
|
||||||
|
msgType: number;
|
||||||
|
subType: number;
|
||||||
|
content: profileLikeSubTipType;
|
||||||
|
}
|
||||||
export interface SysMessageHeaderType {
|
export interface SysMessageHeaderType {
|
||||||
id: string;
|
id: string;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
@@ -78,6 +84,12 @@ export const likeMsg = new pb.Type("likeMsg")
|
|||||||
.add(new pb.Field("time", 2, "int32"))
|
.add(new pb.Field("time", 2, "int32"))
|
||||||
.add(new pb.Field("detail", 3, "likeDetail"));
|
.add(new pb.Field("detail", 3, "likeDetail"));
|
||||||
|
|
||||||
export const profileLikeTip = new pb.Type("profileLikeTip")
|
export const profileLikeSubTip = new pb.Type("profileLikeSubTip")
|
||||||
.add(likeMsg)
|
.add(likeMsg)
|
||||||
.add(new pb.Field("msg", 14, "likeMsg"));
|
.add(new pb.Field("msg", 14, "likeMsg"))
|
||||||
|
|
||||||
|
export const profileLikeTip = new pb.Type("profileLikeTip")
|
||||||
|
.add(profileLikeSubTip)
|
||||||
|
.add(new pb.Field("msgType", 1, "int32"))
|
||||||
|
.add(new pb.Field("subType", 2, "int32"))
|
||||||
|
.add(new pb.Field("content", 203, "profileLikeSubTip"));
|
||||||
|
@@ -114,7 +114,7 @@ export interface NodeIKernelBuddyService {
|
|||||||
|
|
||||||
reportDoubtBuddyReqUnread(): void;
|
reportDoubtBuddyReqUnread(): void;
|
||||||
|
|
||||||
getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise<unknown>;
|
getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise<GeneralCallResult & { arkMsg: string }>;
|
||||||
|
|
||||||
isNull(): boolean;
|
isNull(): boolean;
|
||||||
}
|
}
|
||||||
|
11
src/onebot/action/extends/FetchUserProfileLike.ts
Normal file
11
src/onebot/action/extends/FetchUserProfileLike.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName } from '../types';
|
||||||
|
|
||||||
|
export class FetchUserProfileLike extends BaseAction<{ qq: number }, any> {
|
||||||
|
actionName = ActionName.FetchUserProfileLike;
|
||||||
|
|
||||||
|
async _handle(payload: { qq: number }) {
|
||||||
|
if (!payload.qq) throw new Error('qq is required');
|
||||||
|
return await this.core.apis.UserApi.getUidByUinV2(payload.qq.toString());
|
||||||
|
}
|
||||||
|
}
|
@@ -3,6 +3,7 @@ import { OB11Entities } from '@/onebot/entities';
|
|||||||
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 { calcQQLevel } from '@/common/helper';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -22,7 +23,8 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
|
|||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const groupMembers = await this.core.apis.GroupApi.getGroupMembersV2(payload.group_id.toString());
|
const groupMembers = await this.core.apis.GroupApi.getGroupMembersV2(payload.group_id.toString());
|
||||||
const groupMembersArr = Array.from(groupMembers.values());
|
const groupMembersArr = Array.from(groupMembers.values());
|
||||||
|
let uids = groupMembersArr.map(item => item.uid);
|
||||||
|
//let CoreAndBase = await this.core.apis.GroupApi.getCoreAndBaseInfo(uids)
|
||||||
let _groupMembers = groupMembersArr.map(item => {
|
let _groupMembers = groupMembersArr.map(item => {
|
||||||
return OB11Entities.groupMember(payload.group_id.toString(), item);
|
return OB11Entities.groupMember(payload.group_id.toString(), item);
|
||||||
});
|
});
|
||||||
@@ -32,34 +34,38 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
|
|||||||
|
|
||||||
for (let i = 0, len = _groupMembers.length; i < len; i++) {
|
for (let i = 0, len = _groupMembers.length; i < len; i++) {
|
||||||
// 保证基础数据有这个 同时避免群管插件过于依赖这个杀了
|
// 保证基础数据有这个 同时避免群管插件过于依赖这个杀了
|
||||||
_groupMembers[i].join_time = date;
|
const Member = await this.core.apis.GroupApi.getGroupMember(payload.group_id.toString(), _groupMembers[i].user_id);
|
||||||
_groupMembers[i].last_sent_time = date;
|
_groupMembers[i].join_time = +(Member?.joinTime ?? date);
|
||||||
|
_groupMembers[i].last_sent_time = +(Member?.lastSpeakTime ?? date);
|
||||||
MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]);
|
MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const selfRole = groupMembers.get(this.core.selfInfo.uid)?.role;
|
const selfRole = groupMembers.get(this.core.selfInfo.uid)?.role;
|
||||||
const isPrivilege = selfRole === 3 || selfRole === 4;
|
const isPrivilege = selfRole === 3 || selfRole === 4;
|
||||||
|
|
||||||
_groupMembers.forEach(item => {
|
|
||||||
item.last_sent_time = date;
|
|
||||||
item.join_time = date;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isPrivilege) {
|
if (isPrivilege) {
|
||||||
const webGroupMembers = await this.core.apis.WebApi.getGroupMembers(payload.group_id.toString());
|
try {
|
||||||
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
const webGroupMembers = await this.core.apis.WebApi.getGroupMembers(payload.group_id.toString());
|
||||||
if (!webGroupMembers[i]?.uin) {
|
for (let i = 0, len = webGroupMembers.length; i < len; i++) {
|
||||||
continue;
|
if (!webGroupMembers[i]?.uin) {
|
||||||
}
|
continue;
|
||||||
const MemberData = MemberMap.get(webGroupMembers[i]?.uin);
|
}
|
||||||
if (MemberData) {
|
const MemberData = MemberMap.get(webGroupMembers[i]?.uin);
|
||||||
MemberData.join_time = webGroupMembers[i]?.join_time;
|
if (MemberData) {
|
||||||
MemberData.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
MemberData.join_time = webGroupMembers[i]?.join_time;
|
||||||
MemberData.qage = webGroupMembers[i]?.qage;
|
MemberData.last_sent_time = webGroupMembers[i]?.last_speak_time;
|
||||||
MemberData.level = webGroupMembers[i]?.lv.level.toString();
|
MemberData.qage = webGroupMembers[i]?.qage;
|
||||||
MemberMap.set(webGroupMembers[i]?.uin, MemberData);
|
MemberData.level = webGroupMembers[i]?.lv.level.toString();
|
||||||
|
MemberMap.set(webGroupMembers[i]?.uin, MemberData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
const logger = this.core.context.logger;
|
||||||
|
logger.logError.bind(logger)('GetGroupMemberList', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_groupMembers = Array.from(MemberMap.values());
|
_groupMembers = Array.from(MemberMap.values());
|
||||||
|
@@ -68,8 +68,8 @@ import SetGroupPortrait from './go-cqhttp/SetGroupPortrait';
|
|||||||
import { FetchCustomFace } from './extends/FetchCustomFace';
|
import { FetchCustomFace } from './extends/FetchCustomFace';
|
||||||
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivateFile';
|
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivateFile';
|
||||||
import { FetchEmojiLike } from './extends/FetchEmojiLike';
|
import { FetchEmojiLike } from './extends/FetchEmojiLike';
|
||||||
|
import { FetchUserProfileLike } from './extends/FetchUserProfileLike';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
|
|
||||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||||
import GetGuildProfile from './guild/GetGuildProfile';
|
import GetGuildProfile from './guild/GetGuildProfile';
|
||||||
import SetModelShow from './go-cqhttp/SetModelShow';
|
import SetModelShow from './go-cqhttp/SetModelShow';
|
||||||
@@ -85,6 +85,7 @@ import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
|
|||||||
import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesByFolder';
|
import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesByFolder';
|
||||||
import { GetGroupSystemMsg } from './system/GetSystemMsg';
|
import { GetGroupSystemMsg } from './system/GetSystemMsg';
|
||||||
|
|
||||||
|
|
||||||
export type ActionMap = Map<string, BaseAction<any, any>>;
|
export type ActionMap = Map<string, BaseAction<any, any>>;
|
||||||
|
|
||||||
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap {
|
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap {
|
||||||
@@ -178,6 +179,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
|
|||||||
new GetGroupFileSystemInfo(obContext, core),
|
new GetGroupFileSystemInfo(obContext, core),
|
||||||
new GetGroupFilesByFolder(obContext, core),
|
new GetGroupFilesByFolder(obContext, core),
|
||||||
new GetGroupSystemMsg(obContext, core),
|
new GetGroupSystemMsg(obContext, core),
|
||||||
|
new FetchUserProfileLike(obContext, core),
|
||||||
];
|
];
|
||||||
const actionMap = new Map();
|
const actionMap = new Map();
|
||||||
for (const action of actionHandlers) {
|
for (const action of actionHandlers) {
|
||||||
|
@@ -16,8 +16,8 @@ export interface InvalidCheckResult {
|
|||||||
export enum ActionName {
|
export enum ActionName {
|
||||||
// 以下为扩展napcat扩展
|
// 以下为扩展napcat扩展
|
||||||
Unknown = 'unknown',
|
Unknown = 'unknown',
|
||||||
SharePeer = 'ArkShareGroup',
|
SharePeer = 'ArkSharePeer',
|
||||||
ShareGroupEx = 'ArkSharePeer',
|
ShareGroupEx = 'ArkShareGroup',
|
||||||
RebootNormal = 'reboot_normal',//无快速登录重新启动
|
RebootNormal = 'reboot_normal',//无快速登录重新启动
|
||||||
GetRobotUinRange = 'get_robot_uin_range',
|
GetRobotUinRange = 'get_robot_uin_range',
|
||||||
SetOnlineStatus = 'set_online_status',
|
SetOnlineStatus = 'set_online_status',
|
||||||
@@ -118,4 +118,5 @@ export enum ActionName {
|
|||||||
DelGroupNotice = '_del_group_notice',
|
DelGroupNotice = '_del_group_notice',
|
||||||
GetGroupInfoEx = "get_group_info_ex",
|
GetGroupInfoEx = "get_group_info_ex",
|
||||||
GetGroupSystemMsg = 'get_group_system_msg',
|
GetGroupSystemMsg = 'get_group_system_msg',
|
||||||
|
FetchUserProfileLike = "fetch_user_profile_like",
|
||||||
}
|
}
|
||||||
|
@@ -466,7 +466,6 @@ export class OneBotMsgApi {
|
|||||||
sendMsg.data.summary,
|
sendMsg.data.summary,
|
||||||
sendMsg.data.sub_type,
|
sendMsg.data.sub_type,
|
||||||
);
|
);
|
||||||
context.deleteAfterSentFiles.push(sendPicElement.picElement.sourcePath);
|
|
||||||
return sendPicElement;
|
return sendPicElement;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -608,6 +607,14 @@ export class OneBotMsgApi {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
[OB11MessageDataType.miniapp]: async () => undefined,
|
[OB11MessageDataType.miniapp]: async () => undefined,
|
||||||
|
|
||||||
|
[OB11MessageDataType.contact]: async ({ data }, context) => {
|
||||||
|
let arkJson = await this.core.apis.UserApi.getBuddyRecommendContactArkJson(data.id.toString(), '');
|
||||||
|
return this.ob11ToRawConverters.json({
|
||||||
|
data: { data: arkJson.arkMsg },
|
||||||
|
type: OB11MessageDataType.json
|
||||||
|
}, context);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
||||||
@@ -630,7 +637,7 @@ export class OneBotMsgApi {
|
|||||||
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_XMLMSG) {
|
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_XMLMSG) {
|
||||||
//好友添加成功事件
|
//好友添加成功事件
|
||||||
if (element.grayTipElement.xmlElement.templId === '10229' && msg.peerUin !== '') {
|
if (element.grayTipElement.xmlElement.templId === '10229' && msg.peerUin !== '') {
|
||||||
return new OB11FriendAddNoticeEvent(this.core, parseInt(msg.peerUin));
|
return new OB11FriendAddNoticeEvent(this.core, parseInt(msg.peerUin) || Number(await this.core.apis.UserApi.getUinByUidV2(msg.peerUid)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,7 @@ export class OneBotQuickActionApi {
|
|||||||
const peerContextMode = msg.message_type == 'private' ? ContextMode.Private : ContextMode.Group;
|
const peerContextMode = msg.message_type == 'private' ? ContextMode.Private : ContextMode.Group;
|
||||||
|
|
||||||
const peer: Peer = await createContext(this.core, {
|
const peer: Peer = await createContext(this.core, {
|
||||||
message: "",
|
message_type: undefined,
|
||||||
group_id: msg.group_id?.toString(),
|
group_id: msg.group_id?.toString(),
|
||||||
user_id: msg.user_id?.toString(),
|
user_id: msg.user_id?.toString(),
|
||||||
}, peerContextMode);
|
}, peerContextMode);
|
||||||
|
@@ -13,9 +13,10 @@ export class OneBotUserApi {
|
|||||||
this.core = core;
|
this.core = core;
|
||||||
}
|
}
|
||||||
async parseLikeEvent(wrappedBody: Uint8Array): Promise<OB11ProfileLikeEvent | undefined> {
|
async parseLikeEvent(wrappedBody: Uint8Array): Promise<OB11ProfileLikeEvent | undefined> {
|
||||||
const likeTip = profileLikeTip.decode(Uint8Array.from(wrappedBody.slice(12))) as unknown as ProfileLikeTipType;
|
const likeTip = profileLikeTip.decode(Uint8Array.from(wrappedBody)) as unknown as ProfileLikeTipType;
|
||||||
|
if (likeTip?.msgType !== 0 || likeTip?.subType !== 203) return;
|
||||||
this.core.context.logger.logDebug("收到点赞通知消息");
|
this.core.context.logger.logDebug("收到点赞通知消息");
|
||||||
const likeMsg = likeTip.msg;
|
const likeMsg = likeTip.content.msg;
|
||||||
if (!likeMsg) return;
|
if (!likeMsg) return;
|
||||||
const detail = likeMsg.detail;
|
const detail = likeMsg.detail;
|
||||||
if (!detail) return;
|
if (!detail) return;
|
||||||
|
@@ -48,7 +48,8 @@ export class OB11Entities {
|
|||||||
}[role];
|
}[role];
|
||||||
}
|
}
|
||||||
|
|
||||||
static sex(sex: Sex): OB11UserSex {
|
static sex(sex?: Sex): OB11UserSex {
|
||||||
|
if (!sex) return OB11UserSex.unknown;
|
||||||
return {
|
return {
|
||||||
[Sex.male]: OB11UserSex.male,
|
[Sex.male]: OB11UserSex.male,
|
||||||
[Sex.female]: OB11UserSex.female,
|
[Sex.female]: OB11UserSex.female,
|
||||||
@@ -126,7 +127,7 @@ export class OB11Entities {
|
|||||||
return {
|
return {
|
||||||
group_id: parseInt(peerId),
|
group_id: parseInt(peerId),
|
||||||
folder_id: folder.folderId,
|
folder_id: folder.folderId,
|
||||||
folder:folder.folderId,
|
folder: folder.folderId,
|
||||||
folder_name: folder.folderName,
|
folder_name: folder.folderName,
|
||||||
create_time: folder.createTime,
|
create_time: folder.createTime,
|
||||||
creator: parseInt(folder.createUin),
|
creator: parseInt(folder.createUin),
|
||||||
|
@@ -62,6 +62,7 @@ export enum OB11MessageDataType {
|
|||||||
dice = 'dice',
|
dice = 'dice',
|
||||||
RPS = 'rps',
|
RPS = 'rps',
|
||||||
miniapp = 'miniapp',//json类
|
miniapp = 'miniapp',//json类
|
||||||
|
contact = 'contact',
|
||||||
Location = 'location'
|
Location = 'location'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,10 +82,15 @@ export interface OB11MessageText {
|
|||||||
text: string, // 纯文本
|
text: string, // 纯文本
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export interface OB11MessageContext {
|
||||||
|
type: OB11MessageDataType.contact,
|
||||||
|
data: {
|
||||||
|
id: string,
|
||||||
|
}
|
||||||
|
}
|
||||||
export interface OB11MessageFileBase {
|
export interface OB11MessageFileBase {
|
||||||
data: {
|
data: {
|
||||||
file_unique?:string,
|
file_unique?: string,
|
||||||
path?: string;
|
path?: string;
|
||||||
thumb?: string;
|
thumb?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
@@ -198,7 +204,7 @@ export type OB11MessageData =
|
|||||||
OB11MessageAt | OB11MessageReply |
|
OB11MessageAt | OB11MessageReply |
|
||||||
OB11MessageImage | OB11MessageRecord | OB11MessageFile | OB11MessageVideo |
|
OB11MessageImage | OB11MessageRecord | OB11MessageFile | OB11MessageVideo |
|
||||||
OB11MessageNode | OB11MessageIdMusic | OB11MessageCustomMusic | OB11MessageJson |
|
OB11MessageNode | OB11MessageIdMusic | OB11MessageCustomMusic | OB11MessageJson |
|
||||||
OB11MessageDice | OB11MessageRPS | OB11MessageMarkdown | OB11MessageForward
|
OB11MessageDice | OB11MessageRPS | OB11MessageMarkdown | OB11MessageForward | OB11MessageContext
|
||||||
|
|
||||||
export interface OB11PostSendMsg {
|
export interface OB11PostSendMsg {
|
||||||
message_type?: 'private' | 'group'
|
message_type?: 'private' | 'group'
|
||||||
|
@@ -103,18 +103,21 @@ export async function NCoreInitShell() {
|
|||||||
|
|
||||||
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
||||||
const loginListener = new NodeIKernelLoginListener();
|
const loginListener = new NodeIKernelLoginListener();
|
||||||
|
let isLogined = false;
|
||||||
// from constructor
|
// from constructor
|
||||||
loginListener.onUserLoggedIn = (userid: string) => {
|
loginListener.onUserLoggedIn = (userid: string) => {
|
||||||
logger.logError(`当前账号(${userid})已登录,无法重复登录`);
|
logger.logError(`当前账号(${userid})已登录,无法重复登录`);
|
||||||
};
|
};
|
||||||
|
|
||||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => resolve({
|
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
||||||
uid: loginResult.uid,
|
isLogined = true;
|
||||||
uin: loginResult.uin,
|
resolve({
|
||||||
nick: '', // 获取不到
|
uid: loginResult.uid,
|
||||||
online: true,
|
uin: loginResult.uin,
|
||||||
});
|
nick: '', // 获取不到
|
||||||
|
online: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
loginListener.onQRCodeGetPicture = ({ pngBase64QrcodeData, qrcodeUrl }) => {
|
loginListener.onQRCodeGetPicture = ({ pngBase64QrcodeData, qrcodeUrl }) => {
|
||||||
//设置WebuiQrcode
|
//设置WebuiQrcode
|
||||||
@@ -138,11 +141,13 @@ export async function NCoreInitShell() {
|
|||||||
};
|
};
|
||||||
loginListener.onQRCodeSessionFailed = (errType: number, errCode: number, errMsg: string) => {
|
loginListener.onQRCodeSessionFailed = (errType: number, errCode: number, errMsg: string) => {
|
||||||
//logger.logError('登录失败(onQRCodeSessionFailed)', errCode, errMsg);
|
//logger.logError('登录失败(onQRCodeSessionFailed)', errCode, errMsg);
|
||||||
logger.logError('[Core] [Login] Login Error,ErrCode: ', errCode, ' ErrMsg:', errMsg);
|
if (!isLogined) {
|
||||||
if (errType == 1 && errCode == 3) {
|
logger.logError('[Core] [Login] Login Error,ErrCode: ', errCode, ' ErrMsg:', errMsg);
|
||||||
// 二维码过期刷新
|
if (errType == 1 && errCode == 3) {
|
||||||
|
// 二维码过期刷新
|
||||||
|
}
|
||||||
|
loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
loginService.getQRCodePicture();
|
|
||||||
};
|
};
|
||||||
loginListener.onLoginFailed = (args) => {
|
loginListener.onLoginFailed = (args) => {
|
||||||
//logger.logError('登录失败(onLoginFailed)', args);
|
//logger.logError('登录失败(onLoginFailed)', args);
|
||||||
@@ -189,14 +194,14 @@ export async function NCoreInitShell() {
|
|||||||
.then(result => {
|
.then(result => {
|
||||||
if (result.loginErrorInfo.errMsg) {
|
if (result.loginErrorInfo.errMsg) {
|
||||||
logger.logError('快速登录错误:', result.loginErrorInfo.errMsg);
|
logger.logError('快速登录错误:', result.loginErrorInfo.errMsg);
|
||||||
loginService.getQRCodePicture();
|
if (!isLogined) loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch();
|
.catch();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
logger.logError('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
logger.logError('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
||||||
loginService.getQRCodePicture();
|
if (!isLogined) loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log('没有 -q 指令指定快速登录,将使用二维码登录方式');
|
logger.log('没有 -q 指令指定快速登录,将使用二维码登录方式');
|
||||||
@@ -204,7 +209,7 @@ export async function NCoreInitShell() {
|
|||||||
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
||||||
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
||||||
.join('\n')
|
.join('\n')
|
||||||
}`);
|
}`);
|
||||||
}
|
}
|
||||||
loginService.getQRCodePicture();
|
loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
undefined,
|
undefined,
|
||||||
SettingButton('V2.5.0', 'napcat-update-button', 'secondary'),
|
SettingButton('V2.5.4', 'napcat-update-button', 'secondary'),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
void 0,
|
void 0,
|
||||||
SettingButton("V2.5.0", "napcat-update-button", "secondary")
|
SettingButton("V2.5.4", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
Reference in New Issue
Block a user