From fccb0852aa0d9ee813034dc631f7b86e13f3d2f3 Mon Sep 17 00:00:00 2001 From: linyuchen <lin.yu.chen@foxmail.com> Date: Fri, 15 Mar 2024 18:54:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=B8=BB=E5=8A=A8?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E8=A2=AB=E8=BF=87=E6=BB=A4=E7=9A=84=E5=8A=A0?= =?UTF-8?q?=E7=BE=A4=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manifest.json | 4 +- src/common/data.ts | 18 +++---- src/common/utils.ts | 8 ++- src/main/main.ts | 6 +-- src/ntqqapi/ntcall.ts | 49 +++++++++++++++---- src/ntqqapi/types.ts | 8 ++- src/onebot11/action/index.ts | 2 + .../action/llonebot/GetGroupAddRequest.ts | 32 ++++++++++++ src/onebot11/action/types.ts | 1 + src/version.ts | 2 +- 10 files changed, 102 insertions(+), 28 deletions(-) create mode 100644 src/onebot11/action/llonebot/GetGroupAddRequest.ts diff --git a/manifest.json b/manifest.json index 69d0f1b..a0b3932 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ { "manifest_version": 4, "type": "extension", - "name": "LLOneBot v3.14.1", + "name": "LLOneBot v3.15.0", "slug": "LLOneBot", "description": "LiteLoaderQQNT的OneBotApi,不支持商店在线更新", - "version": "3.14.1", + "version": "3.15.0", "icon": "./icon.jpg", "authors": [ { diff --git a/src/common/data.ts b/src/common/data.ts index 30f1b53..b47d7c9 100644 --- a/src/common/data.ts +++ b/src/common/data.ts @@ -11,7 +11,7 @@ import { import {type FileCache, type LLOneBotError} from './types' import {dbUtil} from "./db"; import {raw} from "express"; -import {log} from "./utils"; +import {isNumeric, log} from "./utils"; export const selfInfo: SelfInfo = { uid: '', @@ -28,9 +28,9 @@ export const llonebotError: LLOneBotError = { } -export async function getFriend(qq: string, uid: string = ""): Promise<Friend | undefined> { - let filterKey = uid ? "uid" : "uin" - let filterValue = uid ? uid : qq +export async function getFriend(uinOrUid: string): Promise<Friend | undefined> { + let filterKey = isNumeric(uinOrUid) ? "uin" : "uid" + let filterValue = uinOrUid let friend = friends.find(friend => friend[filterKey] === filterValue.toString()) // if (!friend) { // try { @@ -59,15 +59,13 @@ export async function getGroup(qq: string): Promise<Group | undefined> { return group } -export async function getGroupMember(groupQQ: string | number, memberQQ: string | number, memberUid: string = null) { +export async function getGroupMember(groupQQ: string | number, memberUinOrUid: string | number) { groupQQ = groupQQ.toString() - if (memberQQ) { - memberQQ = memberQQ.toString() - } + memberUinOrUid = memberUinOrUid.toString() const group = await getGroup(groupQQ) if (group) { - const filterKey = memberQQ ? "uin" : "uid" - const filterValue = memberQQ ? memberQQ : memberUid + 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) { diff --git a/src/common/utils.ts b/src/common/utils.ts index 81a126d..c6904ab 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -32,6 +32,11 @@ function truncateString(obj: any, maxLength = 500) { return obj; } +export function isNumeric(str: string) { + return /^\d+$/.test(str); +} + + export function log(...msg: any[]) { if (!getConfigUtil().getConfig().log) { return //console.log(...msg); @@ -225,8 +230,7 @@ export async function encodeSilk(filePath: string) { const pcm = fs.readFileSync(filePath); const silk = await encode(pcm, 0); fs.writeFileSync(pttPath, silk.data); - // fs.unlink(wavPath, (err) => { - // }); + fs.unlink(wavPath, (err) => { }); log(`语音文件${filePath}转换成功!`, pttPath) return { converted: true, diff --git a/src/main/main.ts b/src/main/main.ts index c6a1a89..fc769da 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -148,7 +148,7 @@ function onLoad() { let operatorId = message.senderUin for (const element of message.elements) { const operatorUid = element.grayTipElement?.revokeElement.operatorUid - const operator = await getGroupMember(message.peerUin, null, operatorUid) + const operator = await getGroupMember(message.peerUin, operatorUid) operatorId = operator.uin } const groupRecallEvent = new OB11GroupRecallNoticeEvent( @@ -215,7 +215,7 @@ function onLoad() { // member2 = await getGroupMember(notify.group.groupCode, null, notify.user2.uid); // } if ([GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET].includes(notify.type)) { - const member1 = await getGroupMember(notify.group.groupCode, null, notify.user1.uid); + const member1 = await getGroupMember(notify.group.groupCode, notify.user1.uid); log("有管理员变动通知"); refreshGroupMembers(notify.group.groupCode).then() let groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent() @@ -253,7 +253,7 @@ function onLoad() { log("收到邀请我加群通知") let groupInviteEvent = new OB11GroupRequestEvent(); groupInviteEvent.group_id = parseInt(notify.group.groupCode); - let user_id = (await getFriend("", notify.user2.uid))?.uin + let user_id = (await getFriend(notify.user2.uid))?.uin if (!user_id) { user_id = (await NTQQApi.getUserDetailInfo(notify.user2.uid))?.uin } diff --git a/src/ntqqapi/ntcall.ts b/src/ntqqapi/ntcall.ts index 872de10..89e99d7 100644 --- a/src/ntqqapi/ntcall.ts +++ b/src/ntqqapi/ntcall.ts @@ -1,4 +1,4 @@ -import {ipcMain} from "electron"; +import {BrowserWindow, ipcMain} from "electron"; import {hookApiCallbacks, ReceiveCmd, registerReceiveHook, removeReceiveHook} from "./hook"; import {log, sleep} from "../common/utils"; import { @@ -42,6 +42,7 @@ export enum NTQQApiClass { NT_API = "ns-ntApi", FS_API = "ns-FsApi", OS_API = "ns-OsApi", + WINDOW_API = "ns-WindowApi", HOTUPDATE_API = "ns-HotUpdateApi", BUSINESS_API = "ns-BusinessApi", GLOBAL_DATA = "ns-GlobalDataApi" @@ -93,6 +94,8 @@ export enum NTQQApiMethod { CACHE_CHAT_GET = 'nodeIKernelStorageCleanService/getChatCacheInfo', CACHE_FILE_GET = 'nodeIKernelStorageCleanService/getFileCacheInfo', CACHE_CHAT_CLEAR = 'nodeIKernelStorageCleanService/clearChatCacheInfo', + + OPEN_EXTRA_WINDOW = 'openExternalWindow', } enum NTQQApiChannel { @@ -203,12 +206,13 @@ interface GeneralCallResult { export class NTQQApi { - static async setHeader(path: string){ + static async setHeader(path: string) { return await callNTQQApi<GeneralCallResult>({ methodName: NTQQApiMethod.SET_HEADER, args: [path] }) } + static async likeFriend(uid: string, count = 1) { return await callNTQQApi<GeneralCallResult>({ methodName: NTQQApiMethod.LIKE_FRIEND, @@ -256,7 +260,11 @@ export class NTQQApi { null ] }) - return result.info + const info = result.info + if (info?.uin) { + uidMaps[info.uid] = info.uin + } + return info } static async getFriends(forced = false) { @@ -482,8 +490,7 @@ export class NTQQApi { if ((await dbUtil.getMsgByLongId(sentMessage.msgId)).sendStatus == 2) { return sentMessage } - } - else{ + } else { return sentMessage } // log(`给${peerUid}发送消息成功`) @@ -510,7 +517,7 @@ export class NTQQApi { static async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) { return await callNTQQApi<GeneralCallResult>({ methodName: NTQQApiMethod.FORWARD_MSG, - args:[ + args: [ { msgIds: msgIds, srcContact: srcPeer, @@ -525,6 +532,7 @@ export class NTQQApi { }) } + static async multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) { const msgInfos = msgIds.map(id => { return {msgId: id, senderShowName: selfInfo.nick} @@ -596,6 +604,29 @@ export class NTQQApi { }); } + static async getGroupIgnoreNotifies() { + await NTQQApi.getGroupNotifies(); + const result = callNTQQApi<GroupNotifies>({ + className: NTQQApiClass.WINDOW_API, + methodName: NTQQApiMethod.OPEN_EXTRA_WINDOW, + cbCmd: ReceiveCmd.GROUP_NOTIFY, + afterFirstCmd: false, + args: [ + "GroupNotifyFilterWindow" + ] + }) + // 关闭窗口 + setTimeout(() => { + for (const w of BrowserWindow.getAllWindows()) { + // log("close window", w.webContents.getURL()) + if (w.webContents.getURL().indexOf("#/notify-filter/") != -1) { + w.close(); + } + } + }, 2000); + return result; + } + static async handleGroupRequest(seq: string, operateType: GroupRequestOperateTypes, reason?: string) { const notify: GroupNotify = await dbUtil.getGroupNotify(seq) if (!notify) { @@ -815,7 +846,7 @@ export class NTQQApi { }); } - static clearCache(cacheKeys: Array<string> = [ 'tmp', 'hotUpdate' ]) { + static clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) { return callNTQQApi<any>({ // TODO: 目前还不知道真正的返回值是什么 methodName: NTQQApiMethod.CACHE_CLEAR, args: [{ @@ -835,12 +866,12 @@ export class NTQQApi { pageIndex }, null] }).then(list => res(list)) - .catch(e => rej(e)); + .catch(e => rej(e)); }); } static getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) { - const _lastRecord = lastRecord ? lastRecord : { fileType: fileType }; + const _lastRecord = lastRecord ? lastRecord : {fileType: fileType}; return callNTQQApi<CacheFileList>({ methodName: NTQQApiMethod.CACHE_FILE_GET, diff --git a/src/ntqqapi/types.ts b/src/ntqqapi/types.ts index 6b5e46f..743b6df 100644 --- a/src/ntqqapi/types.ts +++ b/src/ntqqapi/types.ts @@ -392,11 +392,17 @@ export interface GroupNotifies { notifies: GroupNotify[], } +export enum GroupNotifyStatus { + IGNORE = 0, + WAIT_HANDLE = 1, + APPROVE = 2, + REJECT = 3 +} export interface GroupNotify { time: number; // 自己添加的字段,时间戳,毫秒, 用于判断收到短时间内收到重复的notify seq: string, // 唯一标识符,转成数字再除以1000应该就是时间戳? type: GroupNotifyTypes, - status: 0, // 未知 + status: GroupNotifyStatus, // 0是已忽略?,1是未处理,2是已同意 group: { groupCode: string, groupName: string }, user1: { uid: string, nickName: string }, // 被设置管理员的人 user2: { uid: string, nickName: string }, // 操作者 diff --git a/src/onebot11/action/index.ts b/src/onebot11/action/index.ts index 6740960..b01359b 100644 --- a/src/onebot11/action/index.ts +++ b/src/onebot11/action/index.ts @@ -34,11 +34,13 @@ import GoCQHTTPMarkMsgAsRead from "./MarkMsgAsRead"; import CleanCache from "./CleanCache"; import GoCQHTTPUploadGroupFile from "./go-cqhttp/UploadGroupFile"; import {GetConfigAction, SetConfigAction} from "./llonebot/Config"; +import GetGroupAddRequest from "./llonebot/GetGroupAddRequest"; export const actionHandlers = [ new Debug(), new GetConfigAction(), new SetConfigAction(), + new GetGroupAddRequest(), // onebot11 new SendLike(), new GetMsg(), diff --git a/src/onebot11/action/llonebot/GetGroupAddRequest.ts b/src/onebot11/action/llonebot/GetGroupAddRequest.ts new file mode 100644 index 0000000..059c289 --- /dev/null +++ b/src/onebot11/action/llonebot/GetGroupAddRequest.ts @@ -0,0 +1,32 @@ +import {GroupNotify, GroupNotifyStatus} from "../../../ntqqapi/types"; +import BaseAction from "../BaseAction"; +import {ActionName} from "../types"; +import {NTQQApi} from "../../../ntqqapi/ntcall"; +import {uidMaps} from "../../../common/data"; +import {log} from "../../../common/utils"; + +interface OB11GroupRequestNotify { + group_id: number, + user_id: number, + flag: string +} + +export default class GetGroupAddRequest extends BaseAction<null, OB11GroupRequestNotify[]> { + actionName = ActionName.GetGroupIgnoreAddRequest + + protected async _handle(payload: null): Promise<OB11GroupRequestNotify[]> { + const data = await NTQQApi.getGroupIgnoreNotifies() + log(data); + let notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE); + let returnData: OB11GroupRequestNotify[] = [] + for (const notify of notifies) { + const uin = uidMaps[notify.user1.uid] || (await NTQQApi.getUserDetailInfo(notify.user1.uid))?.uin + returnData.push({ + group_id: parseInt(notify.group.groupCode), + user_id: parseInt(uin), + flag: notify.seq + }) + } + return returnData; + } +} \ No newline at end of file diff --git a/src/onebot11/action/types.ts b/src/onebot11/action/types.ts index e170890..112b0c2 100644 --- a/src/onebot11/action/types.ts +++ b/src/onebot11/action/types.ts @@ -14,6 +14,7 @@ export interface InvalidCheckResult { } export enum ActionName { + GetGroupIgnoreAddRequest = "get_group_ignore_add_request", GetConfig = "get_config", SetConfig = "set_config", Debug = "llonebot_debug", diff --git a/src/version.ts b/src/version.ts index 943ebf4..b9f51bb 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const version = "3.14.1" \ No newline at end of file +export const version = "3.15.0" \ No newline at end of file