diff --git a/CHANGELOG.MD b/CHANGELOG.MD index d37b298..1150b3f 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -3,6 +3,8 @@ - refactor: 重构websocket的action处理 - feat: 基础信息获取,好友/群/群成员 - feat: at消息解析 +- feat: uid <-> uin +- feat: 群成员信息支持使用QQ号获取 ## v1.1.1 / 2024-02-20 diff --git a/rollup.config.ts b/rollup.config.ts index 1789445..8b3017c 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -70,34 +70,34 @@ const options: RollupOptions[] = [ typescript(), json(), // 压缩 - terser(), - // 混淆 - obfuscator({ - global: true, - }), - { - name: 'jsc', - writeBundle: (options, bundle) => { - console.log('generate jsc...') - if (bundle['core.js']) { - const core = bundle['core.js'] - // console.log(options) - if (core.type === 'chunk' && options.dir) { - const fromPath = path.resolve(options.dir, './core.js') - console.log('compile file:', fromPath) - // 字节码生成 - bytenode.compileFile({ - filename: fromPath, - compileAsModule: true, - electron: true, - compress: true, - electronPath: process.env['PROGRAM_PATH'], - output: `${fromPath}c`, - }) - } - } - } - }, + // terser(), + // // 混淆 + // obfuscator({ + // global: true, + // }), + // { + // name: 'jsc', + // writeBundle: (options, bundle) => { + // console.log('generate jsc...') + // if (bundle['core.js']) { + // const core = bundle['core.js'] + // // console.log(options) + // if (core.type === 'chunk' && options.dir) { + // const fromPath = path.resolve(options.dir, './core.js') + // console.log('compile file:', fromPath) + // // 字节码生成 + // bytenode.compileFile({ + // filename: fromPath, + // compileAsModule: true, + // electron: true, + // compress: true, + // electronPath: process.env['PROGRAM_PATH'], + // output: `${fromPath}c`, + // }) + // } + // } + // } + // }, ], // 指出哪些模块应该视为外部模块 external: ['electron', 'module', 'ntwrapper', 'telecord-native'], diff --git a/src/ntqq/types/wrapper.d.ts b/src/ntqq/types/wrapper.d.ts index 655ceaf..443589c 100644 --- a/src/ntqq/types/wrapper.d.ts +++ b/src/ntqq/types/wrapper.d.ts @@ -768,6 +768,28 @@ declare namespace NTNativeWrapper { constructor(options: NodeIKernelSessionListenerConstructorOptions) } + // #region UixConvertService + class NodeIKernelUixConvertService extends NTBaseClass { + /** + * 根据QQ号获取用户id + * + * 已测试 + * @param uin QQ号 + */ + getUid(uin: `${number}`[]): Promise + /** + * 根据用户id获取QQ号 + * + * 未测试 + * @param uin QQ号 + */ + getUin(uid: `u_${string}`[]): Promise> + } + interface UidInfo { + uidInfo: Map<`${number}`, `u_${string}`> + } + // #endregion + interface NodeIKernelUnitedConfigListenerConstructorOptions { onUnitedConfigUpdate: () => void } @@ -835,6 +857,7 @@ declare namespace NTNativeWrapper { getSettingService(): NodeIKernelSettingService getSkinService(): NodeIKernelSkinService getStorageCleanService(): NodeIKernelStorageCleanService + getUixConvertService(): NodeIKernelUixConvertService getUnitedConfigService(): NodeIKernelUnitedConfigService offLine(info: NodeIQQNTWrapperSessionType.OfflineReq): Promise } diff --git a/src/onebot/actions/friend/interfaces.d.ts b/src/onebot/actions/friend/interfaces.d.ts index 053fbb4..250cbfb 100644 --- a/src/onebot/actions/friend/interfaces.d.ts +++ b/src/onebot/actions/friend/interfaces.d.ts @@ -64,6 +64,7 @@ export interface GroupInfoResp { */ export interface GroupMemberInfoReq extends BotActionParams { group_id: number + user_uin: number user_uid: `u_${string}` } diff --git a/src/onebot/actions/group/member.ts b/src/onebot/actions/group/member.ts index 1ce6eb6..d5b3078 100644 --- a/src/onebot/actions/group/member.ts +++ b/src/onebot/actions/group/member.ts @@ -1,6 +1,8 @@ import { useLogger } from "../../../common/log" +import { CustomError } from "../../../server/error/custom-error" import { useStore } from "../../../store/store" -import { getGroupMemberInfoById } from "../../common/group" +import { getGroupMemberInfoByUid, getGroupMemberInfoByUin } from "../../common/group" +import { GroupMemberDetailInfoType } from "../../common/interfaces" import { getUserInfoByUid } from "../../common/user" import { GroupMemberInfoReq, GroupMemberInfoResp, UserInfoReq, UserInfoResp } from "../friend/interfaces" @@ -18,7 +20,21 @@ const getGroupMemberInfo = async (p: GroupMemberInfoReq): Promise => { /** * - * @param gid NodeIKernelGroupService[undefined]/getMemberInfo/eca95e2a-f434-436e-a8da-cf2fcbb3bcbf -arguments: 933286835 [ 'u_EbxBsO-JLi3oxEYabJ0umg' ] true -JSON arguments: ["933286835",["u_EbxBsO-JLi3oxEYabJ0umg"],true] + * @param gid 群号 + * @param uid 用户id * @returns */ -export const getGroupMemberInfoById = (gid: number, uid: `u_${string}`): Promise => { +export const getGroupMemberInfoByUin = async (gid: number, uin: number): Promise => { + log.info('getGroupMemberInfoByUin', gid, uin) + const { getWrapperSession } = useNTCore() + const session = getWrapperSession() + const convert = session.getUixConvertService() + const info = await convert.getUid([`${uin}`]) + log.info('get uid:', info) + const uid = info?.uidInfo?.get(`${uin}`) + if (!uid) { + throw new CustomError(1, 'Failed to get uid by uin!') + } + return await getGroupMemberInfoByUid(gid, uid) +} +/** + * + * @param gid 群号 + * @param uid 用户id + * @returns + */ +export const getGroupMemberInfoByUid = (gid: number, uid: `u_${string}`): Promise => { + log.info('getGroupMemberInfoByUid', gid, uid) return new Promise(async (resolve, reject) => { let remover: { remove: () => void } | null = null // 超时拒绝 let time = setTimeout(() => { if (remover) remover?.remove() - reject('getGroupMemberInfoById timeout') + reject('getGroupMemberInfoByUid timeout') }, 30000) remover = registerEventListener(`KernelGroupListener/onMemberInfoChange`, 'always', (groupId: `${number}`, b: number, payload: Map<`u_${string}`, GroupMemberDetailInfoType>) => { if (groupId !== `${gid}`) return @@ -57,7 +76,8 @@ export const getGroupMemberInfoById = (gid: number, uid: `u_${string}`): Promise clearTimeout(time) const result = payload.get(uid) if (!result) { - throw new CustomError(1, 'failed to get member info!') + log.error('info:', result, 'payload:', payload) + throw new CustomError(1, 'Failed to get member info!') } resolve(result) }) @@ -65,6 +85,6 @@ export const getGroupMemberInfoById = (gid: number, uid: `u_${string}`): Promise const session = getWrapperSession() const service = session.getGroupService() const result = await service.getMemberInfo(`${gid}`, [uid], true) - log.info(`getGroupMemberInfoById[${gid}]:`, result) + log.info(`getGroupMemberInfoByUid[${gid}]:`, result) }) } diff --git a/src/onebot/common/message.d.ts b/src/onebot/common/message.d.ts index f767212..91eb792 100644 --- a/src/onebot/common/message.d.ts +++ b/src/onebot/common/message.d.ts @@ -396,6 +396,10 @@ declare namespace BotMessageReceiveElements { * */ uid: `u_${string}` | 'all' + /** + * QQ号 + */ + uin: number name?: string } diff --git a/src/onebot/event/message.ts b/src/onebot/event/message.ts index ded0c95..dca974a 100644 --- a/src/onebot/event/message.ts +++ b/src/onebot/event/message.ts @@ -5,6 +5,7 @@ import { useStore } from "../../store/store" import { getBotAccount, getUserInfoByUid } from "../common/user" import { EventDataType, MessageData, RecallMessageData } from "./interfaces" import { useLogger } from "../../common/log" +import { getGroupMemberInfoByUid } from "../common/group" const { registerEventListener } = useStore() const { sendMessage } = useServer() @@ -66,6 +67,15 @@ const onRecvMsg = () => { break } ret.data.elements = convertNTMessage2BotMessage(msg.elements) + for (const ele of ret.data.elements) { + if (ele.type === 'mention') { + if(false === ele.data.at?.isAll) { + // at特定成员,获取QQ号 + const info = await getGroupMemberInfoByUid(ret.data.group_id, ele.data.at.uid as `u_${string}`) + ele.data.at.uin = parseInt(info.uin) + } + } + } ret.data.records = msg.records.map(e => ({ message_id: e.msgId, message_seq: e.msgSeq, diff --git a/src/transfer/message/convert.ts b/src/transfer/message/convert.ts index 30fe4e4..7d6fe4f 100644 --- a/src/transfer/message/convert.ts +++ b/src/transfer/message/convert.ts @@ -8,6 +8,7 @@ import { getRichMediaFilePathForGuild } from "../../ntqq/common/nt-api"; import { copyFile, getFileType } from "../../ntqq/common/fs-api"; import { useNTCore } from "../../ntqq/core/core"; import { useStore } from "../../store/store"; +import { getGroupMemberInfoByUid } from "../../onebot/common/group"; const log = useLogger('Convert') @@ -34,6 +35,7 @@ export const convertNTMessage2BotMessage = (elems: NTReceiveMessageType.NTMessag at: { isAll: false, uid: cur.atNtUid as `u_${string}`, + uin: parseInt(cur.atTinyId), name: cur.content, } } @@ -48,6 +50,7 @@ export const convertNTMessage2BotMessage = (elems: NTReceiveMessageType.NTMessag at: { isAll: true, uid: 'all', + uin: 0, name: cur.content, } } diff --git a/tools/dev.cjs b/tools/dev.cjs index 198da7d..f82e6e2 100644 --- a/tools/dev.cjs +++ b/tools/dev.cjs @@ -147,6 +147,7 @@ const ActionHandle = { ...process.env, YUKIHANA_LOG: true, ELECTRON_RUN_AS_NODE: true, + YUKIHANA_ACTION: 'dev', YUKIHANA_NATIVE: "D:/GitHub/Telecord-native/build/nt_native.node", } }) @@ -161,6 +162,7 @@ const ActionHandle = { ...process.env, YUKIHANA_LOG: true, ELECTRON_RUN_AS_NODE: true, + YUKIHANA_ACTION: 'dev', YUKIHANA_NATIVE: "/home/msojocs/github/nt-native/build/nt_native.node", } })