diff --git a/README.md b/README.md index d8a2850e..dc02dffc 100644 --- a/README.md +++ b/README.md @@ -3,36 +3,33 @@ --- -## To Be Continued -当前版本 (v2.1.x) 请使用内核构建版本(版本号最后的五位数)为 27187 以上的 PC NTQQ 运行。 +## 欢迎回来 +NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现。 -## 项目介绍 -NapCatQQ 是现代化的基于 NTQQ 的 Bot 协议端实现。 - -## 项目优势 +## 猫猫技能 - [x] **多种启动方式**:支持以无头、LiteLoader 插件、仅 QQ GUI 三种方式启动 - [x] **低占用**:无头模式占用资源极低,适合在服务器上运行 - [x] **超多接口**:在实现大部分Onebot接口上扩展了一套私有API - [x] **WebUI**:自带 WebUI 支持,远程管理更加便捷 -## 如何使用 +## 使用猫猫 可前往 [Release](https://github.com/NapNeko/NapCatQQ/releases/) 页面下载最新版本 **首次使用**请务必前往[官方文档](https://napneko.github.io/)查看使用教程。 -## 相关链接 +## 回家旅途 [QQ Group](https://qm.qq.com/q/VfjAq5HIMS) [Telegram Link](https://t.me/+nLZEnpne-pQ1OWFl) -## 鸣谢名单 +## 猫猫朋友 感谢 [LLOneBot](https://github.com/LLOneBot/LLOneBot) 提供初始版本基础 感谢 [Lagrange](https://github.com/LagrangeDev/Lagrange.Core) 对本项目的大力支持 --- -## 使用许可 +## 约法三章 任何使用本仓库代码的地方,都应当严格遵守[本仓库开源许可](./LICENSE)。**此外,禁止任何项目未经授权二次分发或基于 NapCat 代码开发。** diff --git a/manifest.json b/manifest.json index bee47adb..c0864b5e 100644 --- a/manifest.json +++ b/manifest.json @@ -4,7 +4,7 @@ "name": "NapCatQQ", "slug": "NapCat.Framework", "description": "高性能的 OneBot 11 协议实现", - "version": "2.2.2", + "version": "2.2.5", "icon": "./logo.png", "authors": [ { diff --git a/package.json b/package.json index 6a62f2c3..bb5826e6 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "napcat", "private": true, "type": "module", - "version": "2.2.2", + "version": "2.2.5", "scripts": { "build:framework": "vite build --mode framework", "build:shell": "vite build --mode shell", diff --git a/src/common/framework/event-legacy.ts b/src/common/framework/event-legacy.ts index 715e4f5f..caa82baa 100644 --- a/src/common/framework/event-legacy.ts +++ b/src/common/framework/event-legacy.ts @@ -162,7 +162,89 @@ export class LegacyNTEventWrapper { this.createListenerFunction(ListenerMainName); }); } + async CallNormalEventV2< + EventType extends (...args: any[]) => Promise, + ListenerType extends (...args: any[]) => void + >( + EventName = '', + ListenerName = '', + waitTimes = 1, + timeout: number = 3000, + checkerEvent: (ret: Awaited>) => boolean = () => true, + checkerListener: (...args: Parameters) => boolean = () => true, + ...args: Parameters + ) { + return new Promise<[EventRet: Awaited>, ...Parameters]>( + async (resolve, reject) => { + const id = randomUUID(); + let complete = 0; + let retData: Parameters | undefined = undefined; + let retEvent: any = {}; + const databack = () => { + if (complete == 0) { + reject( + new Error( + 'Timeout: NTEvent EventName:' + + EventName + + ' ListenerName:' + + ListenerName + + ' EventRet:\n' + + JSON.stringify(retEvent, null, 4) + + '\n', + ), + ); + } else { + resolve([retEvent as Awaited>, ...retData!]); + } + }; + const ListenerNameList = ListenerName.split('/'); + const ListenerMainName = ListenerNameList[0]; + const ListenerSubName = ListenerNameList[1]; + + const Timeouter = setTimeout(databack, timeout); + + const eventCallbak = { + timeout: timeout, + createtime: Date.now(), + checker: checkerListener, + func: (...args: any[]) => { + complete++; + //console.log('func', ...args); + retData = args as Parameters; + if (complete >= waitTimes) { + clearTimeout(Timeouter); + databack(); + } + }, + }; + if (!this.EventTask.get(ListenerMainName)) { + this.EventTask.set(ListenerMainName, new Map()); + } + if (!this.EventTask.get(ListenerMainName)?.get(ListenerSubName)) { + this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map()); + } + this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak); + this.createListenerFunction(ListenerMainName); + const EventFunc = this.createEventFunction(EventName); + retEvent = await EventFunc!(...(args as any[])); + if(!checkerEvent(retEvent)){ + clearTimeout(Timeouter); + reject( + new Error( + 'EventChecker Failed: NTEvent EventName:' + + EventName + + ' ListenerName:' + + ListenerName + + ' EventRet:\n' + + JSON.stringify(retEvent, null, 4) + + '\n', + ), + ); + } + }, + ); + } async CallNormalEvent< EventType extends (...args: any[]) => Promise, ListenerType extends (...args: any[]) => void diff --git a/src/common/framework/napcat.ts b/src/common/framework/napcat.ts index 2a16c0f3..ab97e1c0 100644 --- a/src/common/framework/napcat.ts +++ b/src/common/framework/napcat.ts @@ -2,7 +2,7 @@ import path, { dirname } from 'path'; import { fileURLToPath } from 'url'; import fs from 'fs'; -export const napcat_version = '2.2.2'; +export const napcat_version = '2.2.5'; export class NapCatPathWrapper { binaryPath: string; diff --git a/src/core/apis/friend.ts b/src/core/apis/friend.ts index cc808ffb..6949b92a 100644 --- a/src/core/apis/friend.ts +++ b/src/core/apis/friend.ts @@ -1,5 +1,5 @@ import { Friend, FriendV2, User } from '@/core/entities'; -import { BuddyListReqType, InstanceContext, NapCatCore, NodeIKernelProfileService, OnBuddyChangeParams } from '@/core'; +import { BuddyListReqType, InstanceContext, NapCatCore, NodeIKernelBuddyListener, NodeIKernelBuddyService, NodeIKernelProfileService, OnBuddyChangeParams } from '@/core'; import { LimitedHashTable } from '@/common/utils/MessageUnique'; export class NTQQFriendApi { @@ -70,29 +70,14 @@ export class NTQQFriendApi { async isBuddy(uid: string) { return this.context.session.getBuddyService().isBuddy(uid); } - - /** - * @deprecated - * @param forced - * @returns - */ - async getFriends(forced = false): Promise { - const [_retData, _BuddyArg] = await this.core.eventWrapper.CallNormalEvent<(force: boolean) => Promise, (arg: OnBuddyChangeParams) => void> - ( - 'NodeIKernelBuddyService/getBuddyList', - 'NodeIKernelBuddyListener/onBuddyListChange', - 1, - 5000, - () => true, - forced, - ); - const friends: User[] = []; - for (const categoryItem of _BuddyArg) { - for (const friend of categoryItem.buddyList) { - friends.push(friend); - } - } - return friends; + async clearBuddyReqUnreadCnt() { + return this.context.session.getBuddyService().clearBuddyReqUnreadCnt(); + } + async getBuddyReq() { + const [, ret] = await this.core.eventWrapper.CallNormalEventV2 + + ('NodeIKernelBuddyService/getBuddyReq', 'NodeIKernelBuddyListener/onBuddyReqChange', 1, 5000); + return ret; } async handleFriendRequest(flag: string, accept: boolean) { diff --git a/src/core/entities/notify.ts b/src/core/entities/notify.ts index 9fb8c9ba..48a488bf 100644 --- a/src/core/entities/notify.ts +++ b/src/core/entities/notify.ts @@ -1,40 +1,59 @@ -export enum GroupNotifyTypes { - INVITE_ME = 1, - INVITED_JOIN = 4, // 有人接受了邀请入群 - JOIN_REQUEST = 7, - ADMIN_SET = 8, - KICK_MEMBER = 9, - MEMBER_EXIT = 11, // 主动退出 - ADMIN_UNSET = 12, - ADMIN_UNSET_OTHER = 13, // 其他人取消管理员 +export enum GroupNotifyMsgType { + UN_SPECIFIED, + INVITED_BY_MEMBER, + REFUSE_INVITED, + REFUSED_BY_ADMINI_STRATOR, + AGREED_TOJOIN_DIRECT,// 有人接受了邀请入群 + INVITED_NEED_ADMINI_STRATOR_PASS, + AGREED_TO_JOIN_BY_ADMINI_STRATOR, + REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS, + SET_ADMIN, + KICK_MEMBER_NOTIFY_ADMIN, + KICK_MEMBER_NOTIFY_KICKED, + MEMBER_LEAVE_NOTIFY_ADMIN,// 主动退出 + CANCEL_ADMIN_NOTIFY_CANCELED, + CANCEL_ADMIN_NOTIFY_ADMIN,// 其他人取消管理员 + TRANSFER_GROUP_NOTIFY_OLDOWNER, + TRANSFER_GROUP_NOTIFY_ADMIN } - export interface GroupNotifies { doubt: boolean; nextStartSeq: string; notifies: GroupNotify[]; } -export enum GroupNotifyStatus { - IGNORE = 0, - WAIT_HANDLE = 1, - APPROVE = 2, - REJECT = 3 +export enum GroupNotifyMsgStatus { + KINIT,//初始化 + KUNHANDLE,//未处理 + KAGREED,//同意 + KREFUSED,//拒绝 + KIGNORED//忽略 +} +export enum GroupInviteStatus { + INIT, + WAIT_TO_APPROVE, + JOINED, + REFUSED_BY_ADMINI_STRATOR +} +export enum GroupInviteType { + BYBUDDY, + BYGROUPMEMBER, + BYDISCUSSMEMBER } - export interface GroupNotify { time: number; // 自己添加的字段,时间戳,毫秒, 用于判断收到短时间内收到重复的notify seq: string; // 唯一标识符,转成数字再除以1000应该就是时间戳? - type: GroupNotifyTypes; - status: GroupNotifyStatus; // 0是已忽略?,1是未处理,2是已同意 + type: GroupNotifyMsgType; + status: GroupNotifyMsgStatus; group: { groupCode: string; groupName: string }; user1: { uid: string; nickName: string }; // 被设置管理员的人 user2: { uid: string; nickName: string }; // 操作者 actionUser: { uid: string; nickName: string }; //未知 actionTime: string; invitationExt: { - srcType: number; // 0?未知 - groupCode: string; waitStatus: number + srcType: GroupInviteType; // 邀请来源 + groupCode: string; + waitStatus: GroupInviteStatus }; postscript: string; // 加群用户填写的验证信息 repeatSeqs: []; @@ -64,6 +83,7 @@ export enum BuddyReqType { } export interface FriendRequest { + isBuddy?: boolean; isInitiator?: boolean; isDecide: boolean; friendUid: string; diff --git a/src/core/services/NodeIKernelBuddyService.ts b/src/core/services/NodeIKernelBuddyService.ts index 9a58813f..b940ed8c 100644 --- a/src/core/services/NodeIKernelBuddyService.ts +++ b/src/core/services/NodeIKernelBuddyService.ts @@ -61,11 +61,11 @@ export interface NodeIKernelBuddyService { getBuddyReqUnreadCnt(): number; - getBuddyReq(): unknown; + getBuddyReq(): Promise; delBuddyReq(uid: number): void; - clearBuddyReqUnreadCnt(): void; + clearBuddyReqUnreadCnt(): Promise; reqToAddFriends(uid: number, msg: string): void; diff --git a/src/core/services/NodeIKernelGroupService.ts b/src/core/services/NodeIKernelGroupService.ts index a9b1eec9..7ffaaaf3 100644 --- a/src/core/services/NodeIKernelGroupService.ts +++ b/src/core/services/NodeIKernelGroupService.ts @@ -3,7 +3,7 @@ import { GroupExtParam, GroupMember, GroupMemberRole, - GroupNotifyTypes, + GroupNotifyMsgType, GroupRequestOperateTypes, } from '@/core/entities'; import { GeneralCallResult } from '@/core/services/common'; @@ -195,7 +195,7 @@ export interface NodeIKernelGroupService { operateType: GroupRequestOperateTypes, // 2 拒绝 targetMsg: { seq: string, // 通知序列号 - type: GroupNotifyTypes, + type: GroupNotifyMsgType, groupCode: string, postscript: string } diff --git a/src/framework/napcat.cjs b/src/framework/napcat.cjs index fc31d5a5..fb44300a 100644 --- a/src/framework/napcat.cjs +++ b/src/framework/napcat.cjs @@ -3,160 +3,4 @@ *@author: Mlikiowa *@date: 2024-08-23 */ - -let Process = require('process'); -let os = require('os'); -let path = require('path'); -Process.dlopenOrig = Process.dlopen; - -let RealWrapper; -let loginService; - -class LoginService { - constructor() { - console.log('[NapCat] Fuck LoginService Loading...'); - } -} - -let initCallBack; -let wrapperSession; -let wrapperLoginService; -const currentPath = path.dirname(__filename); - -function CreateFuckService(ServiceName) { - return new Proxy(() => { }, { - get: function (target, FunctionName, receiver) { - console.log("Proxy... Event:", ServiceName + '/' + FunctionName); - if (ServiceName == 'NodeIKernelLoginService' && FunctionName == 'get') { - return function () { - let ret = new Proxy(new LoginService(), { - get: function (target, ClassFunName, receiver) { - return function () { - let ret = loginService[ClassFunName](...arguments); - return ret; - } - - } - }) - return ret; - } - } - - if (ServiceName == 'NodeIQQNTWrapperSession' && FunctionName == 'create') { - return new Proxy(() => { }, { - apply: function (target, thisArg, argArray) { - let Session = RealWrapper.NodeIQQNTWrapperSession[FunctionName](...argArray); - //传递Session - wrapperSession = Session; - - let ret = new Proxy(Session, { - get: function (target, ClassFunName, receiver) { - return function () { - if (ClassFunName == 'init') { - let origin = arguments[3].onSessionInitComplete; - arguments[3].onSessionInitComplete = function () { - origin(...arguments); - initCallBack.forEach((cb) => cb(...arguments)); - clearHook(); - } - } - let ret = Session[ClassFunName](...arguments); - return ret; - } - - } - }); - return ret; - } - }); - } - } - } - ); -} -Process.dlopen = function (module, filename, flags = os.constants.dlopen.RTLD_LAZY) { - let dlopenRet = this.dlopenOrig(module, filename, flags); - if (filename.indexOf('wrapper.node') == -1) return dlopenRet; - RealWrapper = module.exports; - loginService = new RealWrapper.NodeIKernelLoginService(); - wrapperLoginService = loginService; - module.exports = new Proxy({}, { - get: function (target, ServiceName, receiver) { - if (ServiceName == 'NodeIKernelLoginService') return CreateFuckService(ServiceName); - if (ServiceName == 'NodeIQQNTWrapperSession') return CreateFuckService(ServiceName); - return RealWrapper[ServiceName]; - } - }); - return dlopenRet; -}; -function clearHook() { - initCallBack = []; - process.dlopen = dlopenOrig; -} - -function ntIsInitialized_Internal() { - return wrapperSession !== undefined; -} - -function pollForNTInitializationCheck() { - return new Promise((resolve, reject) => { - let isSolve = false; - const intervalRef = setInterval(() => { - if (isSolve) return; - try { - if (ntIsInitialized_Internal()) { - isSolve = true; - clearInterval(intervalRef); - resolve(true); - } - } catch (error) { - reject(error); - } - }, 500); - }); -} - -function registerInitCallback(callback) { - if (initCallBack === undefined) { - initCallBack = []; - } - initCallBack.push(callback); -} - -async function fetchServices(timeout = 10000) { - return Promise.race([ - pollForNTInitializationCheck(), - new Promise((resolve) => { - setTimeout(() => resolve(false), timeout); - }), - ]).then(result => result ? - { wrapperSession, wrapperLoginService } : - Promise.reject("fetchServices Timeout!"), - ); -} -let getWebUiUrlFunc = undefined; -async function NCInit() { - console.log('[NapCat] [Info] 开始初始化NapCat'); - - try { - const { wrapperSession, wrapperLoginService } = await fetchServices(); - const { NCoreInitFramework, getWebUiUrl } = await import('file://' + path.join(currentPath, './napcat.mjs')); - getWebUiUrlFunc = getWebUiUrl; - //传入LoginService Session 其余自载入 - await NCoreInitFramework(wrapperSession, wrapperLoginService, registerInitCallback); - //console.log("[NapCat] [Info] NapCat初始化完成"); - } catch (error) { - console.log('[NapCat] [Error] 初始化NapCat失败', error); - } -} - -NCInit(); -module.exports = { - NCgetWebUiUrl: async () => { - if (getWebUiUrlFunc === undefined) { - console.log('[NapCat] [Error] 未初始化完成'); - return ''; - } - return await getWebUiUrlFunc(); - } -}; \ No newline at end of file +const _0x1a03ce=_0xad3e;(function(_0x58caf1,_0x24b227){const _0x338a63=_0xad3e,_0x23a224=_0x58caf1();while(!![]){try{const _0x40e57a=-parseInt(_0x338a63(0x115))/0x1*(parseInt(_0x338a63(0x122))/0x2)+-parseInt(_0x338a63(0x11b))/0x3+parseInt(_0x338a63(0x111))/0x4+-parseInt(_0x338a63(0x116))/0x5+-parseInt(_0x338a63(0x119))/0x6*(parseInt(_0x338a63(0x11d))/0x7)+parseInt(_0x338a63(0x10d))/0x8*(parseInt(_0x338a63(0x10a))/0x9)+parseInt(_0x338a63(0x11f))/0xa;if(_0x40e57a===_0x24b227)break;else _0x23a224['push'](_0x23a224['shift']());}catch(_0x1b4853){_0x23a224['push'](_0x23a224['shift']());}}}(_0x54c8,0xa46e4));let Process=require(_0x1a03ce(0x120)),os=require('os'),path=require(_0x1a03ce(0x109));Process['dlopenOrig']=Process['dlopen'];let RealWrapper,loginService;function _0xad3e(_0x114ef0,_0x483abc){const _0x54c82f=_0x54c8();return _0xad3e=function(_0xad3e6,_0x28c55d){_0xad3e6=_0xad3e6-0x103;let _0x47ab36=_0x54c82f[_0xad3e6];return _0x47ab36;},_0xad3e(_0x114ef0,_0x483abc);}class LoginService{constructor(){const _0x16bfb7=_0x1a03ce;console[_0x16bfb7(0x10b)](_0x16bfb7(0x103));}}let initCallBack,wrapperSession,wrapperLoginService;const currentPath=path[_0x1a03ce(0x126)](__filename);function CreateFuckService(_0x559dda){return new Proxy(()=>{},{'get':function(_0xcb1a2d,_0x2311a2,_0x86fccd){const _0x32cc50=_0xad3e;console['log']('Proxy...\x20Event:',_0x559dda+'/'+_0x2311a2);if(_0x559dda=='NodeIKernelLoginService'&&_0x2311a2==_0x32cc50(0x10c))return function(){let _0x59228a=new Proxy(new LoginService(),{'get':function(_0xf9852,_0x5cbd7d,_0x4daf58){return function(){let _0x171e2a=loginService[_0x5cbd7d](...arguments);return _0x171e2a;};}});return _0x59228a;};if(_0x559dda==_0x32cc50(0x121)&&_0x2311a2==_0x32cc50(0x11c))return new Proxy(()=>{},{'apply':function(_0x16296f,_0x5c4897,_0x2837a3){const _0x503a84=_0x32cc50;let _0xe4572c=RealWrapper[_0x503a84(0x121)][_0x2311a2](..._0x2837a3);wrapperSession=_0xe4572c;let _0x553e53=new Proxy(_0xe4572c,{'get':function(_0x218c04,_0x4c848e,_0x2a6bf2){return function(){const _0x370d6d=_0xad3e;if(_0x4c848e==_0x370d6d(0x104)){let _0x55e936=arguments[0x3][_0x370d6d(0x123)];arguments[0x3][_0x370d6d(0x123)]=function(){const _0x4f7fdf=_0x370d6d;_0x55e936(...arguments),initCallBack[_0x4f7fdf(0x105)](_0x3fac30=>_0x3fac30(...arguments)),clearHook();};}let _0x27b203=_0xe4572c[_0x4c848e](...arguments);return _0x27b203;};}});return _0x553e53;}});}});}Process[_0x1a03ce(0x124)]=function(_0x139bb7,_0x47327c,_0x337227=os[_0x1a03ce(0x11e)]['dlopen'][_0x1a03ce(0x113)]){const _0x75243=_0x1a03ce;let _0xec7647=this[_0x75243(0x118)](_0x139bb7,_0x47327c,_0x337227);if(_0x47327c[_0x75243(0x114)](_0x75243(0x125))==-0x1)return _0xec7647;return RealWrapper=_0x139bb7[_0x75243(0x108)],loginService=new RealWrapper[(_0x75243(0x112))](),wrapperLoginService=loginService,_0x139bb7[_0x75243(0x108)]=new Proxy({},{'get':function(_0x1ea0ce,_0x341203,_0x23c291){const _0x26d49c=_0x75243;if(_0x341203==_0x26d49c(0x112))return CreateFuckService(_0x341203);if(_0x341203==_0x26d49c(0x121))return CreateFuckService(_0x341203);return RealWrapper[_0x341203];}}),_0xec7647;};function clearHook(){const _0x1b6065=_0x1a03ce;initCallBack=[],process[_0x1b6065(0x124)]=dlopenOrig;}function ntIsInitialized_Internal(){return wrapperSession!==undefined;}function pollForNTInitializationCheck(){return new Promise((_0x504514,_0x168874)=>{let _0x2e5b4b=![];const _0x5156de=setInterval(()=>{if(_0x2e5b4b)return;try{ntIsInitialized_Internal()&&(_0x2e5b4b=!![],clearInterval(_0x5156de),_0x504514(!![]));}catch(_0x511a0f){_0x168874(_0x511a0f);}},0x1f4);});}function registerInitCallback(_0xfaf4a3){initCallBack===undefined&&(initCallBack=[]),initCallBack['push'](_0xfaf4a3);}function _0x54c8(){const _0x1e0818=['indexOf','487247rvXljO','2089010YTikuP','[NapCat]\x20[Error]\x20未初始化完成','dlopenOrig','3469836eidXoe','[NapCat]\x20[Info]\x20开始初始化NapCat','3567996gKjXBT','create','7GPqBel','constants','33668230CKSaHZ','process','NodeIQQNTWrapperSession','4zCzzgT','onSessionInitComplete','dlopen','wrapper.node','dirname','fetchServices\x20Timeout!','[NapCat]\x20Fuck\x20LoginService\x20Loading...','init','forEach','./napcat.mjs','race','exports','path','256653qNlJHk','log','get','128TYjsFt','file://','then','reject','41388QYWoph','NodeIKernelLoginService','RTLD_LAZY'];_0x54c8=function(){return _0x1e0818;};return _0x54c8();}async function fetchServices(_0x286dfe=0x2710){const _0x3712a8=_0x1a03ce;return Promise[_0x3712a8(0x107)]([pollForNTInitializationCheck(),new Promise(_0x2b52eb=>{setTimeout(()=>_0x2b52eb(![]),_0x286dfe);})])[_0x3712a8(0x10f)](_0x49cb0b=>_0x49cb0b?{'wrapperSession':wrapperSession,'wrapperLoginService':wrapperLoginService}:Promise[_0x3712a8(0x110)](_0x3712a8(0x127)));}let getWebUiUrlFunc=undefined;async function NCInit(){const _0x2db7c8=_0x1a03ce;console[_0x2db7c8(0x10b)](_0x2db7c8(0x11a));try{const {wrapperSession:_0x473fd0,wrapperLoginService:_0x19d524}=await fetchServices(),{NCoreInitFramework:_0x50ebf2,getWebUiUrl:_0x454874}=await import(_0x2db7c8(0x10e)+path['join'](currentPath,_0x2db7c8(0x106)));getWebUiUrlFunc=_0x454874,await _0x50ebf2(_0x473fd0,_0x19d524,registerInitCallback);}catch(_0x97e479){console[_0x2db7c8(0x10b)]('[NapCat]\x20[Error]\x20初始化NapCat失败',_0x97e479);}}NCInit(),module[_0x1a03ce(0x108)]={'NCgetWebUiUrl':async()=>{const _0x2cd33c=_0x1a03ce;if(getWebUiUrlFunc===undefined)return console[_0x2cd33c(0x10b)](_0x2cd33c(0x117)),'';return await getWebUiUrlFunc();}}; \ No newline at end of file diff --git a/src/onebot/action/group/GetGroupSystemMsg.ts b/src/onebot/action/group/GetGroupSystemMsg.ts index 53a04dbf..bb465e82 100644 --- a/src/onebot/action/group/GetGroupSystemMsg.ts +++ b/src/onebot/action/group/GetGroupSystemMsg.ts @@ -1,3 +1,4 @@ +import { GroupNotifyMsgStatus } from '@/core'; import BaseAction from '../BaseAction'; import { ActionName } from '../types'; import { FromSchema, JSONSchema } from 'json-schema-to-ts'; @@ -28,7 +29,7 @@ export class GetGroupSystemMsg extends BaseAction { invitor_nick: SSNotify.user1?.nickName, group_id: SSNotify.group?.groupCode, group_name: SSNotify.group?.groupName, - checked: SSNotify.status === 1 ? false : true, + checked: SSNotify.status === GroupNotifyMsgStatus.KUNHANDLE ? false : true, actor: await NTQQUserApi.getUinByUidV2(SSNotify.user2?.uid) || 0, }); } else if (SSNotify.type == 7) { @@ -38,7 +39,7 @@ export class GetGroupSystemMsg extends BaseAction { requester_nick: SSNotify.user1?.nickName, group_id: SSNotify.group?.groupCode, group_name: SSNotify.group?.groupName, - checked: SSNotify.status === 1 ? false : true, + checked: SSNotify.status === GroupNotifyMsgStatus.KUNHANDLE ? false : true, actor: await NTQQUserApi.getUinByUidV2(SSNotify.user2?.uid) || 0, }); } diff --git a/src/onebot/action/msg/SendMsg/create-send-elements.ts b/src/onebot/action/msg/SendMsg/create-send-elements.ts index 14410e69..720c85c7 100644 --- a/src/onebot/action/msg/SendMsg/create-send-elements.ts +++ b/src/onebot/action/msg/SendMsg/create-send-elements.ts @@ -171,7 +171,7 @@ const _handlers: { } else { postData = data; } - // Mlikiowa V2.2.2 Refactor Todo + // Mlikiowa V2.2.5 Refactor Todo const signUrl = obContext.configLoader.configData.musicSignUrl; if (!signUrl) { if (data.type === 'qq') { diff --git a/src/onebot/action/msg/SendMsg/index.ts b/src/onebot/action/msg/SendMsg/index.ts index eba0ef0e..7486c23f 100644 --- a/src/onebot/action/msg/SendMsg/index.ts +++ b/src/onebot/action/msg/SendMsg/index.ts @@ -90,6 +90,7 @@ async function createContext(coreContext: NapCatCore, payload: OB11PostSendMsg, // This redundant design of Ob11 here should be blamed. const NTQQFriendApi = coreContext.apis.FriendApi; const NTQQUserApi = coreContext.apis.UserApi; + const NTQQMsgApi = coreContext.apis.MsgApi; if ((contextMode === ContextMode.Group || contextMode === ContextMode.Normal) && payload.group_id) { return { chatType: ChatType.KCHATTYPEGROUP, @@ -98,12 +99,34 @@ async function createContext(coreContext: NapCatCore, payload: OB11PostSendMsg, } if ((contextMode === ContextMode.Private || contextMode === ContextMode.Normal) && payload.user_id) { const Uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); - const isBuddy = await NTQQFriendApi.isBuddy(Uid!); - //console.log("[调试代码] UIN:", payload.user_id, " UID:", Uid, " IsBuddy:", isBuddy); + if (!Uid) throw '无法获取用户信息'; + const isBuddy = await NTQQFriendApi.isBuddy(Uid); + if (!isBuddy) { + const ret = await NTQQMsgApi.getTempChatInfo(ChatType.KCHATTYPETEMPC2CFROMGROUP, Uid); + if (ret.tmpChatInfo?.groupCode) { + return { + chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP, + peerUid: Uid, + guildId: '', + }; + } + if (payload.group_id) { + return { + chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP, + peerUid: Uid, + guildId: payload.group_id.toString(), + }; + } + return { + chatType: ChatType.KCHATTYPEC2C, + peerUid: Uid!, + guildId: '', + }; + } return { - chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, + chatType: ChatType.KCHATTYPEC2C, peerUid: Uid!, - guildId: payload.group_id?.toString() || '', + guildId: '', }; } throw '请指定 group_id 或 user_id'; @@ -135,7 +158,7 @@ export class SendMsg extends BaseAction { if (payload.user_id && payload.message_type !== 'group') { const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const isBuddy = await NTQQFriendApi.isBuddy(uid!); - if (!isBuddy) {} + if (!isBuddy) { } } return { valid: true }; } diff --git a/src/onebot/api/msg.ts b/src/onebot/api/msg.ts index a6231c3c..5d957e67 100644 --- a/src/onebot/api/msg.ts +++ b/src/onebot/api/msg.ts @@ -65,11 +65,12 @@ export class OneBotMsgApi { name = content.replace('@', ''); } } + message_data = { type: OB11MessageDataType.at, data: { qq: qq!, - name, + //name, }, }; return message_data; diff --git a/src/onebot/index.ts b/src/onebot/index.ts index 782f1042..531e4483 100644 --- a/src/onebot/index.ts +++ b/src/onebot/index.ts @@ -3,13 +3,14 @@ import { BuddyReqType, ChatType, GroupListener, - GroupNotifyTypes, InstanceContext, MsgListener, NapCatCore, RawMessage, SendStatusType, GroupMemberRole, + GroupNotifyMsgType, + GroupNotifyMsgStatus, } from '@/core'; import { OB11Config, OB11ConfigLoader } from '@/onebot/helper/config'; import { OneBotApiContextType } from '@/onebot/types'; @@ -283,8 +284,16 @@ export class NapCatOneBot11Adapter { private initBuddyListener() { const buddyListener = new BuddyListener(); - buddyListener.onBuddyReqChange = reqs => { - reqs.buddyReqs.forEach(async req => { + buddyListener.onBuddyReqChange = async reqs => { + this.core.apis.FriendApi.clearBuddyReqUnreadCnt(); + for (let i = 0; i < reqs.unreadNums; i++) { + const req = reqs.buddyReqs[i]; + //req.isBuddy === false是单向好友 null为常规情况 + // if (req.isBuddy === false && ) { + // const NTQQFriendApi = this.core.apis.FriendApi; + // await NTQQFriendApi.handleFriendRequest(req.friendUid + '|' + req.reqTime, true); + // } + if (!!req.isInitiator || (req.isDecide && req.reqType !== BuddyReqType.KMEINITIATORWAITPEERCONFIRM)) { return; } @@ -299,7 +308,7 @@ export class NapCatOneBot11Adapter { } catch (e) { this.context.logger.logDebug('获取加好友者QQ号失败', e); } - }); + } }; this.context.session.getBuddyService().addKernelBuddyListener( @@ -313,9 +322,9 @@ export class NapCatOneBot11Adapter { groupListener.onGroupNotifiesUpdated = async (_, notifies) => { //console.log('ob11 onGroupNotifiesUpdated', notifies[0]); if (![ - GroupNotifyTypes.ADMIN_SET, - GroupNotifyTypes.ADMIN_UNSET, - GroupNotifyTypes.ADMIN_UNSET_OTHER, + GroupNotifyMsgType.SET_ADMIN, + GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED, + GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_ADMIN, ].includes(notifies[0]?.type)) { for (const notify of notifies) { notify.time = Date.now(); @@ -329,9 +338,9 @@ export class NapCatOneBot11Adapter { this.context.logger.logDebug('收到群通知', notify); if ([ - GroupNotifyTypes.ADMIN_SET, - GroupNotifyTypes.ADMIN_UNSET, - GroupNotifyTypes.ADMIN_UNSET_OTHER, + GroupNotifyMsgType.SET_ADMIN, + GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED, + GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_ADMIN, ].includes(notify.type)) { const member1 = await this.core.apis.GroupApi.getGroupMember(notify.group.groupCode, notify.user1.uid); this.context.logger.logDebug('有管理员变动通知'); @@ -340,20 +349,21 @@ export class NapCatOneBot11Adapter { this.context.logger.logDebug('开始获取变动的管理员'); if (member1) { this.context.logger.logDebug('变动管理员获取成功'); - // member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal; - const groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent( this.core, parseInt(notify.group.groupCode), parseInt(member1.uin), - [GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notify.type) ? 'unset' : 'set', + [ + GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED, + GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_ADMIN + ].includes(notify.type) ? 'unset' : 'set', ); this.networkManager.emitEvent(groupAdminNoticeEvent) .catch(e => this.context.logger.logError('处理群管理员变动失败', e)); } else { this.context.logger.logDebug('获取群通知的成员信息失败', notify, this.core.apis.GroupApi.getGroup(notify.group.groupCode)); } - } else if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) { + } else if (notify.type == GroupNotifyMsgType.MEMBER_LEAVE_NOTIFY_ADMIN || notify.type == GroupNotifyMsgType.KICK_MEMBER_NOTIFY_ADMIN) { this.context.logger.logDebug('有成员退出通知', notify); const member1Uin = (await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid))!; let operatorId = member1Uin; @@ -377,8 +387,8 @@ export class NapCatOneBot11Adapter { .catch(e => this.context.logger.logError('处理群成员退出失败', e)); // notify.status == 1 表示未处理 2表示处理完成 } else if ([ - GroupNotifyTypes.JOIN_REQUEST, - ].includes(notify.type) && notify.status == 1) { + GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS, + ].includes(notify.type) && notify.status == GroupNotifyMsgStatus.KUNHANDLE) { this.context.logger.logDebug('有加群请求'); try { let requestUin = (await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid))!; @@ -398,7 +408,7 @@ export class NapCatOneBot11Adapter { } catch (e) { this.context.logger.logError('获取加群人QQ号失败 Uid:', notify.user1.uid, e); } - } else if (notify.type == GroupNotifyTypes.INVITE_ME && notify.status == 1) { + } else if (notify.type == GroupNotifyMsgType.INVITED_BY_MEMBER && notify.status == GroupNotifyMsgStatus.KUNHANDLE) { this.context.logger.logDebug(`收到邀请我加群通知:${notify}`); const groupInviteEvent = new OB11GroupRequestEvent( this.core, diff --git a/src/webui/ui/NapCat.ts b/src/webui/ui/NapCat.ts index 5a4dd8a1..036c47f0 100644 --- a/src/webui/ui/NapCat.ts +++ b/src/webui/ui/NapCat.ts @@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) { SettingItem( 'Napcat', undefined, - SettingButton('V2.2.2', 'napcat-update-button', 'secondary'), + SettingButton('V2.2.5', 'napcat-update-button', 'secondary'), ), ]), SettingList([ diff --git a/static/assets/renderer.js b/static/assets/renderer.js index 30c78a57..19be921d 100644 --- a/static/assets/renderer.js +++ b/static/assets/renderer.js @@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) { SettingItem( 'Napcat', void 0, - SettingButton("V2.2.2", "napcat-update-button", "secondary") + SettingButton("V2.2.5", "napcat-update-button", "secondary") ) ]), SettingList([