From c5b69561af69fd4b472f314575558bddfaf19384 Mon Sep 17 00:00:00 2001 From: idranme Date: Fri, 9 Aug 2024 14:20:59 +0800 Subject: [PATCH] sync --- src/common/data.ts | 48 ++-- src/common/utils/QQBasicInfo.ts | 24 +- src/common/utils/helper.ts | 52 +++- src/common/utils/table.ts | 71 +++++ src/main/main.ts | 31 +-- src/ntqqapi/api/friend.ts | 37 ++- src/ntqqapi/api/group.ts | 52 +--- src/ntqqapi/api/user.ts | 106 +++++++- src/ntqqapi/constructor.ts | 2 +- src/ntqqapi/hook.ts | 6 +- .../listeners/NodeIKernelGroupListener.ts | 240 +++++++++++++++++ src/ntqqapi/listeners/index.ts | 3 +- .../services/NodeIKernelGroupService.ts | 249 ++++++++++++++++++ .../services/NodeIKernelProfileLikeService.ts | 22 ++ src/ntqqapi/services/index.ts | 4 +- src/ntqqapi/types/group.ts | 7 + src/ntqqapi/types/notify.ts | 38 +++ src/ntqqapi/types/user.ts | 82 ++++++ src/ntqqapi/wrapper.ts | 14 +- .../action/group/GetGroupMemberList.ts | 3 +- src/onebot11/action/msg/SendMsg.ts | 65 +---- src/onebot11/action/user/SendLike.ts | 17 +- src/onebot11/constructor.ts | 14 +- 23 files changed, 970 insertions(+), 217 deletions(-) create mode 100644 src/common/utils/table.ts create mode 100644 src/ntqqapi/listeners/NodeIKernelGroupListener.ts create mode 100644 src/ntqqapi/services/NodeIKernelGroupService.ts create mode 100644 src/ntqqapi/services/NodeIKernelProfileLikeService.ts diff --git a/src/common/data.ts b/src/common/data.ts index 4287849..6ef4a1d 100644 --- a/src/common/data.ts +++ b/src/common/data.ts @@ -33,6 +33,8 @@ export const llonebotError: LLOneBotError = { wsServerError: '', otherError: 'LLOnebot未能正常启动,请检查日志查看错误', } +// 群号 -> 群成员map(uid=>GroupMember) +export const groupMembers: Map> = new Map>() export async function getFriend(uinOrUid: string): Promise { let filterKey = isNumeric(uinOrUid.toString()) ? 'uin' : 'uid' @@ -79,34 +81,32 @@ export function deleteGroup(groupCode: string) { export async function getGroupMember(groupQQ: string | number, memberUinOrUid: string | number) { groupQQ = groupQQ.toString() memberUinOrUid = memberUinOrUid.toString() - const group = await getGroup(groupQQ) - if (group) { - const filterKey = isNumeric(memberUinOrUid) ? 'uin' : 'uid' - const filterValue = memberUinOrUid - let filterFunc: (member: GroupMember) => boolean = (member) => member[filterKey] === filterValue - let member = group.members?.find(filterFunc) - if (!member) { - try { - const _members = await NTQQGroupApi.getGroupMembers(groupQQ) - if (_members.length > 0) { - group.members = _members - } - } catch (e) { - // log("刷新群成员列表失败", e.stack.toString()) - } - - member = group.members?.find(filterFunc) + let members = groupMembers.get(groupQQ) + if (!members) { + try { + members = await NTQQGroupApi.getGroupMembers(groupQQ) + // 更新群成员列表 + groupMembers.set(groupQQ, members) + } + catch (e) { + return null + } + } + const getMember = () => { + let member: GroupMember | undefined = undefined + if (isNumeric(memberUinOrUid)) { + member = Array.from(members!.values()).find(member => member.uin === memberUinOrUid) + } else { + member = members!.get(memberUinOrUid) } return member } - return null -} - -export async function refreshGroupMembers(groupQQ: string) { - const group = groups.find((group) => group.groupCode === groupQQ) - if (group) { - group.members = await NTQQGroupApi.getGroupMembers(groupQQ) + let member = getMember() + if (!member) { + members = await NTQQGroupApi.getGroupMembers(groupQQ) + member = getMember() } + return member } export const uidMaps: Record = {} // 一串加密的字符串(uid) -> qq号 diff --git a/src/common/utils/QQBasicInfo.ts b/src/common/utils/QQBasicInfo.ts index 29c0ceb..2e7c5e1 100644 --- a/src/common/utils/QQBasicInfo.ts +++ b/src/common/utils/QQBasicInfo.ts @@ -33,17 +33,17 @@ if (typeof configVersionInfoPath !== 'string') { export { configVersionInfoPath } type QQPkgInfo = { - version: string; - buildVersion: string; - platform: string; - eleArch: string; + version: string + buildVersion: string + platform: string + eleArch: string } type QQVersionConfigInfo = { - baseVersion: string; - curVersion: string; - prevVersion: string; - onErrorVersions: Array; - buildId: string; + baseVersion: string + curVersion: string + prevVersion: string + onErrorVersions: Array + buildId: string } let _qqVersionConfigInfo: QQVersionConfigInfo = { @@ -80,4 +80,8 @@ if (systemPlatform === 'linux') { } // todo: mac 平台的 appid export const appid = _appid -export const isQQ998: boolean = qqPkgInfo.buildVersion >= '22106' \ No newline at end of file +export const isQQ998: boolean = qqPkgInfo.buildVersion >= '22106' + +export function getBuildVersion(): number { + return +qqPkgInfo.buildVersion +} \ No newline at end of file diff --git a/src/common/utils/helper.ts b/src/common/utils/helper.ts index 275d786..1dbbd0a 100644 --- a/src/common/utils/helper.ts +++ b/src/common/utils/helper.ts @@ -74,24 +74,50 @@ export function wrapText(str: string, maxLength: number): string { * @returns 处理后缓存或调用原方法的结果 */ export function cacheFunc(ttl: number, customKey: string = '') { - const cache = new Map(); + const cache = new Map() return function (target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor { - const originalMethod = descriptor.value; - const className = target.constructor.name; // 获取类名 - const methodName = propertyKey; // 获取方法名 + const originalMethod = descriptor.value + const className = target.constructor.name // 获取类名 + const methodName = propertyKey // 获取方法名 descriptor.value = async function (...args: any[]) { - const cacheKey = `${customKey}${className}.${methodName}:${JSON.stringify(args)}`; - const cached = cache.get(cacheKey); + const cacheKey = `${customKey}${className}.${methodName}:${JSON.stringify(args)}` + const cached = cache.get(cacheKey) if (cached && cached.expiry > Date.now()) { - return cached.value; + return cached.value } else { - const result = await originalMethod.apply(this, args); - cache.set(cacheKey, { value: result, expiry: Date.now() + ttl }); - return result; + const result = await originalMethod.apply(this, args) + cache.set(cacheKey, { value: result, expiry: Date.now() + ttl }) + return result } - }; + } - return descriptor; - }; + return descriptor + } +} + +export function CacheClassFuncAsyncExtend(ttl: number = 3600 * 1000, customKey: string = '', checker: any = (...data: any[]) => { return true }) { + function logExecutionTime(target: any, methodName: string, descriptor: PropertyDescriptor) { + const cache = new Map() + const originalMethod = descriptor.value + descriptor.value = async function (...args: any[]) { + const key = `${customKey}${String(methodName)}.(${args.map(arg => JSON.stringify(arg)).join(', ')})` + cache.forEach((value, key) => { + if (value.expiry < Date.now()) { + cache.delete(key) + } + }) + const cachedValue = cache.get(key) + if (cachedValue && cachedValue.expiry > Date.now()) { + return cachedValue.value + } + const result = await originalMethod.apply(this, args) + if (!checker(...args, result)) { + return result //丢弃缓存 + } + cache.set(key, { expiry: Date.now() + ttl, value: result }) + return result + } + } + return logExecutionTime } \ No newline at end of file diff --git a/src/common/utils/table.ts b/src/common/utils/table.ts new file mode 100644 index 0000000..bdb9e02 --- /dev/null +++ b/src/common/utils/table.ts @@ -0,0 +1,71 @@ +export class LimitedHashTable { + private keyToValue: Map = new Map() + private valueToKey: Map = new Map() + private maxSize: number + + constructor(maxSize: number) { + this.maxSize = maxSize + } + + resize(count: number) { + this.maxSize = count + } + + set(key: K, value: V): void { + this.keyToValue.set(key, value) + this.valueToKey.set(value, key) + while (this.keyToValue.size !== this.valueToKey.size) { + console.log('keyToValue.size !== valueToKey.size Error Atom') + this.keyToValue.clear() + this.valueToKey.clear() + } + while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) { + const oldestKey = this.keyToValue.keys().next().value + this.valueToKey.delete(this.keyToValue.get(oldestKey)!) + this.keyToValue.delete(oldestKey) + } + } + + getValue(key: K): V | undefined { + return this.keyToValue.get(key) + } + + getKey(value: V): K | undefined { + return this.valueToKey.get(value) + } + + deleteByValue(value: V): void { + const key = this.valueToKey.get(value) + if (key !== undefined) { + this.keyToValue.delete(key) + this.valueToKey.delete(value) + } + } + + deleteByKey(key: K): void { + const value = this.keyToValue.get(key) + if (value !== undefined) { + this.keyToValue.delete(key) + this.valueToKey.delete(value) + } + } + + getKeyList(): K[] { + return Array.from(this.keyToValue.keys()) + } + + //获取最近刚写入的几个值 + getHeads(size: number): { key: K; value: V }[] | undefined { + const keyList = this.getKeyList() + if (keyList.length === 0) { + return undefined + } + const result: { key: K; value: V }[] = [] + const listSize = Math.min(size, keyList.length) + for (let i = 0; i < listSize; i++) { + const key = keyList[listSize - i] + result.push({ key, value: this.keyToValue.get(key)! }) + } + return result + } +} \ No newline at end of file diff --git a/src/main/main.ts b/src/main/main.ts index 99a6893..dc74a4b 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -21,7 +21,6 @@ import { getGroupMember, groups, llonebotError, - refreshGroupMembers, selfInfo, uidMaps, } from '../common/data' @@ -443,32 +442,10 @@ function onLoad() { } }) NTEventDispatch.init({ ListenerMap: wrapperConstructor, WrapperSession: wrapperApi.NodeIQQNTWrapperSession! }) - try { - log('start get groups') - const _groups = await NTQQGroupApi.getGroups() - log('_groups', _groups) - await Promise.all( - _groups.map(async (group) => { - try { - const members = await NTQQGroupApi.getGroupMembers(group.groupCode) - group.members = members - groups.push(group) - } catch (e) { - log('获取群成员失败', e) - } - }) - ) - } - catch (e) { - log('获取群列表失败', e) - } - finally { - log('start activate group member info') - NTQQGroupApi.activateMemberInfoChange().then().catch(log) - NTQQGroupApi.activateMemberListChange().then().catch(log) - startReceiveHook().then() - } - + log('start activate group member info') + NTQQGroupApi.activateMemberInfoChange().then().catch(log) + NTQQGroupApi.activateMemberListChange().then().catch(log) + startReceiveHook().then() if (config.ob11.enableHttp) { ob11HTTPServer.start(config.ob11.httpPort) diff --git a/src/ntqqapi/api/friend.ts b/src/ntqqapi/api/friend.ts index 55384e8..56efd3a 100644 --- a/src/ntqqapi/api/friend.ts +++ b/src/ntqqapi/api/friend.ts @@ -1,10 +1,12 @@ import { Friend, FriendRequest, FriendV2 } from '../types' import { ReceiveCmdS } from '../hook' import { callNTQQApi, GeneralCallResult, NTQQApiMethod } from '../ntcall' -import { friendRequests } from '../../common/data' -import { wrapperApi } from '@/ntqqapi/wrapper' +import { friendRequests } from '@/common/data' +import { getSession } from '@/ntqqapi/wrapper' import { BuddyListReqType, NodeIKernelProfileService } from '../services' -import { NTEventDispatch } from '../../common/utils/EventTask' +import { NTEventDispatch } from '@/common/utils/EventTask' +import { CacheClassFuncAsyncExtend } from '@/common/utils/helper' +import { LimitedHashTable } from '@/common/utils/table' export class NTQQFriendApi { static async getFriends(forced = false) { @@ -69,7 +71,7 @@ export class NTQQFriendApi { static async getBuddyV2(refresh = false): Promise { const uids: string[] = [] - const session = wrapperApi.NodeIQQNTWrapperSession + const session = getSession() const buddyService = session?.getBuddyService() const buddyListV2 = refresh ? await buddyService?.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService?.getBuddyListV2('0', BuddyListReqType.KNOMAL) uids.push(...buddyListV2?.data.flatMap(item => item.buddyUids)!) @@ -78,4 +80,31 @@ export class NTQQFriendApi { ) return Array.from(data.values()) } + + @CacheClassFuncAsyncExtend(3600 * 1000, 'getBuddyIdMap', () => true) + static async getBuddyIdMapCache(refresh = false): Promise> { + return await NTQQFriendApi.getBuddyIdMap(refresh) + } + + static async getBuddyIdMap(refresh = false): Promise> { + const uids: string[] = [] + const retMap: LimitedHashTable = new LimitedHashTable(5000) + const session = getSession() + const buddyService = session?.getBuddyService() + const buddyListV2 = refresh ? await buddyService?.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService?.getBuddyListV2('0', BuddyListReqType.KNOMAL) + uids.push(...buddyListV2?.data.flatMap(item => item.buddyUids)!) + const data = await NTEventDispatch.CallNoListenerEvent( + 'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids + ); + data.forEach((value, key) => { + retMap.set(value.uin!, value.uid!) + }) + //console.log('getBuddyIdMap', retMap.getValue) + return retMap + } + + static async isBuddy(uid: string): Promise { + const session = getSession() + return session?.getBuddyService().isBuddy(uid)! + } } diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts index 0423c80..21dc68f 100644 --- a/src/ntqqapi/api/group.ts +++ b/src/ntqqapi/api/group.ts @@ -5,7 +5,7 @@ import { deleteGroup, uidMaps } from '../../common/data' import { dbUtil } from '../../common/db' import { log } from '../../common/utils/log' import { NTQQWindowApi, NTQQWindows } from './window' -import { wrapperApi } from '../wrapper' +import { getSession } from '../wrapper' export class NTQQGroupApi { static async activateMemberListChange() { @@ -55,45 +55,15 @@ export class NTQQGroupApi { return result.groupList } - static async getGroupMembers(groupQQ: string, num = 3000): Promise { - const sceneId = await callNTQQApi({ - methodName: NTQQApiMethod.GROUP_MEMBER_SCENE, - args: [ - { - groupCode: groupQQ, - scene: 'groupMemberList_MainWindow', - }, - ], - }) - // log("get group member sceneId", sceneId) - try { - const result = await callNTQQApi<{ - result: { infos: any } - }>({ - methodName: NTQQApiMethod.GROUP_MEMBERS, - args: [ - { - sceneId: sceneId, - num: num, - }, - null, - ], - }) - // log("members info", typeof result.result.infos, Object.keys(result.result.infos)) - const values = result.result.infos.values() - - const members: GroupMember[] = Array.from(values) - for (const member of members) { - uidMaps[member.uid] = member.uin - } - // log(uidMaps) - // log("members info", values) - log(`get group ${groupQQ} members success`) - return members - } catch (e) { - log(`get group ${groupQQ} members failed`, e) - return [] + static async getGroupMembers(groupQQ: string, num = 3000): Promise> { + const session = getSession() + const groupService = session?.getGroupService() + const sceneId = groupService?.createMemberListScene(groupQQ, 'groupMemberList_MainWindow') + const result = await groupService?.getNextMemberList(sceneId!, undefined, num) + if (result?.errCode !== 0) { + throw ('获取群成员列表出错,' + result?.errMsg) } + return result.result.infos } static async getGroupMembersInfo(groupCode: string, uids: string[], forceUpdate: boolean = false) { @@ -300,7 +270,7 @@ export class NTQQGroupApi { static publishGroupBulletin(groupQQ: string, title: string, content: string) { } static async removeGroupEssence(GroupCode: string, msgId: string) { - const session = wrapperApi.NodeIQQNTWrapperSession + const session = getSession() // 代码没测过 // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom let MsgData = await session?.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false) @@ -314,7 +284,7 @@ export class NTQQGroupApi { } static async addGroupEssence(GroupCode: string, msgId: string) { - const session = wrapperApi.NodeIQQNTWrapperSession + const session = getSession() // 代码没测过 // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom let MsgData = await session?.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false) diff --git a/src/ntqqapi/api/user.ts b/src/ntqqapi/api/user.ts index ef093d2..a3803a8 100644 --- a/src/ntqqapi/api/user.ts +++ b/src/ntqqapi/api/user.ts @@ -1,14 +1,14 @@ import { callNTQQApi, GeneralCallResult, NTQQApiClass, NTQQApiMethod } from '../ntcall' -import { Group, SelfInfo, User } from '../types' +import { SelfInfo, User, UserDetailInfoByUin, UserDetailInfoByUinV2 } from '../types' import { ReceiveCmdS } from '../hook' -import { selfInfo, uidMaps } from '../../common/data' -import { cacheFunc, isQQ998, log, sleep } from '../../common/utils' -import { wrapperApi } from '@/ntqqapi/wrapper' +import { selfInfo, uidMaps, friends, groupMembers } from '@/common/data' +import { cacheFunc, isQQ998, log, sleep, getBuildVersion } from '@/common/utils' +import { getSession } from '@/ntqqapi/wrapper' import { RequestUtil } from '@/common/utils/request' import { NodeIKernelProfileService, UserDetailSource, ProfileBizType } from '../services' import { NodeIKernelProfileListener } from '../listeners' import { NTEventDispatch } from '@/common/utils/EventTask' -import { qqPkgInfo } from '@/common/utils/QQBasicInfo' +import { NTQQFriendApi } from './friend' const userInfoCache: Record = {} // uid: User @@ -50,7 +50,7 @@ export class NTQQUserApi { return result.profiles.get(uid) } - // 26702 + /** 26702 */ static async fetchUserDetailInfo(uid: string) { type EventService = NodeIKernelProfileService['fetchUserDetailInfo'] type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged'] @@ -63,9 +63,9 @@ export class NTQQUserApi { 5000, (profile) => { if (profile.uid === uid) { - return true; + return true } - return false; + return false }, 'BuddyProfileStore', [ @@ -89,7 +89,7 @@ export class NTQQUserApi { } static async getUserDetailInfo(uid: string, getLevel = false, withBizInfo = true) { - if (+qqPkgInfo.buildVersion >= 26702) { + if (getBuildVersion() >= 26702) { return this.fetchUserDetailInfo(uid) } // this.getUserInfo(uid) @@ -195,7 +195,7 @@ export class NTQQUserApi { } static async getPSkey(domains: string[]): Promise> { - const session = wrapperApi.NodeIQQNTWrapperSession + const session = getSession() const res = await session?.getTipOffService().getPskey(domains, true) if (res.result !== 0) { throw new Error(`获取Pskey失败: ${res.errMsg}`) @@ -204,7 +204,91 @@ export class NTQQUserApi { } static async getClientKey(): Promise { - const session = wrapperApi.NodeIQQNTWrapperSession + const session = getSession() return await session?.getTicketService().forceFetchClientKey('') } + + static async like(uid: string, count = 1): Promise<{ result: number, errMsg: string, succCounts: number }> { + const session = getSession() + return session?.getProfileLikeService().setBuddyProfileLike({ + friendUid: uid, + sourceId: 71, + doLikeCount: count, + doLikeTollCount: 0 + })! + } + + static async getUidByUinV1(Uin: string) { + const session = getSession() + // 通用转换开始尝试 + let uid = (await session?.getUixConvertService().getUid([Uin])).uidInfo.get(Uin); + // Uid 好友转 + if (!uid) { + friends.forEach((t) => { + if (t.uin == Uin) { + uid = t.uid + } + }) + } + //Uid 群友列表转 + if (!uid) { + for (let groupMembersList of groupMembers.values()) { + for (let GroupMember of groupMembersList.values()) { + if (GroupMember.uin == Uin) { + uid = GroupMember.uid + } + } + } + } + if (!uid) { + let unveifyUid = (await NTQQUserApi.getUserDetailInfoByUin(Uin)).info.uid;//从QQ Native 特殊转换 方法三 + if (unveifyUid.indexOf('*') == -1) { + uid = unveifyUid + } + } + return uid + } + + static async getUidByUinV2(Uin: string) { + const session = getSession() + let uid = (await session?.getProfileService().getUidByUin('FriendsServiceImpl', [Uin])!).get(Uin) + if (uid) return uid + uid = (await session?.getGroupService().getUidByUins([Uin])!).uids.get(Uin) + if (uid) return uid + uid = (await session?.getUixConvertService().getUid([Uin])).uidInfo.get(Uin) + if (uid) return uid + console.log((await NTQQFriendApi.getBuddyIdMapCache(true))) + uid = (await NTQQFriendApi.getBuddyIdMapCache(true)).getValue(Uin)//从Buddy缓存获取Uid + if (uid) return uid + uid = (await NTQQFriendApi.getBuddyIdMap(true)).getValue(Uin) + if (uid) return uid + let unveifyUid = (await NTQQUserApi.getUserDetailInfoByUinV2(Uin)).detail.uid//从QQ Native 特殊转换 + if (unveifyUid.indexOf("*") == -1) uid = unveifyUid + //if (uid) return uid + return uid + } + + static async getUidByUin(Uin: string) { + if (getBuildVersion() >= 26702) { + return await NTQQUserApi.getUidByUinV2(Uin) + } + return await NTQQUserApi.getUidByUinV1(Uin) + } + + static async getUserDetailInfoByUinV2(Uin: string) { + return await NTEventDispatch.CallNoListenerEvent + <(Uin: string) => Promise>( + 'NodeIKernelProfileService/getUserDetailInfoByUin', + 5000, + Uin + ) + } + static async getUserDetailInfoByUin(Uin: string) { + return NTEventDispatch.CallNoListenerEvent + <(Uin: string) => Promise>( + 'NodeIKernelProfileService/getUserDetailInfoByUin', + 5000, + Uin + ) + } } diff --git a/src/ntqqapi/constructor.ts b/src/ntqqapi/constructor.ts index a03bb04..f99f18a 100644 --- a/src/ntqqapi/constructor.ts +++ b/src/ntqqapi/constructor.ts @@ -21,7 +21,7 @@ import { log } from '../common/utils/log' import { defaultVideoThumb, getVideoInfo } from '../common/utils/video' import { encodeSilk } from '../common/utils/audio' import { isNull } from '../common/utils' -import faceConfig from './face_config.json'; +import faceConfig from './face_config.json' export const mFaceCache = new Map() // emojiId -> faceName diff --git a/src/ntqqapi/hook.ts b/src/ntqqapi/hook.ts index 020c2e6..b8d651d 100644 --- a/src/ntqqapi/hook.ts +++ b/src/ntqqapi/hook.ts @@ -268,7 +268,7 @@ async function updateGroups(_groups: Group[], needUpdate: boolean = true) { const members = await NTQQGroupApi.getGroupMembers(group.groupCode) if (members) { - existGroup.members = members + existGroup.members = Array.from(members.values()) } } } @@ -287,11 +287,11 @@ async function processGroupEvent(payload: { groupList: Group[] }) { await sleep(200) // 如果请求QQ API的速度过快,通常无法正确拉取到最新的群信息,因此这里人为引入一个延时 const newMembers = await NTQQGroupApi.getGroupMembers(group.groupCode) - group.members = newMembers + group.members = Array.from(newMembers.values()) const newMembersSet = new Set() // 建立索引降低时间复杂度 for (const member of newMembers) { - newMembersSet.add(member.uin) + newMembersSet.add(member[1].uin) } // 判断bot是否是管理员,如果是管理员不需要从这里得知有人退群,这里的退群无法得知是主动退群还是被踢 diff --git a/src/ntqqapi/listeners/NodeIKernelGroupListener.ts b/src/ntqqapi/listeners/NodeIKernelGroupListener.ts new file mode 100644 index 0000000..ae4a4f9 --- /dev/null +++ b/src/ntqqapi/listeners/NodeIKernelGroupListener.ts @@ -0,0 +1,240 @@ +import { Group, GroupListUpdateType, GroupMember, GroupNotify } from '@/ntqqapi/types' + +interface IGroupListener { + onGroupListUpdate(updateType: GroupListUpdateType, groupList: Group[]): void + + onGroupExtListUpdate(...args: unknown[]): void + + onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]): void + + onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]): void + + onGroupNotifiesUnreadCountUpdated(...args: unknown[]): void + + onGroupDetailInfoChange(...args: unknown[]): void + + onGroupAllInfoChange(...args: unknown[]): void + + onGroupsMsgMaskResult(...args: unknown[]): void + + onGroupConfMemberChange(...args: unknown[]): void + + onGroupBulletinChange(...args: unknown[]): void + + onGetGroupBulletinListResult(...args: unknown[]): void + + onMemberListChange(arg: { + sceneId: string, + ids: string[], + infos: Map, + finish: boolean, + hasRobot: boolean + }): void + + onMemberInfoChange(groupCode: string, changeType: number, members: Map): void + + onSearchMemberChange(...args: unknown[]): void + + onGroupBulletinRichMediaDownloadComplete(...args: unknown[]): void + + onGroupBulletinRichMediaProgressUpdate(...args: unknown[]): void + + onGroupStatisticInfoChange(...args: unknown[]): void + + onJoinGroupNotify(...args: unknown[]): void + + onShutUpMemberListChanged(...args: unknown[]): void + + onGroupBulletinRemindNotify(...args: unknown[]): void + + onGroupFirstBulletinNotify(...args: unknown[]): void + + onJoinGroupNoVerifyFlag(...args: unknown[]): void + + onGroupArkInviteStateResult(...args: unknown[]): void + // 发现于Win 9.9.9 23159 + onGroupMemberLevelInfoChange(...args: unknown[]): void +} + +export interface NodeIKernelGroupListener extends IGroupListener { + // eslint-disable-next-line @typescript-eslint/no-misused-new + new(listener: IGroupListener): NodeIKernelGroupListener +} + +export class GroupListener implements IGroupListener { + // 发现于Win 9.9.9 23159 + onGroupMemberLevelInfoChange(...args: unknown[]): void { + + } + onGetGroupBulletinListResult(...args: unknown[]) { + } + + onGroupAllInfoChange(...args: unknown[]) { + } + + onGroupBulletinChange(...args: unknown[]) { + } + + onGroupBulletinRemindNotify(...args: unknown[]) { + } + + onGroupArkInviteStateResult(...args: unknown[]) { + } + + onGroupBulletinRichMediaDownloadComplete(...args: unknown[]) { + } + + onGroupConfMemberChange(...args: unknown[]) { + } + + onGroupDetailInfoChange(...args: unknown[]) { + } + + onGroupExtListUpdate(...args: unknown[]) { + } + + onGroupFirstBulletinNotify(...args: unknown[]) { + } + + onGroupListUpdate(updateType: GroupListUpdateType, groupList: Group[]) { + } + + onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]) { + } + + onGroupBulletinRichMediaProgressUpdate(...args: unknown[]) { + } + + onGroupNotifiesUnreadCountUpdated(...args: unknown[]) { + } + + onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]) { + } + + onGroupsMsgMaskResult(...args: unknown[]) { + } + + onGroupStatisticInfoChange(...args: unknown[]) { + } + + onJoinGroupNotify(...args: unknown[]) { + } + + onJoinGroupNoVerifyFlag(...args: unknown[]) { + } + + onMemberInfoChange(groupCode: string, changeType: number, members: Map) { + } + + onMemberListChange(arg: { + sceneId: string, + ids: string[], + infos: Map, // uid -> GroupMember + finish: boolean, + hasRobot: boolean + }) { + } + + onSearchMemberChange(...args: unknown[]) { + } + + onShutUpMemberListChanged(...args: unknown[]) { + } +} + +export class DebugGroupListener implements IGroupListener { + onGroupMemberLevelInfoChange(...args: unknown[]): void { + console.log('onGroupMemberLevelInfoChange:', ...args) + } + onGetGroupBulletinListResult(...args: unknown[]) { + console.log('onGetGroupBulletinListResult:', ...args) + } + + onGroupAllInfoChange(...args: unknown[]) { + console.log('onGroupAllInfoChange:', ...args) + } + + onGroupBulletinChange(...args: unknown[]) { + console.log('onGroupBulletinChange:', ...args) + } + + onGroupBulletinRemindNotify(...args: unknown[]) { + console.log('onGroupBulletinRemindNotify:', ...args) + } + + onGroupArkInviteStateResult(...args: unknown[]) { + console.log('onGroupArkInviteStateResult:', ...args) + } + + onGroupBulletinRichMediaDownloadComplete(...args: unknown[]) { + console.log('onGroupBulletinRichMediaDownloadComplete:', ...args) + } + + onGroupConfMemberChange(...args: unknown[]) { + console.log('onGroupConfMemberChange:', ...args) + } + + onGroupDetailInfoChange(...args: unknown[]) { + console.log('onGroupDetailInfoChange:', ...args) + } + + onGroupExtListUpdate(...args: unknown[]) { + console.log('onGroupExtListUpdate:', ...args) + } + + onGroupFirstBulletinNotify(...args: unknown[]) { + console.log('onGroupFirstBulletinNotify:', ...args) + } + + onGroupListUpdate(...args: unknown[]) { + console.log('onGroupListUpdate:', ...args) + } + + onGroupNotifiesUpdated(...args: unknown[]) { + console.log('onGroupNotifiesUpdated:', ...args) + } + + onGroupBulletinRichMediaProgressUpdate(...args: unknown[]) { + console.log('onGroupBulletinRichMediaProgressUpdate:', ...args) + } + + onGroupNotifiesUnreadCountUpdated(...args: unknown[]) { + console.log('onGroupNotifiesUnreadCountUpdated:', ...args) + } + + onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]) { + console.log('onGroupSingleScreenNotifies:') + } + + onGroupsMsgMaskResult(...args: unknown[]) { + console.log('onGroupsMsgMaskResult:', ...args) + } + + onGroupStatisticInfoChange(...args: unknown[]) { + console.log('onGroupStatisticInfoChange:', ...args) + } + + onJoinGroupNotify(...args: unknown[]) { + console.log('onJoinGroupNotify:', ...args) + } + + onJoinGroupNoVerifyFlag(...args: unknown[]) { + console.log('onJoinGroupNoVerifyFlag:', ...args) + } + + onMemberInfoChange(groupCode: string, changeType: number, members: Map) { + console.log('onMemberInfoChange:', groupCode, changeType, members) + } + + onMemberListChange(...args: unknown[]) { + console.log('onMemberListChange:', ...args) + } + + onSearchMemberChange(...args: unknown[]) { + console.log('onSearchMemberChange:', ...args) + } + + onShutUpMemberListChanged(...args: unknown[]) { + console.log('onShutUpMemberListChanged:', ...args) + } +} \ No newline at end of file diff --git a/src/ntqqapi/listeners/index.ts b/src/ntqqapi/listeners/index.ts index b3932e9..66fb556 100644 --- a/src/ntqqapi/listeners/index.ts +++ b/src/ntqqapi/listeners/index.ts @@ -1 +1,2 @@ -export * from './NodeIKernelProfileListener' \ No newline at end of file +export * from './NodeIKernelProfileListener' +export * from './NodeIKernelGroupListener' \ No newline at end of file diff --git a/src/ntqqapi/services/NodeIKernelGroupService.ts b/src/ntqqapi/services/NodeIKernelGroupService.ts new file mode 100644 index 0000000..860e53a --- /dev/null +++ b/src/ntqqapi/services/NodeIKernelGroupService.ts @@ -0,0 +1,249 @@ +import { NodeIKernelGroupListener } from '@/ntqqapi/listeners' +import { + GroupExtParam, + GroupMember, + GroupMemberRole, + GroupNotifyTypes, + GroupRequestOperateTypes, +} from '@/ntqqapi/types' +import { GeneralCallResult } from './common' + +//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底 + +export interface NodeIKernelGroupService { + getMemberCommonInfo(Req: { + groupCode: string, + startUin: string, + identifyFlag: string, + uinList: string[], + memberCommonFilter: { + memberUin: number, + uinFlag: number, + uinFlagExt: number, + uinMobileFlag: number, + shutUpTime: number, + privilege: number, + }, + memberNum: number, + filterMethod: string, + onlineFlag: string, + realSpecialTitleFlag: number + }): Promise + //26702 + getGroupMemberLevelInfo(groupCode: string): Promise + //26702 + getGroupHonorList(groupCodes: Array): unknown + + getUinByUids(uins: string[]): Promise<{ + errCode: number, + errMsg: string, + uins: Map + }> + + getUidByUins(uins: string[]): Promise<{ + errCode: number, + errMsg: string, + uids: Map + }> + //26702(其实更早 但是我不知道) + checkGroupMemberCache(arrayList: Array): Promise + + //26702(其实更早 但是我不知道) + getGroupLatestEssenceList(groupCode: string): Promise + + //26702(其实更早 但是我不知道) + shareDigest(Req: { + appId: string, + appType: number, + msgStyle: number, + recvUin: string, + sendType: number, + clientInfo: { + platform: number + }, + richMsg: { + usingArk: boolean, + title: string, + summary: string, + url: string, + pictureUrl: string, + brief: string + } + }): Promise + //26702(其实更早 但是我不知道) + isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise + //26702(其实更早 但是我不知道) + queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise + //26702(其实更早 但是我不知道) + fetchGroupEssenceList(Req: { groupCode: string, pageStart: number, pageLimit: number }, Arg: unknown): Promise + //26702 + getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{ + errCode: number, + errMsg: string, + result: { + ids: Array<{ + uid: string, + index: number//0 + }>, + infos: {}, + finish: true, + hasRobot: false + } + }> + + setHeader(uid: string, path: string): unknown + + addKernelGroupListener(listener: NodeIKernelGroupListener): number + + removeKernelGroupListener(listenerId: unknown): void + + createMemberListScene(groupCode: string, scene: string): string + + destroyMemberListScene(SceneId: string): void + //About Arg (a) name: lastId 根据手Q来看为object {index:?(number),uid:string} + getNextMemberList(sceneId: string, a: undefined, num: number): Promise<{ + errCode: number, errMsg: string, + result: { ids: string[], infos: Map, finish: boolean, hasRobot: boolean } + }> + + getPrevMemberList(): unknown + + monitorMemberList(): unknown + + searchMember(sceneId: string, keywords: string[]): unknown + + getMemberInfo(group_id: string, uids: string[], forceFetch: boolean): Promise + //getMemberInfo [ '56729xxxx', [ 'u_4Nj08cwW5Hxxxxx' ], true ] + + kickMember(groupCode: string, memberUids: string[], refuseForever: boolean, kickReason: string): Promise + + modifyMemberRole(groupCode: string, uid: string, role: GroupMemberRole): void + + modifyMemberCardName(groupCode: string, uid: string, cardName: string): void + + getTransferableMemberInfo(groupCode: string): unknown//获取整个群的 + + transferGroup(uid: string): void + + getGroupList(force: boolean): Promise + + getGroupExtList(force: boolean): Promise + + getGroupDetailInfo(groupCode: string): unknown + + getMemberExtInfo(param: GroupExtParam): Promise//req + + getGroupAllInfo(): unknown + + getDiscussExistInfo(): unknown + + getGroupConfMember(): unknown + + getGroupMsgMask(): unknown + + getGroupPortrait(): void + + modifyGroupName(groupCode: string, groupName: string, arg: false): void + + modifyGroupRemark(groupCode: string, remark: string): void + + modifyGroupDetailInfo(groupCode: string, arg: unknown): void + + setGroupMsgMask(groupCode: string, arg: unknown): void + + changeGroupShieldSettingTemp(groupCode: string, arg: unknown): void + + inviteToGroup(arg: unknown): void + + inviteMembersToGroup(args: unknown[]): void + + inviteMembersToGroupWithMsg(args: unknown): void + + createGroup(arg: unknown): void + + createGroupWithMembers(arg: unknown): void + + quitGroup(groupCode: string): void + + destroyGroup(groupCode: string): void + //获取单屏群通知列表 + getSingleScreenNotifies(force: boolean, start_seq: string, num: number): Promise + + clearGroupNotifies(groupCode: string): void + + getGroupNotifiesUnreadCount(unknown: Boolean): Promise + + clearGroupNotifiesUnreadCount(groupCode: string): void + + operateSysNotify( + doubt: boolean, + operateMsg: { + operateType: GroupRequestOperateTypes, // 2 拒绝 + targetMsg: { + seq: string, // 通知序列号 + type: GroupNotifyTypes, + groupCode: string, + postscript: string + } + }): Promise + + setTop(groupCode: string, isTop: boolean): void + + getGroupBulletin(groupCode: string): unknown + + deleteGroupBulletin(groupCode: string, seq: string): void + + publishGroupBulletin(groupCode: string, pskey: string, data: any): Promise + + publishInstructionForNewcomers(groupCode: string, arg: unknown): void + + uploadGroupBulletinPic(groupCode: string, pskey: string, imagePath: string): Promise + + downloadGroupBulletinRichMedia(groupCode: string): unknown + + getGroupBulletinList(groupCode: string): unknown + + getGroupStatisticInfo(groupCode: string): unknown + + getGroupRemainAtTimes(groupCode: string): number + + getJoinGroupNoVerifyFlag(groupCode: string): unknown + + getGroupArkInviteState(groupCode: string): unknown + + reqToJoinGroup(groupCode: string, arg: unknown): void + + setGroupShutUp(groupCode: string, shutUp: boolean): void + + getGroupShutUpMemberList(groupCode: string): unknown[] + + setMemberShutUp(groupCode: string, memberTimes: { uid: string, timeStamp: number }[]): Promise + + getGroupRecommendContactArkJson(groupCode: string): unknown + + getJoinGroupLink(groupCode: string): unknown + + modifyGroupExtInfo(groupCode: string, arg: unknown): void + + //需要提前判断是否存在 高版本新增 + addGroupEssence(param: { + groupCode: string + msgRandom: number, + msgSeq: number + }): Promise + //需要提前判断是否存在 高版本新增 + removeGroupEssence(param: { + groupCode: string + msgRandom: number, + msgSeq: number + }): Promise + + isNull(): boolean +} \ No newline at end of file diff --git a/src/ntqqapi/services/NodeIKernelProfileLikeService.ts b/src/ntqqapi/services/NodeIKernelProfileLikeService.ts new file mode 100644 index 0000000..dc44a31 --- /dev/null +++ b/src/ntqqapi/services/NodeIKernelProfileLikeService.ts @@ -0,0 +1,22 @@ +import { BuddyProfileLikeReq } from '../types' +import { GeneralCallResult } from './common' + +export interface NodeIKernelProfileLikeService { + addKernelProfileLikeListener(listener: NodeIKernelProfileLikeService): void + + removeKernelProfileLikeListener(listener: unknown): void + + setBuddyProfileLike(...args: unknown[]): { result: number, errMsg: string, succCounts: number } + + getBuddyProfileLike(req: BuddyProfileLikeReq): Promise, + 'friendMaxVotes': number, + 'start': number + } + }> + + getProfileLikeScidResourceInfo(...args: unknown[]): void + + isNull(): boolean +} \ No newline at end of file diff --git a/src/ntqqapi/services/index.ts b/src/ntqqapi/services/index.ts index 3e5969f..052026d 100644 --- a/src/ntqqapi/services/index.ts +++ b/src/ntqqapi/services/index.ts @@ -1,2 +1,4 @@ export * from './NodeIKernelBuddyService' -export * from './NodeIKernelProfileService' \ No newline at end of file +export * from './NodeIKernelProfileService' +export * from './NodeIKernelGroupService' +export * from './NodeIKernelProfileLikeService' \ No newline at end of file diff --git a/src/ntqqapi/types/group.ts b/src/ntqqapi/types/group.ts index fc17b72..4ba3e07 100644 --- a/src/ntqqapi/types/group.ts +++ b/src/ntqqapi/types/group.ts @@ -1,5 +1,12 @@ import { QQLevel, Sex } from './user' +export enum GroupListUpdateType { + REFRESHALL, + GETALL, + MODIFIED, + REMOVE +} + export interface Group { groupCode: string maxMember: number diff --git a/src/ntqqapi/types/notify.ts b/src/ntqqapi/types/notify.ts index cf91bc3..0b8c05b 100644 --- a/src/ntqqapi/types/notify.ts +++ b/src/ntqqapi/types/notify.ts @@ -64,3 +64,41 @@ export interface FriendRequestNotify { buddyReqs: FriendRequest[] } } + +export enum MemberExtSourceType { + DEFAULTTYPE = 0, + TITLETYPE = 1, + NEWGROUPTYPE = 2, +} + +export interface GroupExtParam { + groupCode: string + seq: string + beginUin: string + dataTime: string + uinList: Array + uinNum: string + groupType: string + richCardNameVer: string + sourceType: MemberExtSourceType + memberExtFilter: { + memberLevelInfoUin: number + memberLevelInfoPoint: number + memberLevelInfoActiveDay: number + memberLevelInfoLevel: number + memberLevelInfoName: number + levelName: number + dataTime: number + userShowFlag: number + sysShowFlag: number + timeToUpdate: number + nickName: number + specialTitle: number + levelNameNew: number + userShowFlagNew: number + msgNeedField: number + cmdUinFlagExt3Grocery: number + memberIcon: number + memberInfoSeq: number + } +} \ No newline at end of file diff --git a/src/ntqqapi/types/user.ts b/src/ntqqapi/types/user.ts index 8538265..e109794 100644 --- a/src/ntqqapi/types/user.ts +++ b/src/ntqqapi/types/user.ts @@ -258,4 +258,86 @@ export interface UserDetailInfoListenerArg { simpleInfo: SimpleInfo commonExt: CommonExt photoWall: PhotoWall +} + +export interface BuddyProfileLikeReq { + friendUids: string[] + basic: number + vote: number + favorite: number + userProfile: number + type: number + start: number + limit: number +} + +export interface UserDetailInfoByUinV2 { + result: number + errMsg: string + detail: { + uid: string + uin: string + simpleInfo: SimpleInfo + commonExt: CommonExt + photoWall: null + } +} + +export interface UserDetailInfoByUin { + result: number + errMsg: string + info: { + uid: string //这个没办法用 + qid: string + uin: string + nick: string + remark: string + longNick: string + avatarUrl: string + birthday_year: number + birthday_month: number + birthday_day: number + sex: number //0 + topTime: string + constellation: number + shengXiao: number + kBloodType: number + homeTown: string + makeFriendCareer: number + pos: string + eMail: string + phoneNum: string + college: string + country: string + province: string + city: string + postCode: string + address: string + isBlock: boolean + isSpecialCareOpen: boolean + isSpecialCareZone: boolean + ringId: string + regTime: number + interest: string + termType: number + labels: any[] + qqLevel: { crownNum: number, sunNum: number, moonNum: number, starNum: number } + isHideQQLevel: number + privilegeIcon: { jumpUrl: string, openIconList: any[], closeIconList: any[] } + isHidePrivilegeIcon: number + photoWall: { picList: any[] } + vipFlag: boolean + yearVipFlag: boolean + svipFlag: boolean + vipLevel: number + status: number + qidianMasterFlag: number + qidianCrewFlag: number + qidianCrewFlag2: number + extStatus: number + recommendImgFlag: number + disableEmojiShortCuts: number + pendantId: string + vipNameColorId: string + } } \ No newline at end of file diff --git a/src/ntqqapi/wrapper.ts b/src/ntqqapi/wrapper.ts index 40ed806..31e7f1c 100644 --- a/src/ntqqapi/wrapper.ts +++ b/src/ntqqapi/wrapper.ts @@ -1,10 +1,18 @@ -import { NodeIKernelBuddyService } from './services/NodeIKernelBuddyService' +import { + NodeIKernelBuddyService, + NodeIKernelGroupService, + NodeIKernelProfileService, + NodeIKernelProfileLikeService +} from './services' import os from 'node:os' const Process = require('node:process') export interface NodeIQQNTWrapperSession { [key: string]: any getBuddyService(): NodeIKernelBuddyService + getGroupService(): NodeIKernelGroupService + getProfileService(): NodeIKernelProfileService + getProfileLikeService(): NodeIKernelProfileLikeService } export interface WrapperApi { @@ -65,4 +73,8 @@ Process.dlopen = function (module, filename, flags = os.constants.dlopen.RTLD_LA } } return dlopenRet +} + +export function getSession() { + return wrapperApi.NodeIQQNTWrapperSession } \ No newline at end of file diff --git a/src/onebot11/action/group/GetGroupMemberList.ts b/src/onebot11/action/group/GetGroupMemberList.ts index 150426b..86e4456 100644 --- a/src/onebot11/action/group/GetGroupMemberList.ts +++ b/src/onebot11/action/group/GetGroupMemberList.ts @@ -18,7 +18,8 @@ class GetGroupMemberList extends BaseAction { const group = await getGroup(payload.group_id.toString()) if (group) { if (!group.members?.length || payload.no_cache === true || payload.no_cache === 'true') { - group.members = await NTQQGroupApi.getGroupMembers(payload.group_id.toString()) + const members = await NTQQGroupApi.getGroupMembers(payload.group_id.toString()) + group.members = Array.from(members.values()) log('强制刷新群成员列表, 数量: ', group.members.length) } return OB11Constructor.groupMembers(group) diff --git a/src/onebot11/action/msg/SendMsg.ts b/src/onebot11/action/msg/SendMsg.ts index 25c25fd..7df510c 100644 --- a/src/onebot11/action/msg/SendMsg.ts +++ b/src/onebot11/action/msg/SendMsg.ts @@ -7,10 +7,9 @@ import { GroupMemberRole, PicSubType, RawMessage, - SendArkElement, SendMessageElement, } from '../../../ntqqapi/types' -import { friends, getFriend, getGroup, getGroupMember, getUidByUin, selfInfo } from '../../../common/data' +import { friends, getGroup, getGroupMember, getUidByUin, selfInfo } from '../../../common/data' import { OB11MessageCustomMusic, OB11MessageData, @@ -20,63 +19,21 @@ import { OB11MessageMixType, OB11MessageMusic, OB11MessageNode, - OB11MessageVideo, OB11PostSendMsg, } from '../../types' -import { NTQQMsgApi } from '../../../ntqqapi/api/msg' import { SendMsgElementConstructor } from '../../../ntqqapi/constructor' import BaseAction from '../BaseAction' import { ActionName, BaseCheckResult } from '../types' -import * as fs from 'node:fs' +import fs from 'node:fs' import { decodeCQCode } from '../../cqcode' import { dbUtil } from '../../../common/db' import { ALLOW_SEND_TEMP_MSG, getConfigUtil } from '../../../common/config' import { log } from '../../../common/utils/log' import { sleep } from '../../../common/utils/helper' import { uri2local } from '../../../common/utils' -import { NTQQGroupApi } from '../../../ntqqapi/api' -import { CustomMusicSignPostData, IdMusicSignPostData, MusicSign, MusicSignPostData } from '../../../common/utils/sign' -import { Peer } from '../../../ntqqapi/types/msg' - -function checkSendMessage(sendMsgList: OB11MessageData[]) { - function checkUri(uri: string): boolean { - const pattern = /^(file:\/\/|http:\/\/|https:\/\/|base64:\/\/)/ - return pattern.test(uri) - } - - for (let msg of sendMsgList) { - if (msg['type'] && msg['data']) { - let type = msg['type'] - let data = msg['data'] - if (type === 'text' && !data['text']) { - return 400 - } - else if (['image', 'voice', 'record'].includes(type)) { - if (!data['file']) { - return 400 - } - else { - if (checkUri(data['file'])) { - return 200 - } - else { - return 400 - } - } - } - else if (type === 'at' && !data['qq']) { - return 400 - } - else if (type === 'reply' && !data['id']) { - return 400 - } - } - else { - return 400 - } - } - return 200 -} +import { NTQQGroupApi, NTQQMsgApi, NTQQUserApi, NTQQFriendApi } from '@/ntqqapi/api' +import { CustomMusicSignPostData, IdMusicSignPostData, MusicSign, MusicSignPostData } from '@/common/utils/sign' +import { Peer } from '@/ntqqapi/types/msg' export interface ReturnDataType { message_id: number @@ -351,13 +308,11 @@ export class SendMsg extends BaseAction { } } if (payload.user_id && payload.message_type !== 'group') { - if (!(await getFriend(payload.user_id))) { - if (!ALLOW_SEND_TEMP_MSG && !(await dbUtil.getReceivedTempUinMap())[payload.user_id.toString()]) { - return { - valid: false, - message: `不能发送临时消息`, - } - } + const uid = await NTQQUserApi.getUidByUin(payload.user_id.toString()) + const isBuddy = await NTQQFriendApi.isBuddy(uid!) + // 此处有问题 + if (!isBuddy) { + //return { valid: false, message: '异常消息' } } } return { diff --git a/src/onebot11/action/user/SendLike.ts b/src/onebot11/action/user/SendLike.ts index 34694ac..4048814 100644 --- a/src/onebot11/action/user/SendLike.ts +++ b/src/onebot11/action/user/SendLike.ts @@ -1,8 +1,6 @@ import BaseAction from '../BaseAction' -import { getFriend, getUidByUin, uidMaps } from '../../../common/data' import { ActionName } from '../types' -import { NTQQFriendApi } from '../../../ntqqapi/api/friend' -import { log } from '../../../common/utils/log' +import { NTQQUserApi } from '@/ntqqapi/api' interface Payload { user_id: number @@ -13,19 +11,12 @@ export default class SendLike extends BaseAction { actionName = ActionName.SendLike protected async _handle(payload: Payload): Promise { - log('点赞参数', payload) try { const qq = payload.user_id.toString() - const friend = await getFriend(qq) - let uid: string - if (!friend) { - uid = getUidByUin(qq)! - } else { - uid = friend.uid - } - let result = await NTQQFriendApi.likeFriend(uid, parseInt(payload.times?.toString()) || 1) + const uid: string = await NTQQUserApi.getUidByUin(qq) || '' + const result = await NTQQUserApi.like(uid, parseInt(payload.times?.toString()) || 1) if (result.result !== 0) { - throw result.errMsg + throw Error(result.errMsg) } } catch (e) { throw `点赞失败 ${e}` diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index c688b81..d45f818 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -26,7 +26,7 @@ import { VideoElement, FriendV2 } from '../ntqqapi/types' -import { deleteGroup, getFriend, getGroupMember, selfInfo, tempGroupCodeMap, uidMaps } from '../common/data' +import { deleteGroup, getGroupMember, selfInfo, tempGroupCodeMap, uidMaps } from '../common/data' import { EventType } from './event/OB11BaseEvent' import { encodeCQCode } from './cqcode' import { dbUtil } from '../common/db' @@ -34,9 +34,6 @@ import { OB11GroupIncreaseEvent } from './event/notice/OB11GroupIncreaseEvent' import { OB11GroupBanEvent } from './event/notice/OB11GroupBanEvent' import { OB11GroupUploadNoticeEvent } from './event/notice/OB11GroupUploadNoticeEvent' import { OB11GroupNoticeEvent } from './event/notice/OB11GroupNoticeEvent' -import { NTQQUserApi } from '../ntqqapi/api/user' -import { NTQQFileApi } from '../ntqqapi/api/file' -import { NTQQMsgApi } from '../ntqqapi/api/msg' import { calcQQLevel } from '../common/utils/qqlevel' import { log } from '../common/utils/log' import { isNull, sleep } from '../common/utils/helper' @@ -44,7 +41,7 @@ import { getConfigUtil } from '../common/config' import { OB11GroupTitleEvent } from './event/notice/OB11GroupTitleEvent' import { OB11GroupCardEvent } from './event/notice/OB11GroupCardEvent' import { OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent' -import { NTQQGroupApi } from '../ntqqapi/api' +import { NTQQGroupApi, NTQQUserApi, NTQQFileApi, NTQQMsgApi } from '../ntqqapi/api' import { OB11GroupMsgEmojiLikeEvent } from './event/notice/OB11MsgEmojiLikeEvent' import { mFaceCache } from '../ntqqapi/constructor' import { OB11FriendAddNoticeEvent } from './event/notice/OB11FriendAddNoticeEvent' @@ -54,8 +51,6 @@ import { OB11FriendPokeEvent, OB11GroupPokeEvent } from './event/notice/OB11Poke import { OB11BaseNoticeEvent } from './event/notice/OB11BaseNoticeEvent' import { OB11GroupEssenceEvent } from './event/notice/OB11GroupEssenceEvent' -let lastRKeyUpdateTime = 0 - export class OB11Constructor { static async message(msg: RawMessage): Promise { let config = getConfigUtil().getConfig() @@ -99,10 +94,7 @@ export class OB11Constructor { } else if (msg.chatType == ChatType.friend) { resMsg.sub_type = 'friend' - const friend = await getFriend(msg.senderUin!) - if (friend) { - resMsg.sender.nickname = friend.nick - } + resMsg.sender.nickname = (await NTQQUserApi.getUserDetailInfo(msg.senderUid)).nick } else if (msg.chatType == ChatType.temp) { resMsg.sub_type = 'group'