Compare commits

...

15 Commits

Author SHA1 Message Date
手瓜一十雪
57112c21a2 refactor: flag handle&onebot标准化 2024-12-05 14:17:09 +08:00
手瓜一十雪
0e8ceeb6c9 refactor: CardChangedEvent 2024-12-05 11:36:06 +08:00
手瓜一十雪
f52b8d1f04 feat: 30366 全平台通用性适配 2024-12-05 11:15:10 +08:00
手瓜一十雪
f374cc77ae chore: readme 2024-12-04 23:04:37 +08:00
手瓜一十雪
7c694e7fae chore: 跑路的规范/困难的实现 2024-12-04 23:03:46 +08:00
Mlikiowa
932ffc2673 release: v4.2.23 2024-12-04 14:18:02 +00:00
手瓜一十雪
3de5438139 fix: poke report 2024-12-04 22:16:59 +08:00
手瓜一十雪
c4b5f34271 fix: 兜底 防止进入影响速度 2024-12-04 22:02:11 +08:00
手瓜一十雪
22d3ac33a2 Refactor: 更新群组通知处理逻辑,优化数据结构和异步处理 2024-12-04 21:59:53 +08:00
Mlikiowa
2e5dd6535a release: v4.2.22 2024-12-04 13:18:58 +00:00
手瓜一十雪
eac58a2a50 fix: 9.9.17-30366 2024-12-04 21:04:24 +08:00
手瓜一十雪
e939ec0e52 fix: #597 2024-12-04 20:37:08 +08:00
Mlikiowa
5b17a14a2a release: v4.2.21 2024-12-04 11:49:26 +00:00
手瓜一十雪
8fb8c888f5 refactor: 移除未使用的uidCache和uinCache逻辑 2024-12-04 19:48:59 +08:00
Mlikiowa
4a2884509e release: v4.2.20 2024-12-04 11:46:12 +00:00
21 changed files with 237 additions and 139 deletions

View File

@@ -36,6 +36,13 @@ NapCatQQ 是现代化的基于 NTQQ 的 Bot 协议端实现
## 回家旅途 ## 回家旅途
[QQ Group](https://qm.qq.com/q/I6LU87a0Yq) [QQ Group](https://qm.qq.com/q/I6LU87a0Yq)
## 性能设计/协议标准
NapCat 已实现90+的OneBot/GoCQ标准接口,并提供兼容性保留接口,其设计理念遵守 无数据库/异步优先/后台刷新 的性能思想。
由此设计带来一系列好处,在开发中,获取群员列表通常小于50Ms,单条文本消息发送在320Ms以内,在1k+的群聊流程运行,同时带来一些副作用上报数据中大量使用Magic生成字段, 消息Id无法持久无法上报撤回消息原始内容。
NapCat在设计理念下遵守OneBot规范大多数要求并且积极改进,任何合理的标准化issue与pr将被接收。
## 感谢他们 ## 感谢他们
感谢 [Lagrange](https://github.com/LagrangeDev/Lagrange.Core) 对本项目的大力支持 参考部分代码 已获授权 感谢 [Lagrange](https://github.com/LagrangeDev/Lagrange.Core) 对本项目的大力支持 参考部分代码 已获授权

View File

@@ -4,7 +4,7 @@
"name": "NapCatQQ", "name": "NapCatQQ",
"slug": "NapCat.Framework", "slug": "NapCat.Framework",
"description": "高性能的 OneBot 11 协议实现", "description": "高性能的 OneBot 11 协议实现",
"version": "4.2.19", "version": "4.2.23",
"icon": "./logo.png", "icon": "./logo.png",
"authors": [ "authors": [
{ {

View File

@@ -2,7 +2,7 @@
"name": "napcat", "name": "napcat",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "4.2.19", "version": "4.2.23",
"scripts": { "scripts": {
"build:universal": "npm run build:webui && vite build --mode universal || exit 1", "build:universal": "npm run build:webui && vite build --mode universal || exit 1",
"build:framework": "npm run build:webui && vite build --mode framework || exit 1", "build:framework": "npm run build:webui && vite build --mode framework || exit 1",

View File

@@ -1 +1 @@
export const napCatVersion = '4.2.19'; export const napCatVersion = '4.2.23';

View File

@@ -1,4 +1,4 @@
import { FriendV2 } from '@/core/types'; import { FriendRequest, FriendV2 } from '@/core/types';
import { BuddyListReqType, InstanceContext, NapCatCore } from '@/core'; import { BuddyListReqType, InstanceContext, NapCatCore } from '@/core';
import { LimitedHashTable } from '@/common/message-unique'; import { LimitedHashTable } from '@/common/message-unique';
@@ -79,16 +79,10 @@ export class NTQQFriendApi {
return ret; return ret;
} }
async handleFriendRequest(flag: string, accept: boolean) { async handleFriendRequest(notify: FriendRequest, accept: boolean) {
const data = flag.split('|');
if (data.length < 2) {
return;
}
const friendUid = data[0];
const reqTime = data[1];
this.context.session.getBuddyService()?.approvalFriendRequest({ this.context.session.getBuddyService()?.approvalFriendRequest({
friendUid: friendUid, friendUid: notify.friendUid,
reqTime: reqTime, reqTime: notify.reqTime,
accept, accept,
}); });
} }

View File

@@ -7,6 +7,7 @@ import {
KickMemberV2Req, KickMemberV2Req,
MemberExtSourceType, MemberExtSourceType,
NapCatCore, NapCatCore,
GroupNotify,
} from '@/core'; } from '@/core';
import { isNumeric, solveAsyncProblem } from '@/common/helper'; import { isNumeric, solveAsyncProblem } from '@/common/helper';
import { LimitedHashTable } from '@/common/message-unique'; import { LimitedHashTable } from '@/common/message-unique';
@@ -120,7 +121,7 @@ export class NTQQGroupApi {
} }
return this.groupMemberCache; return this.groupMemberCache;
} }
async getGroupMember(groupCode: string | number, memberUinOrUid: string | number) { async getGroupMember(groupCode: string | number, memberUinOrUid: string | number) {
const groupCodeStr = groupCode.toString(); const groupCodeStr = groupCode.toString();
const memberUinOrUidStr = memberUinOrUid.toString(); const memberUinOrUidStr = memberUinOrUid.toString();
@@ -288,20 +289,15 @@ export class NTQQGroupApi {
return this.context.session.getGroupService().uploadGroupBulletinPic(groupCode, _Pskey, imageurl); return this.context.session.getGroupService().uploadGroupBulletinPic(groupCode, _Pskey, imageurl);
} }
async handleGroupRequest(flag: string, operateType: NTGroupRequestOperateTypes, reason?: string) { async handleGroupRequest(notify: GroupNotify, operateType: NTGroupRequestOperateTypes, reason?: string) {
const flagitem = flag.split('|');
const groupCode = flagitem[0];
const seq = flagitem[1];
const type = parseInt(flagitem[2]);
return this.context.session.getGroupService().operateSysNotify( return this.context.session.getGroupService().operateSysNotify(
false, false,
{ {
operateType: operateType, operateType: operateType,
targetMsg: { targetMsg: {
seq: seq, // 通知序列号 seq: notify.seq, // 通知序列号
type: type, type: notify.type,
groupCode: groupCode, groupCode: notify.group.groupCode,
postscript: reason ?? ' ', // 仅传空值可能导致处理失败,故默认给个空格 postscript: reason ?? ' ', // 仅传空值可能导致处理失败,故默认给个空格
}, },
}); });

View File

@@ -8,14 +8,10 @@ import { LRUCache } from '@/common/lru-cache';
export class NTQQUserApi { export class NTQQUserApi {
context: InstanceContext; context: InstanceContext;
core: NapCatCore; core: NapCatCore;
private uidCache: LRUCache<string, string>;
private uinCache: LRUCache<string, string>;
constructor(context: InstanceContext, core: NapCatCore) { constructor(context: InstanceContext, core: NapCatCore) {
this.context = context; this.context = context;
this.core = core; this.core = core;
this.uidCache = new LRUCache(1000);
this.uinCache = new LRUCache(1000);
} }
async getCoreAndBaseInfo(uids: string[]) { async getCoreAndBaseInfo(uids: string[]) {
@@ -174,8 +170,8 @@ export class NTQQUserApi {
} }
async getUidByUinV2(Uin: string) { async getUidByUinV2(Uin: string) {
if (this.uidCache.get(Uin)) { if (!Uin) {
return this.uidCache.get(Uin); return '';
} }
const services = [ const services = [
() => this.context.session.getUixConvertService().getUid([Uin]).then((data) => data.uidInfo.get(Uin)).catch(() => undefined), () => this.context.session.getUixConvertService().getUid([Uin]).then((data) => data.uidInfo.get(Uin)).catch(() => undefined),
@@ -188,16 +184,15 @@ export class NTQQUserApi {
for (const service of services) { for (const service of services) {
uid = await service(); uid = await service();
if (uid && uid.indexOf('*') == -1 && uid !== '') { if (uid && uid.indexOf('*') == -1 && uid !== '') {
this.uidCache.put(Uin, uid);
break; break;
} }
} }
return uid; return uid ?? '';
} }
async getUinByUidV2(Uid: string) { async getUinByUidV2(Uid: string) {
if (this.uinCache.get(Uid)) { if (!Uid) {
return this.uinCache.get(Uid); return '0';
} }
const services = [ const services = [
() => this.context.session.getUixConvertService().getUin([Uid]).then((data) => data.uinInfo.get(Uid)).catch(() => undefined), () => this.context.session.getUixConvertService().getUin([Uid]).then((data) => data.uinInfo.get(Uid)).catch(() => undefined),
@@ -211,11 +206,10 @@ export class NTQQUserApi {
for (const service of services) { for (const service of services) {
uin = await service(); uin = await service();
if (uin && uin !== '0' && uin !== '') { if (uin && uin !== '0' && uin !== '') {
this.uinCache.put(Uid, uin);
break; break;
} }
} }
return uin; return uin ?? '0';
} }
async getRecentContactListSnapShot(count: number) { async getRecentContactListSnapShot(count: number) {

View File

@@ -98,5 +98,17 @@
"6.9.61-29927": { "6.9.61-29927": {
"appid": 537255836, "appid": 537255836,
"qua": "V1_MAC_NQ_6.9.61_29927_GW_B" "qua": "V1_MAC_NQ_6.9.61_29927_GW_B"
},
"9.9.17-30366": {
"appid": 537258389,
"qua": "V1_WIN_NQ_9.9.17_30366_GW_B"
},
"3.2.15-30366": {
"appid": 537258413,
"qua": "V1_LNX_NQ_3.2.15_30366_GW_B"
},
"6.9.62-30366": {
"appid": 537258401,
"qua": "V1_MAC_NQ_6.9.62_30366_GW_B"
} }
} }

View File

@@ -102,5 +102,25 @@
"6.9.61-29927-arm64": { "6.9.61-29927-arm64": {
"send": "4038740", "send": "4038740",
"recv": "403AF58" "recv": "403AF58"
},
"9.9.17-30366-x64": {
"send": "39AB0B0",
"recv": "39AF4E4"
},
"3.2.15-30366-x64": {
"send": "A402380",
"recv": "A405C80"
},
"3.2.15-30366-arm64": {
"send": "70C3FA8",
"recv": "70C77E0"
},
"6.9.62-30366-x64": {
"send": "4669760",
"recv": "466BFCC"
},
"6.9.62-30366-arm64": {
"send": "4189770",
"recv": "418BF88"
} }
} }

View File

@@ -187,11 +187,11 @@ export interface NodeIKernelGroupService {
destroyGroup(groupCode: string): void; destroyGroup(groupCode: string): void;
getSingleScreenNotifies(doubted: boolean, start_seq: string, num: number): Promise<GeneralCallResult>; getSingleScreenNotifies(doubt: boolean, startSeq: string, count: number): Promise<GeneralCallResult>;
clearGroupNotifies(groupCode: string): void; clearGroupNotifies(groupCode: string): void;
getGroupNotifiesUnreadCount(unknown: boolean): Promise<GeneralCallResult>; getGroupNotifiesUnreadCount(doubt: boolean): Promise<GeneralCallResult>;
clearGroupNotifiesUnreadCount(doubt: boolean): void; clearGroupNotifiesUnreadCount(doubt: boolean): void;

View File

@@ -29,6 +29,7 @@ export interface TextElement {
} }
export interface FaceElement { export interface FaceElement {
pokeType?: number;
faceIndex: number; faceIndex: number;
faceType: FaceType; faceType: FaceType;
faceText?: string; faceText?: string;

View File

@@ -1,33 +1,37 @@
import { GroupNotifyMsgStatus } from '@/core'; import { GroupNotifyMsgStatus } from '@/core';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { Notify } from '@/onebot/types';
interface OB11GroupRequestNotify { export default class GetGroupAddRequest extends OneBotAction<null, Notify[] | null> {
group_id: number,
user_id: number,
flag: string
}
export default class GetGroupAddRequest extends OneBotAction<null, OB11GroupRequestNotify[] | null> {
actionName = ActionName.GetGroupIgnoreAddRequest; actionName = ActionName.GetGroupIgnoreAddRequest;
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> { async _handle(payload: null): Promise<Notify[] | null> {
const ignoredNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(true, 10); const NTQQUserApi = this.core.apis.UserApi;
const retData: any = { const NTQQGroupApi = this.core.apis.GroupApi;
join_requests: await Promise.all( const ignoredNotifies = await NTQQGroupApi.getSingleScreenNotifies(true, 10);
ignoredNotifies const retData: Notify[] = [];
.filter(notify => notify.type === 7)
.map(async SSNotify => ({ const notifyPromises = ignoredNotifies
request_id: SSNotify.group.groupCode + '|' + SSNotify.seq + '|' + SSNotify.type, .filter(notify => notify.type === 7)
requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid), .map(async SSNotify => {
requester_nick: SSNotify.user1?.nickName, const invitorUin = SSNotify.user1?.uid ? +await NTQQUserApi.getUinByUidV2(SSNotify.user1.uid) : 0;
group_id: SSNotify.group?.groupCode, const actorUin = SSNotify.user2?.uid ? +await NTQQUserApi.getUinByUidV2(SSNotify.user2.uid) : 0;
group_name: SSNotify.group?.groupName, retData.push({
checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE, request_id: +SSNotify.seq,
actor: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user2?.uid) || 0, invitor_uin: invitorUin,
}))), invitor_nick: SSNotify.user1?.nickName,
}; group_id: +SSNotify.group?.groupCode,
message: SSNotify?.postscript,
group_name: SSNotify.group?.groupName,
checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE,
actor: actorUin,
requester_nick: SSNotify.user1?.nickName,
});
});
await Promise.all(notifyPromises);
return retData; return retData;
} }
} }

View File

@@ -1,26 +1,44 @@
import { GroupNotifyMsgStatus } from '@/core'; import { GroupNotifyMsgStatus } from '@/core';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
export class GetGroupIgnoredNotifies extends OneBotAction<void, any> { import { Notify } from '@/onebot/types';
interface RetData {
InvitedRequest: Notify[];
join_requests: Notify[];
}
export class GetGroupIgnoredNotifies extends OneBotAction<void, RetData> {
actionName = ActionName.GetGroupIgnoredNotifies; actionName = ActionName.GetGroupIgnoredNotifies;
async _handle(payload: void) { async _handle(): Promise<RetData> {
const ignoredNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(true, 10); const SingleScreenNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(false, 50);
const retData: any = { const retData: RetData = { InvitedRequest: [], join_requests: [] };
join_requests: await Promise.all(
ignoredNotifies const notifyPromises = SingleScreenNotifies.map(async (SSNotify) => {
.filter(notify => notify.type === 7) const invitorUin = SSNotify.user1?.uid ? +await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1.uid) : 0;
.map(async SSNotify => ({ const actorUin = SSNotify.user2?.uid ? +await this.core.apis.UserApi.getUinByUidV2(SSNotify.user2.uid) : 0;
request_id: SSNotify.group.groupCode + '|' + SSNotify.seq + '|' + SSNotify.type, const commonData = {
requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid), request_id: +SSNotify.seq,
requester_nick: SSNotify.user1?.nickName, invitor_uin: invitorUin,
group_id: SSNotify.group?.groupCode, invitor_nick: SSNotify.user1?.nickName,
group_name: SSNotify.group?.groupName, group_id: +SSNotify.group?.groupCode,
checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE, message: SSNotify?.postscript,
actor: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user2?.uid) || 0, group_name: SSNotify.group?.groupName,
}))), checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE,
}; actor: actorUin,
requester_nick: SSNotify.user1?.nickName,
};
if (SSNotify.type === 1) {
retData.InvitedRequest.push(commonData);
} else if (SSNotify.type === 7) {
retData.join_requests.push(commonData);
}
});
await Promise.all(notifyPromises);
return retData; return retData;
} }
} }

View File

@@ -4,9 +4,9 @@ import { ActionName } from '@/onebot/action/router';
import { Static, Type } from '@sinclair/typebox'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({ const SchemaData = Type.Object({
flag: Type.String(), flag: Type.Union([Type.String(), Type.Number()]),
approve: Type.Optional(Type.Union([Type.Boolean(), Type.String()])), approve: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
reason: Type.Union([Type.String({ default: ' ' }), Type.Null()]), reason: Type.Optional(Type.Union([Type.String({ default: ' ' }), Type.Null()])),
}); });
type Payload = Static<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
@@ -18,10 +18,26 @@ export default class SetGroupAddRequest extends OneBotAction<Payload, null> {
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const flag = payload.flag.toString(); const flag = payload.flag.toString();
const approve = payload.approve?.toString() !== 'false'; const approve = payload.approve?.toString() !== 'false';
await this.core.apis.GroupApi.handleGroupRequest(flag, const reason = payload.reason ?? ' ';
let notify = await this.findNotify(flag);
if (!notify) {
throw new Error('No such request');
}
await this.core.apis.GroupApi.handleGroupRequest(
notify,
approve ? NTGroupRequestOperateTypes.KAGREE : NTGroupRequestOperateTypes.KREFUSE, approve ? NTGroupRequestOperateTypes.KAGREE : NTGroupRequestOperateTypes.KREFUSE,
payload.reason ?? ' ', reason,
); );
return null; return null;
} }
}
private async findNotify(flag: string) {
let notify = (await this.core.apis.GroupApi.getSingleScreenNotifies(false, 100)).find(e => e.seq == flag);
if (!notify) {
notify = (await this.core.apis.GroupApi.getSingleScreenNotifies(true, 100)).find(e => e.seq == flag);
}
return notify;
}
}

View File

@@ -1,38 +1,43 @@
import { GroupNotifyMsgStatus } from '@/core'; import { GroupNotifyMsgStatus } from '@/core';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
export class GetGroupSystemMsg extends OneBotAction<void, any> { import { Notify } from '@/onebot/types';
interface RetData {
InvitedRequest: Notify[];
join_requests: Notify[];
}
export class GetGroupSystemMsg extends OneBotAction<void, RetData> {
actionName = ActionName.GetGroupSystemMsg; actionName = ActionName.GetGroupSystemMsg;
async _handle() { async _handle(): Promise<RetData> {
const NTQQUserApi = this.core.apis.UserApi; const SingleScreenNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(false, 50);
const NTQQGroupApi = this.core.apis.GroupApi; const retData: RetData = { InvitedRequest: [], join_requests: [] };
// 默认10条 该api未完整实现 包括响应数据规范化 类型规范化
const SingleScreenNotifies = await NTQQGroupApi.getSingleScreenNotifies(false, 10); const notifyPromises = SingleScreenNotifies.map(async (SSNotify) => {
const retData: any = { InvitedRequest: [], join_requests: [] }; const invitorUin = SSNotify.user1?.uid ? +await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1.uid) : 0;
for (const SSNotify of SingleScreenNotifies) { const actorUin = SSNotify.user2?.uid ? +await this.core.apis.UserApi.getUinByUidV2(SSNotify.user2.uid) : 0;
if (SSNotify.type == 1) { const commonData = {
retData.InvitedRequest.push({ request_id: +SSNotify.seq,
request_id: SSNotify.group.groupCode + '|' + SSNotify.seq + '|' + SSNotify.type, invitor_uin: invitorUin,
invitor_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid), invitor_nick: SSNotify.user1?.nickName,
invitor_nick: SSNotify.user1?.nickName, group_id: +SSNotify.group?.groupCode,
group_id: SSNotify.group?.groupCode, message: SSNotify?.postscript,
group_name: SSNotify.group?.groupName, group_name: SSNotify.group?.groupName,
checked: SSNotify.status === GroupNotifyMsgStatus.KUNHANDLE ? false : true, checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE,
actor: await NTQQUserApi.getUinByUidV2(SSNotify.user2?.uid) || 0, actor: actorUin,
}); requester_nick: SSNotify.user1?.nickName,
} else if (SSNotify.type == 7) { };
retData.join_requests.push({
request_id: SSNotify.group.groupCode + '|' + SSNotify.seq + '|' + SSNotify.type, if (SSNotify.type === 1) {
requester_uin: await NTQQUserApi.getUinByUidV2(SSNotify.user1?.uid), retData.InvitedRequest.push(commonData);
requester_nick: SSNotify.user1?.nickName, } else if (SSNotify.type === 7) {
group_id: SSNotify.group?.groupCode, retData.join_requests.push(commonData);
group_name: SSNotify.group?.groupName,
checked: SSNotify.status === GroupNotifyMsgStatus.KUNHANDLE ? false : true,
actor: await NTQQUserApi.getUinByUidV2(SSNotify.user2?.uid) || 0,
});
} }
} });
await Promise.all(notifyPromises);
return retData; return retData;
} }

View File

@@ -3,7 +3,7 @@ import { ActionName } from '@/onebot/action/router';
import { Static, Type } from '@sinclair/typebox'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({ const SchemaData = Type.Object({
flag: Type.String(), flag: Type.Union([Type.String(), Type.Number()]),
approve: Type.Optional(Type.Union([Type.String(), Type.Boolean()])), approve: Type.Optional(Type.Union([Type.String(), Type.Boolean()])),
remark: Type.Optional(Type.String()) remark: Type.Optional(Type.String())
}); });
@@ -16,14 +16,13 @@ export default class SetFriendAddRequest extends OneBotAction<Payload, null> {
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const approve = payload.approve?.toString() !== 'false'; const approve = payload.approve?.toString() !== 'false';
await this.core.apis.FriendApi.handleFriendRequest(payload.flag, approve); let notify = (await this.core.apis.FriendApi.getBuddyReq()).buddyReqs.find(e => e.reqTime == payload.flag.toString());
if (!notify) {
throw new Error('No such request');
}
await this.core.apis.FriendApi.handleFriendRequest(notify, approve);
if (payload.remark) { if (payload.remark) {
const data = payload.flag.split('|'); await this.core.apis.FriendApi.setBuddyRemark(notify.friendUid, payload.remark);
if (data.length < 2) {
throw new Error('Invalid flag');
}
const friendUid = data[0];
await this.core.apis.FriendApi.setBuddyRemark(friendUid, payload.remark);
} }
return null; return null;
} }

View File

@@ -51,9 +51,9 @@ export class OneBotGroupApi {
if (memberUin && adminUin) { if (memberUin && adminUin) {
return new OB11GroupBanEvent( return new OB11GroupBanEvent(
this.core, this.core,
parseInt(GroupCode), +GroupCode,
parseInt(memberUin), +memberUin,
parseInt(adminUin), +adminUin,
duration, duration,
subType, subType,
); );
@@ -98,8 +98,8 @@ export class OneBotGroupApi {
} }
return new OB11GroupMsgEmojiLikeEvent( return new OB11GroupMsgEmojiLikeEvent(
this.core, this.core,
parseInt(groupCode), +groupCode,
parseInt(senderUin), +senderUin,
MessageUnique.getShortIdByMsgId(replyMsg.msgId)!, MessageUnique.getShortIdByMsgId(replyMsg.msgId)!,
[{ [{
emoji_id: emojiId, emoji_id: emojiId,
@@ -111,9 +111,10 @@ export class OneBotGroupApi {
async parseCardChangedEvent(msg: RawMessage) { async parseCardChangedEvent(msg: RawMessage) {
if (msg.senderUin && msg.senderUin !== '0') { if (msg.senderUin && msg.senderUin !== '0') {
const member = await this.core.apis.GroupApi.getGroupMember(msg.peerUid, msg.senderUin); const member = await this.core.apis.GroupApi.getGroupMember(msg.peerUid, msg.senderUin);
if (member && member.cardName !== msg.sendMemberName) { const oldName = member?.cardName || member?.nick || '';
if (member && oldName !== msg.sendMemberName) {
const newCardName = msg.sendMemberName ?? ''; const newCardName = msg.sendMemberName ?? '';
const event = new OB11GroupCardEvent(this.core, parseInt(msg.peerUid), parseInt(msg.senderUin), newCardName, member.cardName); const event = new OB11GroupCardEvent(this.core, parseInt(msg.peerUid), parseInt(msg.senderUin), newCardName, oldName);
member.cardName = newCardName; member.cardName = newCardName;
return event; return event;
} }

View File

@@ -153,6 +153,17 @@ export class OneBotMsgApi {
faceElement: async element => { faceElement: async element => {
const faceIndex = element.faceIndex; const faceIndex = element.faceIndex;
if (element.faceType == FaceType.Poke) {
return {
type: OB11MessageDataType.poke,
data: {
type: element?.pokeType?.toString() ?? '0',
id: faceIndex.toString(),
}
}
}
if (faceIndex === FaceIndex.DICE) { if (faceIndex === FaceIndex.DICE) {
return { return {
type: OB11MessageDataType.dice, type: OB11MessageDataType.dice,

View File

@@ -333,7 +333,7 @@ export class NapCatOneBot11Adapter {
this.core, this.core,
+requesterUin, +requesterUin,
req.extWords, req.extWords,
req.friendUid + '|' + req.reqTime req.reqTime
) )
); );
} catch (e) { } catch (e) {
@@ -365,8 +365,7 @@ export class NapCatOneBot11Adapter {
if (notifyTime < this.bootTime) { if (notifyTime < this.bootTime) {
continue; continue;
} }
const flag = notify.seq;
const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type;
this.context.logger.logDebug('收到群通知', notify); this.context.logger.logDebug('收到群通知', notify);
if ( if (
[GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS].includes(notify.type) && [GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS].includes(notify.type) &&
@@ -405,8 +404,8 @@ export class NapCatOneBot11Adapter {
this.context.logger.logDebug(`收到邀请我加群通知:${notify}`); this.context.logger.logDebug(`收到邀请我加群通知:${notify}`);
const groupInviteEvent = new OB11GroupRequestEvent( const groupInviteEvent = new OB11GroupRequestEvent(
this.core, this.core,
parseInt(notify.group.groupCode), +notify.group.groupCode,
parseInt(await this.core.apis.UserApi.getUinByUidV2(notify.user2.uid)), +await this.core.apis.UserApi.getUinByUidV2(notify.user2.uid),
'invite', 'invite',
notify.postscript, notify.postscript,
flag flag
@@ -423,8 +422,8 @@ export class NapCatOneBot11Adapter {
this.context.logger.logDebug(`收到群员邀请加群通知:${notify}`); this.context.logger.logDebug(`收到群员邀请加群通知:${notify}`);
const groupInviteEvent = new OB11GroupRequestEvent( const groupInviteEvent = new OB11GroupRequestEvent(
this.core, this.core,
parseInt(notify.group.groupCode), +notify.group.groupCode,
parseInt(await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid)), +await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid),
'add', 'add',
notify.postscript, notify.postscript,
flag flag
@@ -571,6 +570,8 @@ export class NapCatOneBot11Adapter {
} }
private async emitFriendRecallMsg(message: RawMessage, oriMessageId: number, element: MessageElement) { private async emitFriendRecallMsg(message: RawMessage, oriMessageId: number, element: MessageElement) {
const operatorUid = element.grayTipElement?.revokeElement.operatorUid;
if (!operatorUid) return undefined;
return new OB11FriendRecallNoticeEvent( return new OB11FriendRecallNoticeEvent(
this.core, this.core,
+message.senderUin, +message.senderUin,
@@ -581,7 +582,7 @@ export class NapCatOneBot11Adapter {
private async emitGroupRecallMsg(message: RawMessage, oriMessageId: number, element: MessageElement) { private async emitGroupRecallMsg(message: RawMessage, oriMessageId: number, element: MessageElement) {
const operatorUid = element.grayTipElement?.revokeElement.operatorUid; const operatorUid = element.grayTipElement?.revokeElement.operatorUid;
if (!operatorUid) return undefined; if (!operatorUid) return undefined;
const operatorId = message.senderUin ?? await this.core.apis.UserApi.getUinByUidV2(operatorUid); const operatorId = await this.core.apis.UserApi.getUinByUidV2(operatorUid);
return new OB11GroupRecallNoticeEvent( return new OB11GroupRecallNoticeEvent(
this.core, this.core,
+message.peerUin, +message.peerUin,

View File

@@ -11,6 +11,17 @@ export interface OB11User {
categoryName?: string; // 分组名称 categoryName?: string; // 分组名称
categoryId?: number; // 分组ID 999为特别关心 categoryId?: number; // 分组ID 999为特别关心
} }
export interface Notify {
request_id: number;
invitor_uin: number;
invitor_nick?: string;
group_id?: number;
group_name?: string;
message?: string;
checked: boolean;
actor: number;
requester_nick?: string;
}
export enum OB11UserSex { export enum OB11UserSex {
male = 'male', // 男性 male = 'male', // 男性

View File

@@ -71,6 +71,14 @@ export enum OB11MessageDataType {
location = 'location' location = 'location'
} }
export interface OB11MessagePoke {
type: OB11MessageDataType.poke;
data: {
type: string;
id: string;
};
}
// 商城表情消息接口定义 // 商城表情消息接口定义
export interface OB11MessageMFace { export interface OB11MessageMFace {
type: OB11MessageDataType.mface; type: OB11MessageDataType.mface;
@@ -247,7 +255,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 | OB11MessageContext; OB11MessageDice | OB11MessageRPS | OB11MessageMarkdown | OB11MessageForward | OB11MessageContext | OB11MessagePoke;
// 发送消息接口定义 // 发送消息接口定义
export interface OB11PostSendMsg { export interface OB11PostSendMsg {