From 1936671cb3158eba5a8f886ce95c962596a30f45 Mon Sep 17 00:00:00 2001 From: linyuchen Date: Tue, 13 Feb 2024 18:37:01 +0800 Subject: [PATCH] fix: self nickname fix: @member msg report fix: send file:// on Windows ver: 3.0.2 --- manifest.json | 2 +- src/common/data.ts | 15 ++++-- src/main/main.ts | 27 ++--------- src/ntqqapi/hook.ts | 86 ++++++++++++++++++--------------- src/ntqqapi/ntcall.ts | 5 +- src/onebot11/actions/SendMsg.ts | 27 ++++++----- src/onebot11/constructor.ts | 25 +++++----- src/onebot11/utils.ts | 60 +++++++++++------------ 8 files changed, 122 insertions(+), 125 deletions(-) diff --git a/manifest.json b/manifest.json index 6425ca0..1334a45 100644 --- a/manifest.json +++ b/manifest.json @@ -4,7 +4,7 @@ "name": "LLOneBot", "slug": "LLOneBot", "description": "LiteLoaderQQNT的OneBotApi", - "version": "3.0.1", + "version": "3.0.2", "thumbnail": "./icon.png", "authors": [{ "name": "linyuchen", diff --git a/src/common/data.ts b/src/common/data.ts index 50e50ee..57a9d8a 100644 --- a/src/common/data.ts +++ b/src/common/data.ts @@ -1,5 +1,5 @@ import { NTQQApi } from '../ntqqapi/ntcall'; -import { Friend, Group, RawMessage, SelfInfo } from "../ntqqapi/types"; +import { Friend, Group, GroupMember, RawMessage, SelfInfo } from "../ntqqapi/types"; export let groups: Group[] = [] export let friends: Friend[] = [] @@ -23,16 +23,23 @@ export async function getGroup(qq: string): Promise { return group } -export async function getGroupMember(groupQQ: string, memberQQ: string) { +export async function getGroupMember(groupQQ: string, memberQQ: string=null, memberUid: string=null) { const group = await getGroup(groupQQ) if (group) { - let member = group.members?.find(member => member.uin === memberQQ) + let filterFunc: (member: GroupMember) => boolean + if (memberQQ){ + filterFunc = member => member.uin === memberQQ + } + else if (memberUid){ + filterFunc = member => member.uid === memberUid + } + let member = group.members?.find(filterFunc) if (!member){ const _members = await NTQQApi.getGroupMembers(groupQQ) if (_members.length){ group.members = _members } - member = group.members?.find(member => member.uin === memberQQ) + member = group.members?.find(filterFunc) } return member } diff --git a/src/main/main.ts b/src/main/main.ts index 51a5ac5..d055e69 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -83,6 +83,7 @@ function onLoad() { log("report self message error: ", e.toString()) } }) + NTQQApi.getGroups(true).then() startExpress(getConfigUtil().getConfig().port) } @@ -99,6 +100,7 @@ function onLoad() { if (selfInfo.uin) { try { const userInfo = (await NTQQApi.getUserInfo(selfInfo.uid)) + log("self info", userInfo); if (userInfo) { selfInfo.nick = userInfo.nick } else { @@ -108,30 +110,11 @@ function onLoad() { } } catch (e) { log("get self nickname failed", e.toString()) + return setTimeout(() => { + getSelfInfo().then() + }, 100) } start(); - // try { - // friends.push(...(await NTQQApi.getFriends(true))) - // log("get friends", friends) - // let _groups: Group[] = [] - // for(let i=0; i++; i<3){ - // try{ - // _groups = await NTQQApi.getGroups(true) - // log("get groups sucess", _groups) - // break - // } catch(e) { - // log("get groups failed", e) - // } - // } - // for (let g of _groups) { - // g.members = (await NTQQApi.getGroupMembers(g.groupCode)) - // log("group members", g.members) - // groups.push(g) - // } - - // } catch (e) { - // log("!!!初始化失败", e.stack.toString()) - // } } else { setTimeout(() => { getSelfInfo().then() diff --git a/src/ntqqapi/hook.ts b/src/ntqqapi/hook.ts index 2dc0976..c458508 100644 --- a/src/ntqqapi/hook.ts +++ b/src/ntqqapi/hook.ts @@ -1,24 +1,24 @@ -import {BrowserWindow} from 'electron'; -import {getConfigUtil, log} from "../common/utils"; -import {NTQQApi, NTQQApiClass, sendMessagePool} from "./ntcall"; +import { BrowserWindow } from 'electron'; +import { getConfigUtil, log } from "../common/utils"; +import { NTQQApi, NTQQApiClass, sendMessagePool } from "./ntcall"; import { Group, User } from "./types"; import { RawMessage } from "./types"; -import {friends, groups, msgHistory} from "../common/data"; +import { friends, groups, msgHistory } from "../common/data"; import { v4 as uuidv4 } from 'uuid'; -export let hookApiCallbacks: Recordvoid>={} +export let hookApiCallbacks: Record void> = {} export enum ReceiveCmd { UPDATE_MSG = "nodeIKernelMsgListener/onMsgInfoListUpdate", NEW_MSG = "nodeIKernelMsgListener/onRecvMsg", SELF_SEND_MSG = "nodeIKernelMsgListener/onAddSendMsg", - USER_INFO = "nodeIKernelProfileListener/onProfileDetailInfoChanged", + USER_INFO = "nodeIKernelProfileListener/onProfileSimpleChanged", GROUPS = "nodeIKernelGroupListener/onGroupListUpdate", GROUPS_UNIX = "onGroupListUpdate", FRIENDS = "onBuddyListChange" } -interface NTQQApiReturnData extends Array { +interface NTQQApiReturnData extends Array { 0: { "type": "request", "eventName": NTQQApiClass, @@ -51,7 +51,7 @@ export function hookNTQQApiReceive(window: BrowserWindow) { new Promise((resolve, reject) => { try { hook.hookFunc(receiveData.payload); - }catch (e) { + } catch (e) { log("hook error", e, receiveData.payload) } }).then() @@ -59,10 +59,10 @@ export function hookNTQQApiReceive(window: BrowserWindow) { } } } - if (args[0]?.callbackId){ + if (args[0]?.callbackId) { // log("hookApiCallback", hookApiCallbacks, args) const callbackId = args[0].callbackId; - if (hookApiCallbacks[callbackId]){ + if (hookApiCallbacks[callbackId]) { // log("callback found") new Promise((resolve, reject) => { hookApiCallbacks[callbackId](args[1]); @@ -85,36 +85,43 @@ export function registerReceiveHook(method: ReceiveCmd, hookFunc: ( return id; } -export function removeReceiveHook(id: string){ - const index = receiveHooks.findIndex(h=>h.id === id) +export function removeReceiveHook(id: string) { + const index = receiveHooks.findIndex(h => h.id === id) receiveHooks.splice(index, 1); } -async function updateGroups(_groups: Group[]){ - for(let group of _groups){ - let existGroup = groups.find(g=>g.groupCode == group.groupCode) - if (!existGroup){ - // log("update group") - let _membeers = await NTQQApi.getGroupMembers(group.groupCode) - if (_membeers){ - group.members = _membeers - } +async function updateGroups(_groups: Group[]) { + for (let group of _groups) { + let existGroup = groups.find(g => g.groupCode == group.groupCode) + if (!existGroup) { + NTQQApi.getGroupMembers(group.groupCode).then(members => { + if (members) { + group.members = members + } + }) + groups.push(group) log("update group members", group.members) - } - else{ - group.members = [...existGroup.members] + } else { + Object.assign(existGroup, group) } } - groups.length = 0; - groups.push(..._groups) } -registerReceiveHook<{groupList: Group[]}>(ReceiveCmd.GROUPS, (payload)=>updateGroups(payload.groupList).then()) -registerReceiveHook<{groupList: Group[]}>(ReceiveCmd.GROUPS_UNIX, (payload)=>updateGroups(payload.groupList).then()) -registerReceiveHook<{data:{categoryId: number, categroyName: string, categroyMbCount: number, buddyList: User[]}[]}>(ReceiveCmd.FRIENDS, payload=>{ - friends.length = 0 +registerReceiveHook<{ groupList: Group[] }>(ReceiveCmd.GROUPS, (payload) => updateGroups(payload.groupList).then()) +registerReceiveHook<{ groupList: Group[] }>(ReceiveCmd.GROUPS_UNIX, (payload) => updateGroups(payload.groupList).then()) +registerReceiveHook<{ + data: { categoryId: number, categroyName: string, categroyMbCount: number, buddyList: User[] }[] +}>(ReceiveCmd.FRIENDS, payload => { for (const fData of payload.data) { - friends.push(...fData.buddyList) + const _friends = fData.buddyList; + for (let friend of _friends) { + let existFriend = friends.find(f => f.uin == friend.uin) + if (!existFriend) { + friends.push(friend) + } else { + Object.assign(existFriend, friend) + } + } } }) @@ -131,24 +138,27 @@ registerReceiveHook<{ msgList: Array }>(ReceiveCmd.UPDATE_MSG, (payl registerReceiveHook<{ msgList: Array }>(ReceiveCmd.NEW_MSG, (payload) => { for (const message of payload.msgList) { log("收到新消息,push到历史记录", message) - if (!msgHistory[message.msgId]){ + if (!msgHistory[message.msgId]) { msgHistory[message.msgId] = message - } - else{ + } else { Object.assign(msgHistory[message.msgId], message) } } + const msgIds = Object.keys(msgHistory); + if (msgIds.length > 3000) { + delete msgHistory[msgIds.sort()[0]] + } }) -registerReceiveHook<{msgRecord: RawMessage}>(ReceiveCmd.SELF_SEND_MSG, ({msgRecord})=>{ +registerReceiveHook<{ msgRecord: RawMessage }>(ReceiveCmd.SELF_SEND_MSG, ({msgRecord}) => { const message = msgRecord; const peerUid = message.peerUid; // log("收到自己发送成功的消息", Object.keys(sendMessagePool), message); const sendCallback = sendMessagePool[peerUid]; - if (sendCallback){ - try{ + if (sendCallback) { + try { sendCallback(message); - }catch(e){ + } catch (e) { log("receive self msg error", e.stack) } } diff --git a/src/ntqqapi/ntcall.ts b/src/ntqqapi/ntcall.ts index b5171ed..b87eb33 100644 --- a/src/ntqqapi/ntcall.ts +++ b/src/ntqqapi/ntcall.ts @@ -142,10 +142,9 @@ export class NTQQApi { } static async getUserInfo(uid: string) { - const result = await callNTQQApi<{ info: User }>(NTQQApiChannel.IPC_UP_2, NTQQApiClass.NT_API, NTQQApiMethod.USER_INFO, + const result = await callNTQQApi<{ profiles: Map }>(NTQQApiChannel.IPC_UP_2, NTQQApiClass.NT_API, NTQQApiMethod.USER_INFO, [{ force: true, uids: [uid] }, undefined], ReceiveCmd.USER_INFO) - return result.info - + return result.profiles.get(uid) } static async getFriends(forced = false) { diff --git a/src/onebot11/actions/SendMsg.ts b/src/onebot11/actions/SendMsg.ts index 48c2c1b..edcd143 100644 --- a/src/onebot11/actions/SendMsg.ts +++ b/src/onebot11/actions/SendMsg.ts @@ -10,6 +10,7 @@ import { v4 as uuid4 } from 'uuid'; import { log } from "../../common/utils"; import BaseAction from "./BaseAction"; import { ActionName } from "./types"; +import * as fs from "fs"; export interface ReturnDataType { message_id: string @@ -23,6 +24,7 @@ class SendMsg extends BaseAction { chatType: ChatType.friend, peerUid: "" } + let deleteAfterSentFiles: string[] = [] let group: Group | undefined = undefined; if (payload?.group_id) { group = await getGroup(payload.group_id.toString()) @@ -94,21 +96,21 @@ class SendMsg extends BaseAction { } } } break; - case OB11MessageDataType.image: { - const file = sendMsg.data?.file - if (file) { - const picPath = await (await uri2local(uuid4(), file)).path - if (picPath) { - sendElements.push(await SendMsgElementConstructor.pic(picPath)) - } - } - } break; + case OB11MessageDataType.image: case OB11MessageDataType.voice: { const file = sendMsg.data?.file if (file) { - const voicePath = await (await uri2local(uuid4(), file)).path - if (voicePath) { - sendElements.push(await SendMsgElementConstructor.ptt(voicePath)) + const {path, isLocal} = (await uri2local(uuid4(), file)) + if (path) { + if (!isLocal){ // 只删除http和base64转过来的文件 + deleteAfterSentFiles.push(path) + } + if (sendMsg.type === OB11MessageDataType.image){ + sendElements.push(await SendMsgElementConstructor.pic(path)) + } + else { + sendElements.push(await SendMsgElementConstructor.ptt(path)) + } } } } @@ -117,6 +119,7 @@ class SendMsg extends BaseAction { // log("send msg:", peer, sendElements) try { const returnMsg = await NTQQApi.sendMsg(peer, sendElements) + deleteAfterSentFiles.map(f=>fs.unlink(f, ()=>{})) return { message_id: returnMsg.msgId } } catch (e) { throw(e.toString()) diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index 3ac603e..56fe5c2 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -54,10 +54,18 @@ export class OB11Constructor { message_data["data"]["mention"] = "all" message_data["data"]["qq"] = "all" } else { + let atUid = element.textElement.atNtUid let atQQ = element.textElement.atUid - // let atMember = await getGroupMember(msg.peerUin, uid) - message_data["data"]["mention"] = atQQ - message_data["data"]["qq"] = atQQ + if (!atQQ || atQQ === "0"){ + const atMember = await getGroupMember(msg.peerUin, null, atUid) + if (atMember){ + atQQ = atMember.uin + } + } + if (atQQ){ + message_data["data"]["mention"] = atQQ + message_data["data"]["qq"] = atQQ + } } } else if (element.textElement) { message_data["type"] = "text" @@ -103,7 +111,6 @@ export class OB11Constructor { let filePath: string = message_data.data.file; message_data.data.file = "file://" + filePath if (enableBase64) { - // filePath = filePath.replace("\\Ori\\", "\\Thumb\\") let {err, data} = await file2base64(filePath); if (err) { console.log("文件转base64失败", err) @@ -116,16 +123,6 @@ export class OB11Constructor { resMsg.message.push(message_data); } } - // if (msgHistory.length > 10000) { - // msgHistory.splice(0, 100) - // } - // msgHistory.push(message) - // if (!reportSelfMessage && onebot_message_data["user_id"] == self_qq) { - // console.log("开启了不上传自己发送的消息,进行拦截 ", onebot_message_data); - // } else { - // console.log("发送上传消息给ipc main", onebot_message_data); - // window.llonebot.postData(onebot_message_data); - // } return resMsg; } diff --git a/src/onebot11/utils.ts b/src/onebot11/utils.ts index 67d5931..cf5b7c8 100644 --- a/src/onebot11/utils.ts +++ b/src/onebot11/utils.ts @@ -6,6 +6,12 @@ const fs = require("fs").promises; export async function uri2local(fileName: string, uri: string){ let filePath = path.join(CONFIG_DIR, fileName) let url = new URL(uri); + let res = { + success: false, + errMsg: "", + path: "", + isLocal: false + } if (url.protocol == "base64:") { // base64转成文件 let base64Data = uri.split("base64://")[1] @@ -13,51 +19,43 @@ export async function uri2local(fileName: string, uri: string){ const buffer = Buffer.from(base64Data, 'base64'); await fs.writeFile(filePath, buffer); } catch (e: any) { - return { - success: false, - errMsg: `base64文件下载失败,` + e.toString(), - path: "" - } + res.errMsg = `base64文件下载失败,` + e.toString() + return res } } else if (url.protocol == "http:" || url.protocol == "https:") { // 下载文件 - let res = await fetch(url) - if (!res.ok) { - return { - success: false, - errMsg: `${url}下载失败,` + res.statusText, - path: "" - } + let fetchRes = await fetch(url) + if (!fetchRes.ok) { + res.errMsg = `${url}下载失败,` + fetchRes.statusText + return res } - let blob = await res.blob(); + let blob = await fetchRes.blob(); let buffer = await blob.arrayBuffer(); try { await fs.writeFile(filePath, Buffer.from(buffer)); } catch (e: any) { - return { - success: false, - errMsg: `${url}下载失败,` + e.toString(), - path: "" - } + res.errMsg = `${url}下载失败,` + e.toString() + return res } } else if (url.protocol === "file:"){ - await fs.copyFile(url.pathname, filePath); - // filePath = (await NTQQApi.uploadFile(url.pathname)).path; + // await fs.copyFile(url.pathname, filePath); + if (process.platform === "win32"){ + filePath = url.pathname.slice(1) + } + else{ + filePath = url.pathname + } + res.isLocal = true } else{ - return { - success: false, - errMsg: `不支持的file协议,` + url.protocol, - path: "" - } + res.errMsg = `不支持的file协议,` + url.protocol + return res } - if (isGIF(filePath)) { + if (isGIF(filePath) && !res.isLocal) { await fs.rename(filePath, filePath + ".gif"); filePath += ".gif"; } - return { - success: true, - errMsg: "", - path: filePath - }; + res.success = true + res.path = filePath + return res } \ No newline at end of file