From 907c9053c738fe4468defebea0a420bd698b5919 Mon Sep 17 00:00:00 2001 From: linyuchen Date: Sat, 20 Jan 2024 14:37:03 +0800 Subject: [PATCH 1/3] fix config path --- manifest.json | 10 +- src/main/main.ts | 20 ++-- src/renderer.ts | 274 +++++++++++++++++++++++++---------------------- 3 files changed, 164 insertions(+), 140 deletions(-) diff --git a/manifest.json b/manifest.json index 231746d..d4b8e15 100644 --- a/manifest.json +++ b/manifest.json @@ -1,19 +1,19 @@ { - "manifest_version": 3, + "manifest_version": 4, "type": "extension", "name": "LLOneBot", "slug": "LLOneBot", "description": "LiteLoaderQQNT的OneBotApi", - "version": "1.2.6", + "version": "2.0.0", "thumbnail": "./icon.png", - "author": { + "authors": [{ "name": "linyuchen", "link": "https://github.com/linyuchen" - }, + }], "repository": { "repo": "linyuchen/LLOneBot", "branch": "main", - "use_release": { + "release": { "tag": "latest", "name": "LLOneBot.zip" } diff --git a/src/main/main.ts b/src/main/main.ts index d828bd0..c6653ff 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -19,6 +19,7 @@ import {ConfigUtil} from "./config"; import {startExpress} from "./HttpServer"; import {isGIF, log} from "./utils"; import {friends, groups, selfInfo} from "./data"; +import {} from "../global"; const fs = require('fs'); @@ -26,15 +27,17 @@ let running = false; // 加载插件时触发 -function onLoad(plugin: any) { +function onLoad() { log("main onLoaded"); + // const config_dir = browserWindow.LiteLoader.plugins["LLOneBot"].path.data; + const config_dir = global.LiteLoader.plugins["LLOneBot"].path.data; function getConfigUtil() { - const configFilePath = path.join(plugin.path.data, `config_${selfInfo.user_id}.json`) + const configFilePath = path.join(config_dir, `config_${selfInfo.user_id}.json`) return new ConfigUtil(configFilePath) } - if (!fs.existsSync(plugin.path.data)) { - fs.mkdirSync(plugin.path.data, {recursive: true}); + if (!fs.existsSync(config_dir)) { + fs.mkdirSync(config_dir, {recursive: true}); } ipcMain.handle(CHANNEL_GET_CONFIG, (event: any, arg: any) => { return getConfigUtil().getConfig() @@ -143,12 +146,17 @@ function onLoad(plugin: any) { // 创建窗口时触发 -function onBrowserWindowCreated(window: any, plugin: any) { +function onBrowserWindowCreated(window: any) { } +try { + onLoad(); +} catch (e: any) { + console.log(e.toString()) +} // 这两个函数都是可选的 export { - onLoad, onBrowserWindowCreated + onBrowserWindowCreated } \ No newline at end of file diff --git a/src/renderer.ts b/src/renderer.ts index 6a62807..72ab177 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -31,8 +31,6 @@ async function getFriends() { } window.llonebot.updateFriends(friends) return friends - - } async function getFriend(qq: string) { @@ -272,50 +270,40 @@ function recallMessage(msgId: string) { let chatListEle: HTMLCollectionOf -async function onLoad(arg: any) { - let runningStatus = await window.llonebot.getRunningStatus(); - if (runningStatus) { - return; - } - - async function getGroupsMembers(groupsArg: Group[]) { - // 批量获取群成员列表 - let failedGroups: Group[] = [] - for (const group of groupsArg) { - let handledGroup = await getGroupMembers(group.uid, true) - if (handledGroup.length == 0) { - failedGroups.push(group) - } - } - if (failedGroups.length > 0) { - console.log("获取群成员列表失败,重试", failedGroups.map(group => group.name)) - setTimeout(() => { - getGroupsMembers(failedGroups).then() - }, 1000) - } else { - window.llonebot.log("全部群成员获取完毕") +async function getGroupsMembers(groupsArg: Group[]) { + // 批量获取群成员列表 + let failedGroups: Group[] = [] + for (const group of groupsArg) { + let handledGroup = await getGroupMembers(group.uid, true) + if (handledGroup.length == 0) { + failedGroups.push(group) } } - await getFriends(); - await getGroups(); - await getGroupsMembers(groups); - - function onNewMessages(messages: MessageElement[]) { - async function func(messages: MessageElement[]) { - console.log("收到新消息", messages) - if (!self_qq) { - self_qq = (await window.LLAPI.getAccountInfo()).uin - } - await handleNewMessage(messages); - } - - func(messages).then(() => { - }) - // console.log("chatListEle", chatListEle) + if (failedGroups.length > 0) { + console.log("获取群成员列表失败,重试", failedGroups.map(group => group.name)) + setTimeout(() => { + getGroupsMembers(failedGroups).then() + }, 1000) + } else { + window.llonebot.log("全部群成员获取完毕") } - window.LLAPI.on("new-messages", onNewMessages); - window.LLAPI.on("new-send-messages", onNewMessages); +} +function onNewMessages(messages: MessageElement[]) { + async function func(messages: MessageElement[]) { + console.log("收到新消息", messages) + if (!self_qq) { + self_qq = (await window.LLAPI.getAccountInfo()).uin + } + await handleNewMessage(messages); + } + + func(messages).then(() => { + }) + // console.log("chatListEle", chatListEle) +} + +async function initAccountInfo(){ let accountInfo = await window.LLAPI.getAccountInfo(); window.llonebot.log("getAccountInfo " + JSON.stringify(accountInfo)); if (!accountInfo.uid) { @@ -326,101 +314,125 @@ async function onLoad(arg: any) { user_id: accountInfo.uin, nickname: selfInfo.nickName }); - window.llonebot.log("selfInfo " + JSON.stringify(selfInfo)) - window.llonebot.startExpress(); + window.llonebot.log("selfInfo " + JSON.stringify(selfInfo)); +} - window.llonebot.listenSendMessage((postData: PostDataSendMsg) => { - listenSendMessage(postData).then().catch(err => console.log("listenSendMessage err", err)) - }) - window.llonebot.listenRecallMessage((arg: { message_id: string }) => { - recallMessage(arg.message_id) - }) - window.llonebot.log("llonebot loaded"); - - window.LLAPI.add_qmenu((qContextMenu: Node) => { - let btn = document.createElement("a") - btn.className = "q-context-menu-item q-context-menu-item--normal vue-component" - btn.setAttribute("aria-disabled", "false") - btn.setAttribute("role", "menuitem") - btn.setAttribute("tabindex", "-1") - btn.onclick = () => { - // window.LLAPI.getPeer().then(peer => { - // // console.log("current peer", peer) - // if (peer && peer.chatType == "group") { - // getGroupMembers(peer.uid, true).then(()=> { - // console.log("获取群成员列表成功", groups); - // alert("获取群成员列表成功") - // }) - // } - // }) - async function func() { - for (const group of groups) { - await getGroupMembers(group.uid, true) +function onLoad() { + window.llonebot.log("llonebot render onLoad"); + window.llonebot.getRunningStatus().then(running=>{ + if (running) { + return; + } + initAccountInfo().then( + ()=>{ + if (friends.length == 0) { + getFriends().then(()=>{}); } - } - - func().then(() => { - console.log("获取群成员列表结果", groups); - // 找到members数量为空的群 - groups.map(group => { - if (group.members.length == 0) { - console.log(`${group.name}群成员为空`) - } - }) - window.llonebot.updateGroups(groups) - }) - } - btn.innerText = "获取群成员列表" - console.log(qContextMenu) - // qContextMenu.appendChild(btn) - }) - - window.LLAPI.on("context-msg-menu", (event, target, msgIds) => { - console.log("msg menu", event, target, msgIds); - }) - - // console.log("getAccountInfo", LLAPI.getAccountInfo()); - function getChatListEle() { - chatListEle = document.getElementsByClassName("viewport-list__inner") - console.log("chatListEle", chatListEle) - if (chatListEle.length == 0) { - setTimeout(getChatListEle, 500) - } else { - try { - // 选择要观察的目标节点 - const targetNode = chatListEle[0]; - - // 创建一个观察器实例并传入回调函数 - const observer = new MutationObserver(function (mutations) { - mutations.forEach(function (mutation) { - // console.log("chat list changed", mutation.type); // 输出 mutation 的类型 - // 获得当前聊天窗口 - window.LLAPI.getPeer().then(peer => { - // console.log("current peer", peer) - if (peer && peer.chatType == "group") { - getGroupMembers(peer.uid, false).then() - } - }) + if (groups.length == 0) { + getGroups().then(()=>{ + getGroupsMembers(groups).then(()=>{}); }); - }); + } + window.LLAPI.on("new-messages", onNewMessages); + window.LLAPI.on("new-send-messages", onNewMessages); + window.llonebot.log("llonebot render start"); + window.llonebot.startExpress(); - // 配置观察选项 - const config = {attributes: true, childList: true, subtree: true}; + window.llonebot.listenSendMessage((postData: PostDataSendMsg) => { + listenSendMessage(postData).then().catch(err => console.log("listenSendMessage err", err)) + }) + window.llonebot.listenRecallMessage((arg: { message_id: string }) => { + recallMessage(arg.message_id) + }) + window.llonebot.log("llonebot loaded"); + window.LLAPI.add_qmenu((qContextMenu: Node) => { + let btn = document.createElement("a") + btn.className = "q-context-menu-item q-context-menu-item--normal vue-component" + btn.setAttribute("aria-disabled", "false") + btn.setAttribute("role", "menuitem") + btn.setAttribute("tabindex", "-1") + btn.onclick = () => { + // window.LLAPI.getPeer().then(peer => { + // // console.log("current peer", peer) + // if (peer && peer.chatType == "group") { + // getGroupMembers(peer.uid, true).then(()=> { + // console.log("获取群成员列表成功", groups); + // alert("获取群成员列表成功") + // }) + // } + // }) + async function func() { + for (const group of groups) { + await getGroupMembers(group.uid, true) + } + } - // 传入目标节点和观察选项 - observer.observe(targetNode, config); + func().then(() => { + console.log("获取群成员列表结果", groups); + // 找到members数量为空的群 + groups.map(group => { + if (group.members.length == 0) { + console.log(`${group.name}群成员为空`) + } + }) + window.llonebot.updateGroups(groups) + }) + } + btn.innerText = "获取群成员列表" + console.log(qContextMenu) + // qContextMenu.appendChild(btn) + }) - } catch (e) { - window.llonebot.log(e) + window.LLAPI.on("context-msg-menu", (event, target, msgIds) => { + console.log("msg menu", event, target, msgIds); + }) + + // console.log("getAccountInfo", LLAPI.getAccountInfo()); + function getChatListEle() { + chatListEle = document.getElementsByClassName("viewport-list__inner") + console.log("chatListEle", chatListEle) + if (chatListEle.length == 0) { + setTimeout(getChatListEle, 500) + } else { + try { + // 选择要观察的目标节点 + const targetNode = chatListEle[0]; + + // 创建一个观察器实例并传入回调函数 + const observer = new MutationObserver(function (mutations) { + mutations.forEach(function (mutation) { + // console.log("chat list changed", mutation.type); // 输出 mutation 的类型 + // 获得当前聊天窗口 + window.LLAPI.getPeer().then(peer => { + // console.log("current peer", peer) + if (peer && peer.chatType == "group") { + getGroupMembers(peer.uid, false).then() + } + }) + }); + }); + + // 配置观察选项 + const config = {attributes: true, childList: true, subtree: true}; + + // 传入目标节点和观察选项 + observer.observe(targetNode, config); + + } catch (e) { + window.llonebot.log(e) + } + } + } + + // getChatListEle(); } - } - } - - // getChatListEle(); + ); + }); } // 打开设置界面时触发 -async function onConfigView(view: any) { +async function onSettingWindowCreated (view: any) { + window.llonebot.log("setting window created"); const {port, hosts} = await window.llonebot.getConfig() function creatHostEleStr(host: string) { @@ -494,7 +506,11 @@ async function onConfigView(view: any) { } + + + +onLoad() + export { - onLoad, - onConfigView + onSettingWindowCreated } \ No newline at end of file From 6364f90b2098307903639aa734842ba8c55e8f1c Mon Sep 17 00:00:00 2001 From: linyuchen Date: Sat, 20 Jan 2024 23:22:44 +0800 Subject: [PATCH 2/3] fix voice record type --- src/common/types.ts | 2 +- src/renderer.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/common/types.ts b/src/common/types.ts index fdd9b62..351f4a6 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -114,7 +114,7 @@ export type SendMessage = { text: string, // 纯文本 } } | { - type: "image" | "voice", + type: "image" | "voice" | "record", file: string, // 本地路径 data?: { file: string // 本地路径 diff --git a/src/renderer.ts b/src/renderer.ts index 72ab177..3f25bce 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -225,7 +225,7 @@ async function listenSendMessage(postData: PostDataSendMsg) { message.content = `@${atMember.cardName || atMember.nick}` } else if (message.type == "text") { message.content = message.data?.text || message.content - } else if (message.type == "image" || message.type == "voice") { + } else if (message.type == "image" || message.type == "voice" || message.type == "record") { // todo: 收到的应该是uri格式的,需要转成本地的, uri格式有三种,http, file, base64 let url = message.data?.file || message.file let uri = new URL(url); @@ -233,7 +233,8 @@ async function listenSendMessage(postData: PostDataSendMsg) { if (message.type == "image") { ext = ".png" } - if (message.type == "voice") { + if (message.type == "voice" || message.type == "record") { + message.type = "voice" ext = ".amr" } let localFilePath = `${Date.now()}${ext}` From 5bbbe77ad0c8ba58cc463cbf93ce4bd8c23bf8b5 Mon Sep 17 00:00:00 2001 From: linyuchen Date: Sat, 20 Jan 2024 23:53:38 +0800 Subject: [PATCH 3/3] doc update --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5673904..c9024a7 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ # LLOneBot API +注意:本文档对应的是 LiteLoader 1.0.0及以上版本,如果你使用的是旧版本请切换到本项目v1分支查看文档 + 将NTQQLiteLoaderAPI封装成OneBot11/12标准的API, V12没有完整测试 ## 安装方法 -1.安装[NTQQLiteLoader](https://github.com/LiteLoaderQQNT/LiteLoaderQQNT) +1.安装[NTQQLiteLoader](https://liteloaderqqnt.github.io/guide/install.html) 2.安装修改后的[LiteLoaderQQNT-Plugin-LLAPI](https://github.com/linyuchen/LiteLoaderQQNT-Plugin-LLAPI),原版的功能有缺陷 -3.安装本项目插件[OneBotApi](https://github.com/linyuchen/LiteLoaderQQNT-OneBotApi/releases/) +3.安装本项目插件[OneBotApi](https://github.com/linyuchen/LiteLoaderQQNT-OneBotApi/releases/), 注意本插件2.0以下的版本不支持LiteLoader 1.0.0及以上版本 -*关于插件的安装方法: 上述的两个插件都没有上架NTQQLiteLoader插件市场,需要自己下载源码复制到插件目录* +*关于插件的安装方法: 上述的两个插件都没有上架NTQQLiteLoader插件市场,需要自己下载复制到插件目录* -*Windows插件目录:`%USERPROFILE%/Documents/LiteLoaderQQNT/plugins`* - -*Mac插件目录:`~/Library/Containers/com.tencent.qq/Data/Documents/LiteLoaderQQNT/plugins`* +*插件目录:`LiteLoaderQQNT/plugins`* ## 支持的API