mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
55 Commits
esm-wrappe
...
v4.7.75
Author | SHA1 | Date | |
---|---|---|---|
![]() |
76b9506395 | ||
![]() |
f1cf636aa2 | ||
![]() |
312dcd0e13 | ||
![]() |
42c2419613 | ||
![]() |
8f7f748e82 | ||
![]() |
7ad3bad1be | ||
![]() |
5cd682e69f | ||
![]() |
5d57780e84 | ||
![]() |
f399955204 | ||
![]() |
770652fe6b | ||
![]() |
9ed5fa8c67 | ||
![]() |
5a4ad29727 | ||
![]() |
1eda3f2e33 | ||
![]() |
95cb95ef96 | ||
![]() |
4e7c96634c | ||
![]() |
58587b8aea | ||
![]() |
3fbf6239db | ||
![]() |
faec53d497 | ||
![]() |
482dcc534e | ||
![]() |
854f61dda6 | ||
![]() |
fca38713a1 | ||
![]() |
5dd3bade53 | ||
![]() |
665360f48d | ||
![]() |
65719cb56a | ||
![]() |
bdb76d4639 | ||
![]() |
15634412ef | ||
![]() |
bbcf9649fa | ||
![]() |
e845d7314e | ||
![]() |
6927b1c94f | ||
![]() |
a09c6acd0d | ||
![]() |
0963650ccb | ||
![]() |
380688b353 | ||
![]() |
ad5466bff8 | ||
![]() |
a83652bf3f | ||
![]() |
c632de314d | ||
![]() |
259c9610d5 | ||
![]() |
e9936c5524 | ||
![]() |
3f60440e72 | ||
![]() |
71a15f92fb | ||
![]() |
32bc0dd820 | ||
![]() |
20d1ac9d01 | ||
![]() |
18baf89e0e | ||
![]() |
3a1d1f2e59 | ||
![]() |
e9a048721d | ||
![]() |
68f0c7ff1a | ||
![]() |
2875fe94ea | ||
![]() |
1870427c0f | ||
![]() |
636568fd30 | ||
![]() |
bbc2391bf8 | ||
![]() |
401684542a | ||
![]() |
870edb2513 | ||
![]() |
7ad09169ea | ||
![]() |
c1a0f8915b | ||
![]() |
dcdab8e5a1 | ||
![]() |
eb3278fdab |
@@ -53,6 +53,8 @@ _Modern protocol-side framework implemented based on NTQQ._
|
||||
|
||||
+ [AstrBot](https://github.com/AstrBotDevs/AstrBot) 是完美适配本项目的LLM Bot框架 在此推荐一下
|
||||
|
||||
+ [MaiBot](https://github.com/MaiM-with-u/MaiBot) 一只赛博群友 麦麦 Bot框架 在此推荐一下
|
||||
|
||||
+ 不过最最重要的 还是需要感谢屏幕前的你哦~
|
||||
|
||||
---
|
||||
|
BIN
external/LiteLoaderWrapper.zip
vendored
BIN
external/LiteLoaderWrapper.zip
vendored
Binary file not shown.
@@ -4,7 +4,7 @@
|
||||
"name": "NapCatQQ",
|
||||
"slug": "NapCat.Framework",
|
||||
"description": "高性能的 OneBot 11 协议实现",
|
||||
"version": "4.7.62",
|
||||
"version": "4.7.74",
|
||||
"icon": "./logo.png",
|
||||
"authors": [
|
||||
{
|
||||
|
@@ -92,7 +92,9 @@ const MusicInsert = () => {
|
||||
className="w-96"
|
||||
fullWidth
|
||||
selectedKey={mode}
|
||||
onSelectionChange={setMode}
|
||||
onSelectionChange={(key) => {
|
||||
if (key !== null) setMode(key)
|
||||
}}
|
||||
>
|
||||
<Tab title="主流平台" key="default" className="flex flex-col gap-2">
|
||||
<Select
|
||||
|
@@ -56,9 +56,9 @@ export default function TerminalPage() {
|
||||
|
||||
setTabs((prev) => [...prev, newTab])
|
||||
setSelectedTab(id)
|
||||
} catch (error) {
|
||||
} catch (error: unknown) {
|
||||
console.error('Failed to create terminal:', error)
|
||||
toast.error('创建终端失败')
|
||||
toast.error((error as Error).message)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"name": "napcat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "4.7.62",
|
||||
"version": "4.7.74",
|
||||
"scripts": {
|
||||
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
|
||||
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
|
||||
|
@@ -13,11 +13,15 @@ export class NapCatPathWrapper {
|
||||
constructor(mainPath: string = dirname(fileURLToPath(import.meta.url))) {
|
||||
this.binaryPath = mainPath;
|
||||
let writePath: string;
|
||||
if (os.platform() === 'darwin') {
|
||||
|
||||
if (process.env['NAPCAT_WORKDIR']) {
|
||||
writePath = process.env['NAPCAT_WORKDIR'];
|
||||
} else if (os.platform() === 'darwin') {
|
||||
writePath = path.join(os.homedir(), 'Library', 'Application Support', 'QQ', 'NapCat');
|
||||
} else {
|
||||
writePath = this.binaryPath;
|
||||
}
|
||||
|
||||
this.logsPath = path.join(writePath, 'logs');
|
||||
this.configPath = path.join(writePath, 'config');
|
||||
this.cachePath = path.join(writePath, 'cache');
|
||||
|
@@ -1 +1 @@
|
||||
export const napCatVersion = '4.7.62';
|
||||
export const napCatVersion = '4.7.74';
|
||||
|
@@ -10,11 +10,14 @@ import {
|
||||
GroupNotify,
|
||||
GroupInfoSource,
|
||||
ShutUpGroupMember,
|
||||
Peer,
|
||||
ChatType,
|
||||
} from '@/core';
|
||||
import { isNumeric, solveAsyncProblem } from '@/common/helper';
|
||||
import { LimitedHashTable } from '@/common/message-unique';
|
||||
import { NTEventWrapper } from '@/common/event';
|
||||
import { CancelableTask, TaskExecutor } from '@/common/cancel-task';
|
||||
import { createGroupDetailInfoV2Param, createGroupExtFilter, createGroupExtInfo } from '../data';
|
||||
|
||||
export class NTQQGroupApi {
|
||||
context: InstanceContext;
|
||||
@@ -47,6 +50,22 @@ export class NTQQGroupApi {
|
||||
this.initCache().then().catch(e => this.context.logger.logError(e));
|
||||
}
|
||||
|
||||
async createGrayTip(groupCode: string, tip: string) {
|
||||
return this.context.session.getMsgService().addLocalJsonGrayTipMsg(
|
||||
{
|
||||
chatType: ChatType.KCHATTYPEGROUP,
|
||||
peerUid: groupCode,
|
||||
} as Peer,
|
||||
{
|
||||
busiId: 2201,
|
||||
jsonStr: JSON.stringify({ "align": "center", "items": [{ "txt": tip, "type": "nor" }] }),
|
||||
recentAbstract: tip,
|
||||
isServer: false
|
||||
},
|
||||
true,
|
||||
true
|
||||
)
|
||||
}
|
||||
async initCache() {
|
||||
for (const group of await this.getGroups(true)) {
|
||||
this.refreshGroupMemberCache(group.groupCode, false).then().catch(e => this.context.logger.logError(e));
|
||||
@@ -95,6 +114,58 @@ export class NTQQGroupApi {
|
||||
return this.context.session.getGroupService().setHeader(groupCode, filePath);
|
||||
}
|
||||
|
||||
// 0 0 无需管理员审核
|
||||
// 0 2 需要管理员审核
|
||||
// 1 2 禁止Bot入群( 最好只传一个1 ?)
|
||||
async setGroupRobotAddOption(groupCode: string, robotMemberSwitch?: number, robotMemberExamine?: number) {
|
||||
let extInfo = createGroupExtInfo(groupCode);
|
||||
let groupExtFilter = createGroupExtFilter();
|
||||
if (robotMemberSwitch !== undefined) {
|
||||
extInfo.extInfo.inviteRobotMemberSwitch = robotMemberSwitch;
|
||||
groupExtFilter.inviteRobotMemberSwitch = 1;
|
||||
}
|
||||
if (robotMemberExamine !== undefined) {
|
||||
extInfo.extInfo.inviteRobotMemberExamine = robotMemberExamine;
|
||||
groupExtFilter.inviteRobotMemberExamine = 1;
|
||||
}
|
||||
return this.context.session.getGroupService().modifyGroupExtInfoV2(extInfo, groupExtFilter);
|
||||
}
|
||||
|
||||
async setGroupAddOption(groupCode: string, option: {
|
||||
addOption: number;
|
||||
groupQuestion?: string;
|
||||
groupAnswer?: string;
|
||||
}) {
|
||||
let param = createGroupDetailInfoV2Param(groupCode);
|
||||
// 设置要修改的目标
|
||||
param.filter.addOption = 1;
|
||||
if (option.addOption == 4 || option.addOption == 5) {
|
||||
// 4 问题进入答案 5 问题管理员批准
|
||||
param.filter.groupQuestion = 1;
|
||||
param.filter.groupAnswer = option.addOption == 4 ? 1 : 0;
|
||||
param.modifyInfo.groupQuestion = option.groupQuestion || '';
|
||||
param.modifyInfo.groupAnswer = option.addOption == 4 ? option.groupAnswer || '' : '';
|
||||
}
|
||||
param.modifyInfo.addOption = option.addOption;
|
||||
return this.context.session.getGroupService().modifyGroupDetailInfoV2(param, 0);
|
||||
}
|
||||
|
||||
async setGroupSearch(groupCode: string, option: {
|
||||
noCodeFingerOpenFlag?: number;
|
||||
noFingerOpenFlag?: number;
|
||||
}) {
|
||||
let param = createGroupDetailInfoV2Param(groupCode);
|
||||
if (option.noCodeFingerOpenFlag) {
|
||||
param.filter.noCodeFingerOpenFlag = 1;
|
||||
param.modifyInfo.noCodeFingerOpenFlag = option.noCodeFingerOpenFlag;
|
||||
}
|
||||
if (option.noFingerOpenFlag) {
|
||||
param.filter.noFingerOpenFlag = 1;
|
||||
param.modifyInfo.noFingerOpenFlag = option.noFingerOpenFlag;
|
||||
}
|
||||
return this.context.session.getGroupService().modifyGroupDetailInfoV2(param, 0);
|
||||
}
|
||||
|
||||
async getGroups(forced: boolean = false) {
|
||||
const [, , groupList] = await this.core.eventWrapper.callNormalEventV2(
|
||||
'NodeIKernelGroupService/getGroupList',
|
||||
|
245
src/core/data/group.ts
Normal file
245
src/core/data/group.ts
Normal file
@@ -0,0 +1,245 @@
|
||||
import { GroupDetailInfoV2Param, GroupExtInfo, GroupExtFilter } from "../types";
|
||||
|
||||
export function createGroupDetailInfoV2Param(group_code: string): GroupDetailInfoV2Param {
|
||||
return {
|
||||
groupCode: group_code,
|
||||
filter:
|
||||
{
|
||||
noCodeFingerOpenFlag: 0,
|
||||
noFingerOpenFlag: 0,
|
||||
groupName: 0,
|
||||
classExt: 0,
|
||||
classText: 0,
|
||||
fingerMemo: 0,
|
||||
richFingerMemo: 0,
|
||||
tagRecord: 0,
|
||||
groupGeoInfo:
|
||||
{
|
||||
ownerUid: 0,
|
||||
setTime: 0,
|
||||
cityId: 0,
|
||||
longitude: 0,
|
||||
latitude: 0,
|
||||
geoContent: 0,
|
||||
poiId: 0
|
||||
},
|
||||
groupExtAdminNum: 0,
|
||||
flag: 0,
|
||||
groupMemo: 0,
|
||||
groupAioSkinUrl: 0,
|
||||
groupBoardSkinUrl: 0,
|
||||
groupCoverSkinUrl: 0,
|
||||
groupGrade: 0,
|
||||
activeMemberNum: 0,
|
||||
certificationType: 0,
|
||||
certificationText: 0,
|
||||
groupNewGuideLines:
|
||||
{
|
||||
enabled: 0,
|
||||
content: 0
|
||||
},
|
||||
groupFace: 0,
|
||||
addOption: 0,
|
||||
shutUpTime: 0,
|
||||
groupTypeFlag: 0,
|
||||
appPrivilegeFlag: 0,
|
||||
appPrivilegeMask: 0,
|
||||
groupExtOnly:
|
||||
{
|
||||
tribeId: 0,
|
||||
moneyForAddGroup: 0
|
||||
}, groupSecLevel: 0,
|
||||
groupSecLevelInfo: 0,
|
||||
subscriptionUin: 0,
|
||||
subscriptionUid: "",
|
||||
allowMemberInvite: 0,
|
||||
groupQuestion: 0,
|
||||
groupAnswer: 0,
|
||||
groupFlagExt3: 0,
|
||||
groupFlagExt3Mask: 0,
|
||||
groupOpenAppid: 0,
|
||||
rootId: 0,
|
||||
msgLimitFrequency: 0,
|
||||
hlGuildAppid: 0,
|
||||
hlGuildSubType: 0,
|
||||
hlGuildOrgId: 0,
|
||||
groupFlagExt4: 0,
|
||||
groupFlagExt4Mask: 0,
|
||||
groupSchoolInfo: {
|
||||
location: 0,
|
||||
grade: 0,
|
||||
school: 0
|
||||
},
|
||||
groupCardPrefix:
|
||||
{
|
||||
introduction: 0,
|
||||
rptPrefix: 0
|
||||
}, allianceId: 0,
|
||||
groupFlagPro1: 0,
|
||||
groupFlagPro1Mask: 0
|
||||
},
|
||||
modifyInfo: {
|
||||
noCodeFingerOpenFlag: 0,
|
||||
noFingerOpenFlag: 0,
|
||||
groupName: "",
|
||||
classExt: 0,
|
||||
classText: "",
|
||||
fingerMemo: "",
|
||||
richFingerMemo: "",
|
||||
tagRecord: [],
|
||||
groupGeoInfo: {
|
||||
ownerUid: "",
|
||||
SetTime: 0,
|
||||
CityId: 0,
|
||||
Longitude: "",
|
||||
Latitude: "",
|
||||
GeoContent: "",
|
||||
poiId: ""
|
||||
},
|
||||
groupExtAdminNum: 0,
|
||||
flag: 0,
|
||||
groupMemo: "",
|
||||
groupAioSkinUrl: "",
|
||||
groupBoardSkinUrl: "",
|
||||
groupCoverSkinUrl: "",
|
||||
groupGrade: 0,
|
||||
activeMemberNum: 0,
|
||||
certificationType: 0,
|
||||
certificationText: "",
|
||||
groupNewGuideLines: {
|
||||
enabled: false,
|
||||
content: ""
|
||||
}, groupFace: 0,
|
||||
addOption: 0,
|
||||
shutUpTime: 0,
|
||||
groupTypeFlag: 0,
|
||||
appPrivilegeFlag: 0,
|
||||
appPrivilegeMask: 0,
|
||||
groupExtOnly: {
|
||||
tribeId: 0,
|
||||
moneyForAddGroup: 0
|
||||
},
|
||||
groupSecLevel: 0,
|
||||
groupSecLevelInfo: 0,
|
||||
subscriptionUin: "",
|
||||
subscriptionUid: "",
|
||||
allowMemberInvite: 0,
|
||||
groupQuestion: "",
|
||||
groupAnswer: "",
|
||||
groupFlagExt3: 0,
|
||||
groupFlagExt3Mask: 0,
|
||||
groupOpenAppid: 0,
|
||||
rootId: "",
|
||||
msgLimitFrequency: 0,
|
||||
hlGuildAppid: 0,
|
||||
hlGuildSubType: 0,
|
||||
hlGuildOrgId: 0,
|
||||
groupFlagExt4: 0,
|
||||
groupFlagExt4Mask: 0,
|
||||
groupSchoolInfo: {
|
||||
location: "",
|
||||
grade: 0,
|
||||
school: ""
|
||||
},
|
||||
groupCardPrefix:
|
||||
{
|
||||
introduction: "",
|
||||
rptPrefix: []
|
||||
},
|
||||
allianceId: "",
|
||||
groupFlagPro1: 0,
|
||||
groupFlagPro1Mask: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
export function createGroupExtInfo(group_code: string): GroupExtInfo {
|
||||
return {
|
||||
groupCode: group_code,
|
||||
resultCode: 0,
|
||||
extInfo: {
|
||||
groupInfoExtSeq: 0,
|
||||
reserve: 0,
|
||||
luckyWordId: '',
|
||||
lightCharNum: 0,
|
||||
luckyWord: '',
|
||||
starId: 0,
|
||||
essentialMsgSwitch: 0,
|
||||
todoSeq: 0,
|
||||
blacklistExpireTime: 0,
|
||||
isLimitGroupRtc: 0,
|
||||
companyId: 0,
|
||||
hasGroupCustomPortrait: 0,
|
||||
bindGuildId: '',
|
||||
groupOwnerId: {
|
||||
memberUin: '',
|
||||
memberUid: '',
|
||||
memberQid: '',
|
||||
},
|
||||
essentialMsgPrivilege: 0,
|
||||
msgEventSeq: '',
|
||||
inviteRobotSwitch: 0,
|
||||
gangUpId: '',
|
||||
qqMusicMedalSwitch: 0,
|
||||
showPlayTogetherSwitch: 0,
|
||||
groupFlagPro1: '',
|
||||
groupBindGuildIds: {
|
||||
guildIds: [],
|
||||
},
|
||||
viewedMsgDisappearTime: '',
|
||||
groupExtFlameData: {
|
||||
switchState: 0,
|
||||
state: 0,
|
||||
dayNums: [],
|
||||
version: 0,
|
||||
updateTime: '',
|
||||
isDisplayDayNum: false,
|
||||
},
|
||||
groupBindGuildSwitch: 0,
|
||||
groupAioBindGuildId: '',
|
||||
groupExcludeGuildIds: {
|
||||
guildIds: [],
|
||||
},
|
||||
fullGroupExpansionSwitch: 0,
|
||||
fullGroupExpansionSeq: '',
|
||||
inviteRobotMemberSwitch: 0,
|
||||
inviteRobotMemberExamine: 0,
|
||||
groupSquareSwitch: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
export function createGroupExtFilter(): GroupExtFilter {
|
||||
return {
|
||||
groupInfoExtSeq: 0,
|
||||
reserve: 0,
|
||||
luckyWordId: 0,
|
||||
lightCharNum: 0,
|
||||
luckyWord: 0,
|
||||
starId: 0,
|
||||
essentialMsgSwitch: 0,
|
||||
todoSeq: 0,
|
||||
blacklistExpireTime: 0,
|
||||
isLimitGroupRtc: 0,
|
||||
companyId: 0,
|
||||
hasGroupCustomPortrait: 0,
|
||||
bindGuildId: 0,
|
||||
groupOwnerId: 0,
|
||||
essentialMsgPrivilege: 0,
|
||||
msgEventSeq: 0,
|
||||
inviteRobotSwitch: 0,
|
||||
gangUpId: 0,
|
||||
qqMusicMedalSwitch: 0,
|
||||
showPlayTogetherSwitch: 0,
|
||||
groupFlagPro1: 0,
|
||||
groupBindGuildIds: 0,
|
||||
viewedMsgDisappearTime: 0,
|
||||
groupExtFlameData: 0,
|
||||
groupBindGuildSwitch: 0,
|
||||
groupAioBindGuildId: 0,
|
||||
groupExcludeGuildIds: 0,
|
||||
fullGroupExpansionSwitch: 0,
|
||||
fullGroupExpansionSeq: 0,
|
||||
inviteRobotMemberSwitch: 0,
|
||||
inviteRobotMemberExamine: 0,
|
||||
groupSquareSwitch: 0,
|
||||
}
|
||||
};
|
1
src/core/data/index.ts
Normal file
1
src/core/data/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./group";
|
16
src/core/external/appid.json
vendored
16
src/core/external/appid.json
vendored
@@ -286,5 +286,21 @@
|
||||
"9.9.19-34958": {
|
||||
"appid": 537290742,
|
||||
"qua": "V1_WIN_NQ_9.9.19_34958_GW_B"
|
||||
},
|
||||
"3.2.17-35184": {
|
||||
"appid": 537291084,
|
||||
"qua": "V1_LNX_NQ_3.2.17_35184_GW_B"
|
||||
},
|
||||
"9.9.19-35184": {
|
||||
"appid": 537291048,
|
||||
"qua": "V1_WIN_NQ_9.9.19_35184_GW_B"
|
||||
},
|
||||
"3.2.17-35341": {
|
||||
"appid": 537291383,
|
||||
"qua": "V1_LNX_NQ_3.2.17_35341_GW_B"
|
||||
},
|
||||
"9.9.19-35341": {
|
||||
"appid": 537291347,
|
||||
"qua": "V1_WIN_NQ_9.9.19_35341_GW_B"
|
||||
}
|
||||
}
|
24
src/core/external/offset.json
vendored
24
src/core/external/offset.json
vendored
@@ -366,5 +366,29 @@
|
||||
"9.9.19-34958-x64": {
|
||||
"send": "3BDD8D0",
|
||||
"recv": "3BE20D0"
|
||||
},
|
||||
"3.2.17-35184-x64": {
|
||||
"send": "AE0DDE0",
|
||||
"recv": "AE11800"
|
||||
},
|
||||
"3.2.17-35184-arm64": {
|
||||
"send": "7776028",
|
||||
"recv": "7779958"
|
||||
},
|
||||
"9.9.19-35184-x64": {
|
||||
"send": "3BE5A10",
|
||||
"recv": "3BEA210"
|
||||
},
|
||||
"9.9.19-35341-x64": {
|
||||
"send": "3BF1D50",
|
||||
"recv": "3BF6550"
|
||||
},
|
||||
"3.2.17-35341-x64": {
|
||||
"send": "AE2F700",
|
||||
"recv": "AE33120"
|
||||
},
|
||||
"3.2.17-35341-arm64": {
|
||||
"send": "778D840",
|
||||
"recv": "7791170"
|
||||
}
|
||||
}
|
@@ -30,13 +30,8 @@ export class PacketOperationContext {
|
||||
return await this.context.client.sendOidbPacket(pkt, rsp);
|
||||
}
|
||||
|
||||
async GroupPoke(groupUin: number, uin: number) {
|
||||
const req = trans.SendPoke.build(uin, groupUin);
|
||||
await this.context.client.sendOidbPacket(req);
|
||||
}
|
||||
|
||||
async FriendPoke(uin: number) {
|
||||
const req = trans.SendPoke.build(uin);
|
||||
async SendPoke(is_group: boolean, peer: number, target?: number) {
|
||||
const req = trans.SendPoke.build(is_group, peer, target ?? peer);
|
||||
await this.context.client.sendOidbPacket(req);
|
||||
}
|
||||
|
||||
|
@@ -8,13 +8,13 @@ class SendPoke extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
|
||||
super();
|
||||
}
|
||||
|
||||
build(peer: number, group?: number): OidbPacket {
|
||||
const data = new NapProtoMsg(proto.OidbSvcTrpcTcp0XED3_1).encode({
|
||||
uin: peer,
|
||||
groupUin: group,
|
||||
friendUin: group ?? peer,
|
||||
ext: 0
|
||||
});
|
||||
build(is_group: boolean, peer: number, target: number): OidbPacket {
|
||||
const payload = {
|
||||
uin: target,
|
||||
ext: 0,
|
||||
...(is_group ? { groupUin: peer } : { friendUin: peer })
|
||||
};
|
||||
const data = new NapProtoMsg(proto.OidbSvcTrpcTcp0XED3_1).encode(payload);
|
||||
return OidbBase.build(0xED3, 1, data);
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@ class OidbBase extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
|
||||
super();
|
||||
}
|
||||
|
||||
build(cmd: number, subCmd: number, body: Uint8Array, isUid: boolean = true, isLafter: boolean = false): OidbPacket {
|
||||
build(cmd: number, subCmd: number, body: Uint8Array, isUid: boolean = true, _isLafter: boolean = false): OidbPacket {
|
||||
const data = new NapProtoMsg(proto.OidbSvcTrpcTcpBase).encode({
|
||||
command: cmd,
|
||||
subCommand: subCmd,
|
||||
|
@@ -8,10 +8,22 @@ import {
|
||||
GroupNotifyMsgType,
|
||||
NTGroupRequestOperateTypes,
|
||||
KickMemberV2Req,
|
||||
GroupDetailInfoV2Param,
|
||||
GroupExtInfo,
|
||||
GroupExtFilter,
|
||||
} from '@/core/types';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
|
||||
export interface NodeIKernelGroupService {
|
||||
|
||||
modifyGroupExtInfoV2(groupExtInfo: GroupExtInfo, groupExtFilter: GroupExtFilter): Promise<GeneralCallResult &
|
||||
{
|
||||
result: {
|
||||
groupCode: string,
|
||||
result: number
|
||||
}
|
||||
}>;
|
||||
|
||||
// --->
|
||||
// 待启用 For Next Version 3.2.0
|
||||
// isTroopMember ? 0 : 111
|
||||
@@ -169,6 +181,9 @@ export interface NodeIKernelGroupService {
|
||||
|
||||
modifyGroupDetailInfo(groupCode: string, arg: unknown): void;
|
||||
|
||||
// 第二个参数在大多数情况为0 设置群成员权限 例如上传群文件权限和群成员付费/加入邀请加入时为8
|
||||
modifyGroupDetailInfoV2(param: GroupDetailInfoV2Param, arg: number): Promise<GeneralCallResult>;
|
||||
|
||||
setGroupMsgMask(groupCode: string, arg: unknown): void;
|
||||
|
||||
changeGroupShieldSettingTemp(groupCode: string, arg: unknown): void;
|
||||
|
@@ -1,4 +1,97 @@
|
||||
import { QQLevel, NTSex } from './user';
|
||||
export interface GroupExtInfo {
|
||||
groupCode: string;
|
||||
resultCode: number;
|
||||
extInfo: EXTInfo;
|
||||
}
|
||||
export interface GroupExtFilter {
|
||||
groupInfoExtSeq: number;
|
||||
reserve: number;
|
||||
luckyWordId: number;
|
||||
lightCharNum: number;
|
||||
luckyWord: number;
|
||||
starId: number;
|
||||
essentialMsgSwitch: number;
|
||||
todoSeq: number;
|
||||
blacklistExpireTime: number;
|
||||
isLimitGroupRtc: number;
|
||||
companyId: number;
|
||||
hasGroupCustomPortrait: number;
|
||||
bindGuildId: number;
|
||||
groupOwnerId: number;
|
||||
essentialMsgPrivilege: number;
|
||||
msgEventSeq: number;
|
||||
inviteRobotSwitch: number;
|
||||
gangUpId: number;
|
||||
qqMusicMedalSwitch: number;
|
||||
showPlayTogetherSwitch: number;
|
||||
groupFlagPro1: number;
|
||||
groupBindGuildIds: number;
|
||||
viewedMsgDisappearTime: number;
|
||||
groupExtFlameData: number;
|
||||
groupBindGuildSwitch: number;
|
||||
groupAioBindGuildId: number;
|
||||
groupExcludeGuildIds: number;
|
||||
fullGroupExpansionSwitch: number;
|
||||
fullGroupExpansionSeq: number;
|
||||
inviteRobotMemberSwitch: number;
|
||||
inviteRobotMemberExamine: number;
|
||||
groupSquareSwitch: number;
|
||||
};
|
||||
|
||||
export interface EXTInfo {
|
||||
groupInfoExtSeq: number;
|
||||
reserve: number;
|
||||
luckyWordId: string;
|
||||
lightCharNum: number;
|
||||
luckyWord: string;
|
||||
starId: number;
|
||||
essentialMsgSwitch: number;
|
||||
todoSeq: number;
|
||||
blacklistExpireTime: number;
|
||||
isLimitGroupRtc: number;
|
||||
companyId: number;
|
||||
hasGroupCustomPortrait: number;
|
||||
bindGuildId: string;
|
||||
groupOwnerId: GroupOwnerID;
|
||||
essentialMsgPrivilege: number;
|
||||
msgEventSeq: string;
|
||||
inviteRobotSwitch: number;
|
||||
gangUpId: string;
|
||||
qqMusicMedalSwitch: number;
|
||||
showPlayTogetherSwitch: number;
|
||||
groupFlagPro1: string;
|
||||
groupBindGuildIds: GroupGuildIDS;
|
||||
viewedMsgDisappearTime: string;
|
||||
groupExtFlameData: GroupEXTFlameData;
|
||||
groupBindGuildSwitch: number;
|
||||
groupAioBindGuildId: string;
|
||||
groupExcludeGuildIds: GroupGuildIDS;
|
||||
fullGroupExpansionSwitch: number;
|
||||
fullGroupExpansionSeq: string;
|
||||
inviteRobotMemberSwitch: number;
|
||||
inviteRobotMemberExamine: number;
|
||||
groupSquareSwitch: number;
|
||||
}
|
||||
|
||||
export interface GroupGuildIDS {
|
||||
guildIds: any[];
|
||||
}
|
||||
|
||||
export interface GroupEXTFlameData {
|
||||
switchState: number;
|
||||
state: number;
|
||||
dayNums: any[];
|
||||
version: number;
|
||||
updateTime: string;
|
||||
isDisplayDayNum: boolean;
|
||||
}
|
||||
|
||||
export interface GroupOwnerID {
|
||||
memberUin: string;
|
||||
memberUid: string;
|
||||
memberQid: string;
|
||||
}
|
||||
|
||||
export interface KickMemberInfo {
|
||||
optFlag: number;
|
||||
@@ -7,6 +100,185 @@ export interface KickMemberInfo {
|
||||
optBytesMsg: string;
|
||||
}
|
||||
|
||||
|
||||
export interface GroupDetailInfoV2Param {
|
||||
groupCode: string;
|
||||
filter: Filter;
|
||||
modifyInfo: ModifyInfo;
|
||||
}
|
||||
|
||||
export interface Filter {
|
||||
noCodeFingerOpenFlag: number;
|
||||
noFingerOpenFlag: number;
|
||||
groupName: number;
|
||||
classExt: number;
|
||||
classText: number;
|
||||
fingerMemo: number;
|
||||
richFingerMemo: number;
|
||||
tagRecord: number;
|
||||
groupGeoInfo: FilterGroupGeoInfo;
|
||||
groupExtAdminNum: number;
|
||||
flag: number;
|
||||
groupMemo: number;
|
||||
groupAioSkinUrl: number;
|
||||
groupBoardSkinUrl: number;
|
||||
groupCoverSkinUrl: number;
|
||||
groupGrade: number;
|
||||
activeMemberNum: number;
|
||||
certificationType: number;
|
||||
certificationText: number;
|
||||
groupNewGuideLines: FilterGroupNewGuideLines;
|
||||
groupFace: number;
|
||||
addOption: number;
|
||||
shutUpTime: number;
|
||||
groupTypeFlag: number;
|
||||
appPrivilegeFlag: number;
|
||||
appPrivilegeMask: number;
|
||||
groupExtOnly: GroupEXTOnly;
|
||||
groupSecLevel: number;
|
||||
groupSecLevelInfo: number;
|
||||
subscriptionUin: number;
|
||||
subscriptionUid: string;
|
||||
allowMemberInvite: number;
|
||||
groupQuestion: number;
|
||||
groupAnswer: number;
|
||||
groupFlagExt3: number;
|
||||
groupFlagExt3Mask: number;
|
||||
groupOpenAppid: number;
|
||||
rootId: number;
|
||||
msgLimitFrequency: number;
|
||||
hlGuildAppid: number;
|
||||
hlGuildSubType: number;
|
||||
hlGuildOrgId: number;
|
||||
groupFlagExt4: number;
|
||||
groupFlagExt4Mask: number;
|
||||
groupSchoolInfo: FilterGroupSchoolInfo;
|
||||
groupCardPrefix: FilterGroupCardPrefix;
|
||||
allianceId: number;
|
||||
groupFlagPro1: number;
|
||||
groupFlagPro1Mask: number;
|
||||
}
|
||||
|
||||
export interface FilterGroupCardPrefix {
|
||||
introduction: number;
|
||||
rptPrefix: number;
|
||||
}
|
||||
|
||||
export interface GroupEXTOnly {
|
||||
tribeId: number;
|
||||
moneyForAddGroup: number;
|
||||
}
|
||||
|
||||
export interface FilterGroupGeoInfo {
|
||||
ownerUid: number;
|
||||
setTime: number;
|
||||
cityId: number;
|
||||
longitude: number;
|
||||
latitude: number;
|
||||
geoContent: number;
|
||||
poiId: number;
|
||||
}
|
||||
|
||||
export interface FilterGroupNewGuideLines {
|
||||
enabled: number;
|
||||
content: number;
|
||||
}
|
||||
|
||||
export interface FilterGroupSchoolInfo {
|
||||
location: number;
|
||||
grade: number;
|
||||
school: number;
|
||||
}
|
||||
|
||||
export interface ModifyInfo {
|
||||
noCodeFingerOpenFlag: number;
|
||||
noFingerOpenFlag: number;
|
||||
groupName: string;
|
||||
classExt: number;
|
||||
classText: string;
|
||||
fingerMemo: string;
|
||||
richFingerMemo: string;
|
||||
tagRecord: any[];
|
||||
groupGeoInfo: ModifyInfoGroupGeoInfo;
|
||||
groupExtAdminNum: number;
|
||||
flag: number;
|
||||
groupMemo: string;
|
||||
groupAioSkinUrl: string;
|
||||
groupBoardSkinUrl: string;
|
||||
groupCoverSkinUrl: string;
|
||||
groupGrade: number;
|
||||
activeMemberNum: number;
|
||||
certificationType: number;
|
||||
certificationText: string;
|
||||
groupNewGuideLines: ModifyInfoGroupNewGuideLines;
|
||||
groupFace: number;
|
||||
addOption: number;// 0 空设置 1 任何人都可以进入 2 需要管理员批准 3 不允许任何人入群 4 问题进入答案 5 问题管理员批准
|
||||
shutUpTime: number;
|
||||
groupTypeFlag: number;
|
||||
appPrivilegeFlag: number;
|
||||
// 需要管理员审核
|
||||
// 0000 0000 0000 0000 0000 0000 0000
|
||||
// 无需审核入群
|
||||
// 0000 0001 0000 0000 0000 0000 0000
|
||||
// 成员数100内无审核
|
||||
// 0100 0000 0000 0000 0000 0000 0000
|
||||
// 禁用 群成员邀请好友
|
||||
// 0100 0000 0000 0000 0000 0000 0000
|
||||
|
||||
appPrivilegeMask: number;
|
||||
// 0110 0001 0000 0000 0000 0000 0000
|
||||
// 101711872
|
||||
groupExtOnly: GroupEXTOnly;
|
||||
groupSecLevel: number;
|
||||
groupSecLevelInfo: number;
|
||||
subscriptionUin: string;
|
||||
subscriptionUid: string;
|
||||
allowMemberInvite: number;
|
||||
groupQuestion: string;
|
||||
groupAnswer: string;
|
||||
groupFlagExt3: number;
|
||||
groupFlagExt3Mask: number;
|
||||
groupOpenAppid: number;
|
||||
rootId: string;
|
||||
msgLimitFrequency: number;
|
||||
hlGuildAppid: number;
|
||||
hlGuildSubType: number;
|
||||
hlGuildOrgId: number;
|
||||
groupFlagExt4: number;
|
||||
groupFlagExt4Mask: number;
|
||||
groupSchoolInfo: ModifyInfoGroupSchoolInfo;
|
||||
groupCardPrefix: ModifyInfoGroupCardPrefix;
|
||||
allianceId: string;
|
||||
groupFlagPro1: number;
|
||||
groupFlagPro1Mask: number;
|
||||
}
|
||||
|
||||
export interface ModifyInfoGroupCardPrefix {
|
||||
introduction: string;
|
||||
rptPrefix: any[];
|
||||
}
|
||||
|
||||
export interface ModifyInfoGroupGeoInfo {
|
||||
ownerUid: string;
|
||||
SetTime: number;
|
||||
CityId: number;
|
||||
Longitude: string;
|
||||
Latitude: string;
|
||||
GeoContent: string;
|
||||
poiId: string;
|
||||
}
|
||||
|
||||
export interface ModifyInfoGroupNewGuideLines {
|
||||
enabled: boolean;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface ModifyInfoGroupSchoolInfo {
|
||||
location: string;
|
||||
grade: number;
|
||||
school: string;
|
||||
}
|
||||
|
||||
// 获取群详细信息的来源类型
|
||||
export enum GroupInfoSource {
|
||||
KUNSPECIFIED,
|
||||
|
28
src/onebot/action/extends/SetGroupAddOption.ts
Normal file
28
src/onebot/action/extends/SetGroupAddOption.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { OneBotAction } from '@/onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const SchemaData = Type.Object({
|
||||
group_id: Type.String(),
|
||||
add_type: Type.Number(),
|
||||
group_question: Type.Optional(Type.String()),
|
||||
group_answer: Type.Optional(Type.String()),
|
||||
});
|
||||
|
||||
type Payload = Static<typeof SchemaData>;
|
||||
|
||||
export default class SetGroupAddOption extends OneBotAction<Payload, null> {
|
||||
override actionName = ActionName.SetGroupAddOption;
|
||||
override payloadSchema = SchemaData;
|
||||
async _handle(payload: Payload): Promise<null> {
|
||||
let ret = await this.core.apis.GroupApi.setGroupAddOption(payload.group_id, {
|
||||
addOption: payload.add_type,
|
||||
groupQuestion: payload.group_question,
|
||||
groupAnswer: payload.group_answer,
|
||||
});
|
||||
if (ret.result != 0) {
|
||||
throw new Error(`设置群添加选项失败, ${ret.result}:${ret.errMsg}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
23
src/onebot/action/extends/SetGroupKickMembers.ts
Normal file
23
src/onebot/action/extends/SetGroupKickMembers.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { OneBotAction } from '@/onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const SchemaData = Type.Object({
|
||||
group_id: Type.String(),
|
||||
user_id: Type.Array(Type.String()),
|
||||
reject_add_request: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
|
||||
});
|
||||
|
||||
type Payload = Static<typeof SchemaData>;
|
||||
|
||||
export default class SetGroupKickMembers extends OneBotAction<Payload, null> {
|
||||
override actionName = ActionName.SetGroupKickMembers;
|
||||
override payloadSchema = SchemaData;
|
||||
|
||||
async _handle(payload: Payload): Promise<null> {
|
||||
const rejectReq = payload.reject_add_request?.toString() == 'true';
|
||||
const uids: string[] = await Promise.all(payload.user_id.map(async uin => await this.core.apis.UserApi.getUidByUinV2(uin)));
|
||||
await this.core.apis.GroupApi.kickMember(payload.group_id.toString(), uids.filter(uid => !!uid), rejectReq);
|
||||
return null;
|
||||
}
|
||||
}
|
27
src/onebot/action/extends/SetGroupRobotAddOption.ts
Normal file
27
src/onebot/action/extends/SetGroupRobotAddOption.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { OneBotAction } from '@/onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const SchemaData = Type.Object({
|
||||
group_id: Type.String(),
|
||||
robot_member_switch: Type.Optional(Type.Number()),
|
||||
robot_member_examine: Type.Optional(Type.Number()),
|
||||
});
|
||||
|
||||
type Payload = Static<typeof SchemaData>;
|
||||
|
||||
export default class SetGroupRobotAddOption extends OneBotAction<Payload, null> {
|
||||
override actionName = ActionName.SetGroupRobotAddOption;
|
||||
override payloadSchema = SchemaData;
|
||||
async _handle(payload: Payload): Promise<null> {
|
||||
let ret = await this.core.apis.GroupApi.setGroupRobotAddOption(
|
||||
payload.group_id,
|
||||
payload.robot_member_switch,
|
||||
payload.robot_member_examine,
|
||||
);
|
||||
if (ret.result != 0) {
|
||||
throw new Error(`设置群机器人添加选项失败, ${ret.result}:${ret.errMsg}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
26
src/onebot/action/extends/SetGroupSearch.ts
Normal file
26
src/onebot/action/extends/SetGroupSearch.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { OneBotAction } from '@/onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const SchemaData = Type.Object({
|
||||
group_id: Type.String(),
|
||||
no_code_finger_open: Type.Optional(Type.Number()),
|
||||
no_finger_open: Type.Optional(Type.Number()),
|
||||
});
|
||||
|
||||
type Payload = Static<typeof SchemaData>;
|
||||
|
||||
export default class SetGroupSearch extends OneBotAction<Payload, null> {
|
||||
override actionName = ActionName.SetGroupSearch;
|
||||
override payloadSchema = SchemaData;
|
||||
async _handle(payload: Payload): Promise<null> {
|
||||
let ret = await this.core.apis.GroupApi.setGroupSearch(payload.group_id, {
|
||||
noCodeFingerOpenFlag: payload.no_code_finger_open,
|
||||
noFingerOpenFlag: payload.no_finger_open,
|
||||
});
|
||||
if (ret.result != 0) {
|
||||
throw new Error(`设置群搜索失败, ${ret.result}:${ret.errMsg}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
import { normalize, SendMsgBase } from '@/onebot/action/msg/SendMsg';
|
||||
import { ContextMode, normalize, ReturnDataType, SendMsgBase } from '@/onebot/action/msg/SendMsg';
|
||||
import { OB11PostSendMsg } from '@/onebot/types';
|
||||
import { ActionName } from '@/onebot/action/router';
|
||||
|
||||
@@ -19,8 +19,14 @@ export class GoCQHTTPSendForwardMsg extends GoCQHTTPSendForwardMsgBase {
|
||||
}
|
||||
export class GoCQHTTPSendPrivateForwardMsg extends GoCQHTTPSendForwardMsgBase {
|
||||
override actionName = ActionName.GoCQHTTP_SendPrivateForwardMsg;
|
||||
override async _handle(payload: OB11PostSendMsg): Promise<ReturnDataType> {
|
||||
return this.base_handle(payload, ContextMode.Private);
|
||||
}
|
||||
}
|
||||
|
||||
export class GoCQHTTPSendGroupForwardMsg extends GoCQHTTPSendForwardMsgBase {
|
||||
override actionName = ActionName.GoCQHTTP_SendGroupForwardMsg;
|
||||
override async _handle(payload: OB11PostSendMsg): Promise<ReturnDataType> {
|
||||
return this.base_handle(payload, ContextMode.Group);
|
||||
}
|
||||
}
|
||||
|
@@ -1,19 +0,0 @@
|
||||
import { ActionName } from '@/onebot/action/router';
|
||||
import { GetPacketStatusDepends } from '@/onebot/action/packet/GetPacketStatus';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const SchemaData = Type.Object({
|
||||
group_id: Type.Union([Type.Number(), Type.String()]),
|
||||
user_id: Type.Union([Type.Number(), Type.String()]),
|
||||
});
|
||||
|
||||
type Payload = Static<typeof SchemaData>;
|
||||
|
||||
export class GroupPoke extends GetPacketStatusDepends<Payload, void> {
|
||||
override actionName = ActionName.GroupPoke;
|
||||
override payloadSchema = SchemaData;
|
||||
|
||||
async _handle(payload: Payload) {
|
||||
await this.core.apis.PacketApi.pkt.operation.GroupPoke(+payload.group_id, +payload.user_id);
|
||||
}
|
||||
}
|
@@ -1,17 +1,19 @@
|
||||
import { ContextMode, SendMsgBase } from '@/onebot/action/msg/SendMsg';
|
||||
import { ContextMode, ReturnDataType, SendMsgBase } from '@/onebot/action/msg/SendMsg';
|
||||
import { ActionName, BaseCheckResult } from '@/onebot/action/router';
|
||||
import { OB11PostSendMsg } from '@/onebot/types';
|
||||
|
||||
// 未检测参数
|
||||
class SendGroupMsg extends SendMsgBase {
|
||||
override actionName = ActionName.SendGroupMsg;
|
||||
override contextMode: ContextMode = ContextMode.Group;
|
||||
|
||||
protected override async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
|
||||
delete payload.user_id;
|
||||
payload.message_type = 'group';
|
||||
return super.check(payload);
|
||||
}
|
||||
override async _handle(payload: OB11PostSendMsg): Promise<ReturnDataType> {
|
||||
return this.base_handle(payload, ContextMode.Group);
|
||||
}
|
||||
}
|
||||
|
||||
export default SendGroupMsg;
|
||||
|
@@ -78,7 +78,6 @@ import { GetGroupFileSystemInfo } from '@/onebot/action/go-cqhttp/GetGroupFileSy
|
||||
import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
|
||||
import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesByFolder';
|
||||
import { GetGroupSystemMsg } from './system/GetSystemMsg';
|
||||
import { GroupPoke } from './group/GroupPoke';
|
||||
import { GetUserStatus } from './extends/GetUserStatus';
|
||||
import { GetRkey } from './extends/GetRkey';
|
||||
import { SetSpecialTitle } from './extends/SetSpecialTitle';
|
||||
@@ -86,7 +85,6 @@ import { GetGroupShutList } from './group/GetGroupShutList';
|
||||
import { GetGroupMemberList } from './group/GetGroupMemberList';
|
||||
import { GetGroupFileUrl } from '@/onebot/action/file/GetGroupFileUrl';
|
||||
import { GetPacketStatus } from '@/onebot/action/packet/GetPacketStatus';
|
||||
import { FriendPoke } from '@/onebot/action/user/FriendPoke';
|
||||
import { GetCredentials } from './system/GetCredentials';
|
||||
import { SendGroupSign, SetGroupSign } from './extends/SetGroupSign';
|
||||
import { GoCQHTTPGetGroupAtAllRemain } from './go-cqhttp/GetGroupAtAllRemain';
|
||||
@@ -102,7 +100,7 @@ import { GetGuildList } from './guild/GetGuildList';
|
||||
import { GetGuildProfile } from './guild/GetGuildProfile';
|
||||
import { GetClientkey } from './extends/GetClientkey';
|
||||
import { SendPacket } from './extends/SendPacket';
|
||||
import { SendPoke } from '@/onebot/action/packet/SendPoke';
|
||||
import { FriendPoke, GroupPoke, SendPoke } from '@/onebot/action/packet/SendPoke';
|
||||
import { SetDiyOnlineStatus } from './extends/SetDiyOnlineStatus';
|
||||
import { BotExit } from './extends/BotExit';
|
||||
import { ClickInlineKeyboardButton } from './extends/ClickInlineKeyboardButton';
|
||||
@@ -118,10 +116,18 @@ import { CleanCache } from './system/CleanCache';
|
||||
import SetFriendRemark from './user/SetFriendRemark';
|
||||
import { SetDoubtFriendsAddRequest } from './new/SetDoubtFriendsAddRequest';
|
||||
import { GetDoubtFriendsAddRequest } from './new/GetDoubtFriendsAddRequest';
|
||||
import SetGroupAddOption from './extends/SetGroupAddOption';
|
||||
import SetGroupSearch from './extends/SetGroupSearch';
|
||||
import SetGroupRobotAddOption from './extends/SetGroupRobotAddOption';
|
||||
import SetGroupKickMembers from './extends/SetGroupKickMembers';
|
||||
|
||||
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
|
||||
|
||||
const actionHandlers = [
|
||||
new SetGroupKickMembers(obContext, core),
|
||||
new SetGroupAddOption(obContext, core),
|
||||
new SetGroupRobotAddOption(obContext, core),
|
||||
new SetGroupSearch(obContext, core),
|
||||
new SetDoubtFriendsAddRequest(obContext, core),
|
||||
new GetDoubtFriendsAddRequest(obContext, core),
|
||||
new SetFriendRemark(obContext, core),
|
||||
|
@@ -104,8 +104,6 @@ function getSpecialMsgNum(payload: OB11PostSendMsg, msgType: OB11MessageDataType
|
||||
}
|
||||
|
||||
export class SendMsgBase extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
|
||||
contextMode = ContextMode.Normal;
|
||||
|
||||
protected override async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
|
||||
const messages = normalize(payload.message);
|
||||
const nodeElementLength = getSpecialMsgNum(payload, OB11MessageDataType.node);
|
||||
@@ -117,12 +115,13 @@ export class SendMsgBase extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
|
||||
}
|
||||
return { valid: true };
|
||||
}
|
||||
|
||||
async _handle(payload: OB11PostSendMsg): Promise<ReturnDataType> {
|
||||
this.contextMode = ContextMode.Normal;
|
||||
if (payload.message_type === 'group') this.contextMode = ContextMode.Group;
|
||||
if (payload.message_type === 'private') this.contextMode = ContextMode.Private;
|
||||
const peer = await createContext(this.core, payload, this.contextMode);
|
||||
return this.base_handle(payload);
|
||||
}
|
||||
async base_handle(payload: OB11PostSendMsg, contextMode: ContextMode = ContextMode.Normal): Promise<ReturnDataType> {
|
||||
if (payload.message_type === 'group') contextMode = ContextMode.Group;
|
||||
if (payload.message_type === 'private') contextMode = ContextMode.Private;
|
||||
const peer = await createContext(this.core, payload, contextMode);
|
||||
|
||||
const messages = normalize(
|
||||
payload.message,
|
||||
|
@@ -1,16 +1,18 @@
|
||||
import { ContextMode, SendMsgBase } from './SendMsg';
|
||||
import { ContextMode, ReturnDataType, SendMsgBase } from './SendMsg';
|
||||
import { ActionName, BaseCheckResult } from '@/onebot/action/router';
|
||||
import { OB11PostSendMsg } from '@/onebot/types';
|
||||
|
||||
// 未检测参数
|
||||
class SendPrivateMsg extends SendMsgBase {
|
||||
override actionName = ActionName.SendPrivateMsg;
|
||||
override contextMode: ContextMode = ContextMode.Private;
|
||||
|
||||
protected override async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
|
||||
payload.message_type = 'private';
|
||||
return super.check(payload);
|
||||
}
|
||||
override async _handle(payload: OB11PostSendMsg): Promise<ReturnDataType> {
|
||||
return this.base_handle(payload, ContextMode.Private);
|
||||
}
|
||||
}
|
||||
|
||||
export default SendPrivateMsg;
|
||||
|
@@ -3,21 +3,36 @@ import { GetPacketStatusDepends } from '@/onebot/action/packet/GetPacketStatus';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const SchemaData = Type.Object({
|
||||
group_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
||||
user_id: Type.Union([Type.Number(), Type.String()]),
|
||||
group_id: Type.Optional(Type.String()),
|
||||
user_id: Type.Optional(Type.String()),
|
||||
target_id: Type.Optional(Type.String()),
|
||||
});
|
||||
|
||||
type Payload = Static<typeof SchemaData>;
|
||||
|
||||
export class SendPoke extends GetPacketStatusDepends<Payload, void> {
|
||||
override actionName = ActionName.SendPoke;
|
||||
export class SendPokeBase extends GetPacketStatusDepends<Payload, void> {
|
||||
override payloadSchema = SchemaData;
|
||||
|
||||
async _handle(payload: Payload) {
|
||||
if (payload.group_id) {
|
||||
await this.core.apis.PacketApi.pkt.operation.GroupPoke(+payload.group_id, +payload.user_id);
|
||||
} else {
|
||||
await this.core.apis.PacketApi.pkt.operation.FriendPoke(+payload.user_id);
|
||||
// 这里的 !! 可以传入空字符串 忽略这些数据有利用接口统一接口
|
||||
const target_id = !!payload.target_id ? payload.target_id : payload.user_id;
|
||||
const peer_id = !!payload.group_id ? payload.group_id : payload.user_id;
|
||||
|
||||
const is_group = !!payload.group_id;
|
||||
if (!target_id || !peer_id) {
|
||||
throw new Error('请检查参数,缺少 user_id 或 group_id');
|
||||
}
|
||||
|
||||
await this.core.apis.PacketApi.pkt.operation.SendPoke(is_group, +peer_id, +target_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class SendPoke extends SendPokeBase {
|
||||
override actionName = ActionName.SendPoke;
|
||||
}
|
||||
export class GroupPoke extends SendPokeBase {
|
||||
override actionName = ActionName.GroupPoke;
|
||||
}
|
||||
export class FriendPoke extends SendPokeBase {
|
||||
override actionName = ActionName.FriendPoke;
|
||||
}
|
||||
|
@@ -10,6 +10,10 @@ export interface InvalidCheckResult {
|
||||
}
|
||||
|
||||
export const ActionName = {
|
||||
SetGroupKickMembers: 'set_group_kick_members',
|
||||
SetGroupRobotAddOption: 'set_group_robot_add_option',
|
||||
SetGroupAddOption: 'set_group_add_option',
|
||||
SetGroupSearch: 'set_group_search',
|
||||
// new extends 完全差异OneBot类别
|
||||
GetDoubtFriendsAddRequest: 'get_doubt_friends_add_request',
|
||||
SetDoubtFriendsAddRequest: 'set_doubt_friends_add_request',
|
||||
@@ -59,7 +63,7 @@ export const ActionName = {
|
||||
GetStatus: 'get_status',
|
||||
GetVersionInfo: 'get_version_info',
|
||||
// Reboot : 'set_restart',
|
||||
CleanCache : 'clean_cache',
|
||||
CleanCache: 'clean_cache',
|
||||
Exit: 'bot_exit',
|
||||
// go-cqhttp
|
||||
SetQQProfile: 'set_qq_profile',
|
||||
|
@@ -1,18 +0,0 @@
|
||||
import { ActionName } from '@/onebot/action/router';
|
||||
import { GetPacketStatusDepends } from '@/onebot/action/packet/GetPacketStatus';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const SchemaData = Type.Object({
|
||||
user_id: Type.Union([Type.Number(), Type.String()])
|
||||
});
|
||||
|
||||
type Payload = Static<typeof SchemaData>;
|
||||
|
||||
export class FriendPoke extends GetPacketStatusDepends<Payload, void> {
|
||||
override actionName = ActionName.FriendPoke;
|
||||
override payloadSchema = SchemaData;
|
||||
|
||||
async _handle(payload: Payload) {
|
||||
await this.core.apis.PacketApi.pkt.operation.FriendPoke(+payload.user_id);
|
||||
}
|
||||
}
|
@@ -1209,7 +1209,6 @@ export class OneBotMsgApi {
|
||||
async waitGroupNotify(groupUin: string, memberUid?: string, operatorUid?: string) {
|
||||
const groupRole = this.core.apis.GroupApi.groupMemberCache.get(groupUin)?.get(this.core.selfInfo.uid.toString())?.role;
|
||||
const isAdminOrOwner = groupRole === 3 || groupRole === 4;
|
||||
|
||||
if (isAdminOrOwner && !operatorUid) {
|
||||
let dataNotify: GroupNotify | undefined;
|
||||
await this.core.eventWrapper.registerListen('NodeIKernelGroupListener/onGroupNotifiesUpdated',
|
||||
@@ -1239,7 +1238,7 @@ export class OneBotMsgApi {
|
||||
const operatorUid = await this.waitGroupNotify(
|
||||
groupChange.groupUin.toString(),
|
||||
groupChange.memberUid,
|
||||
groupChange.operatorInfo ? Buffer.from(groupChange.operatorInfo).toString() : ''
|
||||
groupChange.operatorInfo ? new TextDecoder('utf-8').decode(groupChange.operatorInfo) : undefined
|
||||
);
|
||||
return new OB11GroupIncreaseEvent(
|
||||
this.core,
|
||||
@@ -1251,13 +1250,42 @@ export class OneBotMsgApi {
|
||||
|
||||
} else if (SysMessage.contentHead.type == 34 && SysMessage.body?.msgContent) {
|
||||
const groupChange = new NapProtoMsg(GroupChange).decode(SysMessage.body.msgContent);
|
||||
// 自身被踢出时operatorInfo会是一个protobuf 否则大多数情况为一个string
|
||||
|
||||
let operator_uid_parse: string | undefined = undefined;
|
||||
if (groupChange.operatorInfo) {
|
||||
// 先判断是否可能是protobuf(自身被踢出或以0a开头)
|
||||
if (groupChange.decreaseType === 3 || Buffer.from(groupChange.operatorInfo).toString('hex').startsWith('0a')) {
|
||||
// 可能是protobuf,尝试解析
|
||||
try {
|
||||
operator_uid_parse = new NapProtoMsg(GroupChangeInfo).decode(groupChange.operatorInfo).operator?.operatorUid;
|
||||
} catch (error) {
|
||||
// protobuf解析失败,fallback到字符串解析
|
||||
try {
|
||||
const decoded = new TextDecoder('utf-8').decode(groupChange.operatorInfo);
|
||||
// 检查是否包含非ASCII字符,如果包含则丢弃
|
||||
const isAsciiOnly = [...decoded].every(char => char.charCodeAt(0) >= 32 && char.charCodeAt(0) <= 126);
|
||||
operator_uid_parse = isAsciiOnly ? decoded : '';
|
||||
} catch (e2) {
|
||||
operator_uid_parse = '';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 直接进行字符串解析
|
||||
try {
|
||||
const decoded = new TextDecoder('utf-8').decode(groupChange.operatorInfo);
|
||||
// 检查是否包含非ASCII字符,如果包含则丢弃
|
||||
const isAsciiOnly = [...decoded].every(char => char.charCodeAt(0) >= 32 && char.charCodeAt(0) <= 126);
|
||||
operator_uid_parse = isAsciiOnly ? decoded : '';
|
||||
} catch (e) {
|
||||
operator_uid_parse = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const operatorUid = await this.waitGroupNotify(
|
||||
groupChange.groupUin.toString(),
|
||||
groupChange.memberUid,
|
||||
groupChange.decreaseType === 3 && groupChange.operatorInfo ?
|
||||
new NapProtoMsg(GroupChangeInfo).decode(groupChange.operatorInfo).operator?.operatorUid :
|
||||
groupChange.operatorInfo?.toString()
|
||||
operator_uid_parse
|
||||
);
|
||||
if (groupChange.memberUid === this.core.selfInfo.uid) {
|
||||
setTimeout(() => {
|
||||
|
@@ -2,4 +2,5 @@ import { EventType, OneBotEvent } from '@/onebot/event/OneBotEvent';
|
||||
|
||||
export abstract class OB11BaseNoticeEvent extends OneBotEvent {
|
||||
post_type = EventType.NOTICE;
|
||||
}
|
||||
abstract notice_type: string;
|
||||
}
|
||||
|
6
src/onebot/event/request/OB11BaseRequestEvent.ts
Normal file
6
src/onebot/event/request/OB11BaseRequestEvent.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { EventType, OneBotEvent } from '@/onebot/event/OneBotEvent';
|
||||
|
||||
export abstract class OB11BaseRequestEvent extends OneBotEvent {
|
||||
readonly post_type = EventType.REQUEST;
|
||||
abstract request_type: string;
|
||||
}
|
@@ -1,10 +1,8 @@
|
||||
import { OB11BaseNoticeEvent } from '@/onebot/event/notice/OB11BaseNoticeEvent';
|
||||
import { EventType } from '@/onebot/event/OneBotEvent';
|
||||
import { NapCatCore } from '@/core';
|
||||
import { OB11BaseRequestEvent } from './OB11BaseRequestEvent';
|
||||
|
||||
export class OB11FriendRequestEvent extends OB11BaseNoticeEvent {
|
||||
override post_type = EventType.REQUEST;
|
||||
request_type = 'friend';
|
||||
export class OB11FriendRequestEvent extends OB11BaseRequestEvent {
|
||||
override request_type = 'friend';
|
||||
|
||||
user_id: number;
|
||||
comment: string;
|
||||
|
@@ -1,18 +1,18 @@
|
||||
import { OB11GroupNoticeEvent } from '@/onebot/event/notice/OB11GroupNoticeEvent';
|
||||
import { EventType } from '@/onebot/event/OneBotEvent';
|
||||
import { NapCatCore } from '@/core';
|
||||
import { OB11BaseRequestEvent } from './OB11BaseRequestEvent';
|
||||
|
||||
export class OB11GroupRequestEvent extends OB11GroupNoticeEvent {
|
||||
override post_type = EventType.REQUEST;
|
||||
request_type = 'group';
|
||||
export class OB11GroupRequestEvent extends OB11BaseRequestEvent {
|
||||
override readonly request_type = 'group' as const;
|
||||
|
||||
override user_id: number;
|
||||
group_id: number;
|
||||
user_id: number;
|
||||
comment: string;
|
||||
flag: string;
|
||||
sub_type: string;
|
||||
|
||||
constructor(core: NapCatCore, groupId: number, userId: number, sub_type: string, comment: string, flag: string) {
|
||||
super(core, groupId, userId);
|
||||
super(core);
|
||||
this.group_id = groupId;
|
||||
this.user_id = userId;
|
||||
this.sub_type = sub_type;
|
||||
this.comment = comment;
|
||||
|
@@ -282,7 +282,8 @@ export class NapCatOneBot11Adapter {
|
||||
}, 1, 10 * 60 * 1000);
|
||||
// 10分钟 超时
|
||||
const updatemsg = updatemsgs.find((e) => e.msgId === msg.msgId);
|
||||
if (updatemsg?.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS || updatemsg?.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS_NOSEQ) {
|
||||
// updatemsg?.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS_NOSEQ NOSEQ一般是服务器未下发SEQ 这意味着这条消息不应该推送network
|
||||
if (updatemsg?.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS) {
|
||||
updatemsg.id = MessageUnique.createUniqueMsgId(
|
||||
{
|
||||
chatType: updatemsg.chatType,
|
||||
|
@@ -47,6 +47,9 @@ export const CreateTerminalHandler: RequestHandler = async (req, res) => {
|
||||
if (isMacOS) {
|
||||
return sendError(res, 'MacOS不支持终端');
|
||||
}
|
||||
if ((await WebUiConfig.GetWebUIConfig()).token === 'napcat') {
|
||||
return sendError(res, '默认密码禁止创建终端');
|
||||
}
|
||||
try {
|
||||
const { cols, rows } = req.body;
|
||||
const { id } = terminalManager.createTerminal(cols, rows);
|
||||
|
@@ -9,7 +9,7 @@ Object.defineProperty(global, '__dirname', {
|
||||
// 注意:堆栈格式可能不同,请根据实际环境调整索引及正则表达式
|
||||
for (const line of stack) {
|
||||
const match = line.match(/\((.*):\d+:\d+\)/);
|
||||
if (match) {
|
||||
if (match?.[1]) {
|
||||
callerFile = match[1];
|
||||
if (!callerFile.includes('init-dynamic-dirname.ts')) {
|
||||
break;
|
||||
|
Reference in New Issue
Block a user