mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
支持at
This commit is contained in:
@@ -5,9 +5,10 @@
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build-mac": "tsc && npm run deploy-mac",
|
||||
"build": "tsc & tsc -p src/tsconfig.json",
|
||||
"build-mac": "npm run build && npm run deploy-mac",
|
||||
"deploy-mac": "cp dist/* ~/Library/Containers/com.tencent.qq/Data/Documents/LiteLoaderQQNT/plugins/LLOnebot/",
|
||||
"build-win": "tsc && npm run deploy-win",
|
||||
"build-win": "npm run build && npm run deploy-win",
|
||||
"deploy-win": "cmd /c \"copy dist\\* %USERPROFILE%\\documents\\LiteLoaderQQNT\\plugins\\LLOnebot\\\""
|
||||
},
|
||||
"author": "",
|
||||
|
2
src/global.d.ts
vendored
2
src/global.d.ts
vendored
@@ -31,7 +31,7 @@ declare var llonebot: {
|
||||
updateFriends: (friends: User[]) => void
|
||||
updateGroupMembers: (data: { groupMembers: User[], group_id: string }) => void
|
||||
startExpress: () => void
|
||||
log(data: any): void
|
||||
log(data: any): void,
|
||||
};
|
||||
|
||||
declare global {
|
||||
|
@@ -605,10 +605,10 @@ class Destructor {
|
||||
elementId: "",
|
||||
textElement: {
|
||||
content: element.content,
|
||||
atType: 0,
|
||||
atUid: "",
|
||||
atType: element.atType || 0,
|
||||
atUid: element.atUid || "",
|
||||
atTinyId: "",
|
||||
atNtUid: "",
|
||||
atNtUid: element.atNtUid,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
56
src/main.ts
56
src/main.ts
@@ -66,7 +66,14 @@ function startExpress(event: any) {
|
||||
resData["data"] = groups.map(group => {
|
||||
return {
|
||||
group_id: group.uid,
|
||||
group_name: group.name
|
||||
group_name: group.name,
|
||||
group_members: group.members.map(member => {
|
||||
return {
|
||||
user_id: member.uin,
|
||||
user_name: member.cardName || member.nick,
|
||||
user_display_name: member.cardName || member.nick
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -74,10 +81,29 @@ function startExpress(event: any) {
|
||||
let group = groups.find(group => group.uid == jsonData.params.group_id)
|
||||
if (group){
|
||||
resData["data"] = group?.members?.map(member => {
|
||||
let role = "member"
|
||||
switch (member.role) {
|
||||
case 4: {
|
||||
role = "owner"
|
||||
break;
|
||||
}
|
||||
case 3:{
|
||||
role = "admin"
|
||||
break
|
||||
}
|
||||
case 2:{
|
||||
role = "member"
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
return {
|
||||
user_id: member.uin,
|
||||
user_name: member.cardName || member.nick,
|
||||
user_display_name: member.cardName || member.nick
|
||||
user_name: member.nick,
|
||||
user_display_name: member.cardName || member.nick,
|
||||
nickname: member.nick,
|
||||
card: member.cardName,
|
||||
role
|
||||
}
|
||||
|
||||
}) || []
|
||||
@@ -96,7 +122,7 @@ function startExpress(event: any) {
|
||||
}
|
||||
res.send(resData)
|
||||
});
|
||||
app.listen(port, () => {
|
||||
app.listen(port,"0.0.0.0", () => {
|
||||
console.log(`服务器已启动,监听端口 ${port}`);
|
||||
});
|
||||
}
|
||||
@@ -109,6 +135,28 @@ function onLoad(plugin: any) {
|
||||
})
|
||||
|
||||
ipcMain.on("updateGroups", (event: any, arg: Group[]) => {
|
||||
for(const group of arg){
|
||||
let existGroup = groups.find(g => g.uid == group.uid)
|
||||
if (existGroup){
|
||||
if (!existGroup.members){
|
||||
existGroup.members = []
|
||||
}
|
||||
existGroup.name = group.name
|
||||
for (const member of group.members || []){
|
||||
let existMember = existGroup.members?.find(m => m.uin == member.uin)
|
||||
if (existMember){
|
||||
existMember.nick = member.nick
|
||||
existMember.cardName = member.cardName
|
||||
}
|
||||
else{
|
||||
existGroup.members?.push(member)
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
groups.push(group)
|
||||
}
|
||||
}
|
||||
groups = arg
|
||||
})
|
||||
|
||||
|
214
src/renderer.ts
214
src/renderer.ts
@@ -2,7 +2,8 @@
|
||||
|
||||
// import express from "express";
|
||||
// const { ipcRenderer } = require('electron');
|
||||
import {Group, MessageElement, Peer, PostDataSendMsg, User} from "./types";
|
||||
import {AtType, Group, MessageElement, Peer, PostDataSendMsg, User} from "./types";
|
||||
|
||||
|
||||
const host = "http://localhost:5000"
|
||||
|
||||
@@ -50,12 +51,13 @@ async function getGroups() {
|
||||
async function getGroupMembers(group_qq: string, forced: boolean = false) {
|
||||
let group = await getGroup(group_qq)
|
||||
if (!group?.members || group!.members!.length == 0 || forced) {
|
||||
let res = (await window.LLAPI.getGroupMemberList(group_qq + "_groupMemberList_MainWindow", 5000))
|
||||
let res = (await window.LLAPI.getGroupMemberList(group_qq, 5000))
|
||||
// console.log(`更新群${group}成员列表 await`, _res)
|
||||
// window.LLAPI.getGroupMemberList(group_qq + "_groupMemberList_MainWindow", 5000).then(res =>{
|
||||
let members = res.result.infos.values();
|
||||
console.log("getGroupMemberList api response:", res)
|
||||
if (members && forced) {
|
||||
group!.members = []
|
||||
group.members = []
|
||||
}
|
||||
for (const member of members) {
|
||||
if (!group!.members!.find(m => m.uid == member.uid)) {
|
||||
@@ -63,7 +65,7 @@ async function getGroupMembers(group_qq: string, forced: boolean = false) {
|
||||
}
|
||||
}
|
||||
window.llonebot.updateGroups(groups)
|
||||
console.log(`更新群${group}成员列表`, group)
|
||||
console.log(`更新群${group.name}成员列表`, group)
|
||||
// })
|
||||
}
|
||||
return group?.members
|
||||
@@ -89,8 +91,11 @@ async function forwardMessage(message: MessageElement) {
|
||||
platform: "qq",
|
||||
user_id: self_qq
|
||||
},
|
||||
self_id: self_qq,
|
||||
time: 0,
|
||||
type: "message",
|
||||
post_type: "message",
|
||||
message_type: message.peer.chatType,
|
||||
detail_type: message.peer.chatType,
|
||||
sub_type: "",
|
||||
message: []
|
||||
@@ -111,28 +116,27 @@ async function forwardMessage(message: MessageElement) {
|
||||
data: {},
|
||||
type: "unknown"
|
||||
}
|
||||
|
||||
if (element.textElement?.atType == 2) {
|
||||
message_data["type"] = "at"
|
||||
if (element.textElement.atUid != "0") {
|
||||
message_data["data"]["mention"] = element.textElement.atUid
|
||||
} else {
|
||||
let uid = element.textElement.atNtUid
|
||||
let atMember = await getGroupMember(message.peer.uid, uid)
|
||||
message_data["data"]["mention"] = atMember!.uin
|
||||
if (element.textElement?.atType == 2) {
|
||||
message_data["type"] = "at"
|
||||
if (element.textElement.atUid != "0") {
|
||||
message_data["data"]["mention"] = element.textElement.atUid
|
||||
} else {
|
||||
let uid = element.textElement.atNtUid
|
||||
let atMember = await getGroupMember(message.peer.uid, uid)
|
||||
message_data["data"]["mention"] = atMember!.uin
|
||||
}
|
||||
} else if (element.textElement) {
|
||||
message_data["type"] = "text"
|
||||
message_data["data"]["text"] = element.textElement.content
|
||||
} else if (element.picElement) {
|
||||
message_data["type"] = "image"
|
||||
message_data["data"]["file_id"] = element.picElement.fileUuid
|
||||
message_data["data"]["path"] = element.picElement.sourcePath
|
||||
} else if (element.replyElement) {
|
||||
message_data["type"] = "reply"
|
||||
message_data["data"]["reply"] = element.replyElement.sourceMsgIdInRecords
|
||||
}
|
||||
} else if (element.textElement) {
|
||||
message_data["type"] = "text"
|
||||
message_data["data"]["text"] = element.textElement.content
|
||||
} else if (element.picElement) {
|
||||
message_data["type"] = "image"
|
||||
message_data["data"]["file_id"] = element.picElement.fileUuid
|
||||
message_data["data"]["path"] = element.picElement.sourcePath
|
||||
} else if (element.replyElement) {
|
||||
message_data["type"] = "reply"
|
||||
message_data["data"]["reply"] = element.replyElement.sourceMsgIdInRecords
|
||||
}
|
||||
onebot_message_data.message.push(message_data)
|
||||
onebot_message_data.message.push(message_data)
|
||||
}
|
||||
|
||||
console.log("发送上传消息给ipc main", onebot_message_data)
|
||||
@@ -169,11 +173,20 @@ async function listenSendMessage(postData: PostDataSendMsg) {
|
||||
name: group.name,
|
||||
uid: group.uid
|
||||
}
|
||||
for (let message of postData.params.message){
|
||||
if (message.type == "text" && message.atType == 2){
|
||||
let atUid = message.atUid
|
||||
let group = await getGroup(postData.params.group_id)
|
||||
let atMember = group.members.find(member => member.uin == atUid)
|
||||
message.atNtUid = atMember.uid
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("未找到群, 发送群消息失败", postData)
|
||||
}
|
||||
}
|
||||
if (peer) {
|
||||
console.log("发送消息", postData)
|
||||
window.LLAPI.sendMessage(peer, postData.params.message).then(res => console.log("消息发送成功:", res),
|
||||
err => console.log("消息发送失败", postData, err))
|
||||
}
|
||||
@@ -187,7 +200,28 @@ function onLoad() {
|
||||
window.llonebot.listenSendMessage((postData: PostDataSendMsg) => {
|
||||
listenSendMessage(postData).then()
|
||||
});
|
||||
getGroups().then()
|
||||
|
||||
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{
|
||||
console.log("全部群成员获取完毕", groups)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function onNewMessages(messages: MessageElement[]) {
|
||||
async function func(messages: MessageElement[]) {
|
||||
@@ -203,41 +237,51 @@ function onLoad() {
|
||||
console.log("chatListEle", chatListEle)
|
||||
}
|
||||
|
||||
window.LLAPI.on("new-messages", onNewMessages);
|
||||
|
||||
try {
|
||||
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("获取群成员列表成功")
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
window.LLAPI.getGroupMemberList("164461995", 5000).then(res =>{
|
||||
console.log("获取群成员列表结果", res)
|
||||
})
|
||||
}
|
||||
btn.innerText = "获取群成员列表"
|
||||
console.log(qContextMenu)
|
||||
// qContextMenu.appendChild(btn)
|
||||
// qContextMenu.insertAdjacentHTML("beforeend", btn)
|
||||
getGroups().then(()=>{
|
||||
getGroupsMembers(groups).then(()=>{
|
||||
window.LLAPI.on("new-messages", onNewMessages);
|
||||
})
|
||||
}catch (e){
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
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("msg menu", event, target, msgIds);
|
||||
})
|
||||
|
||||
// console.log("getAccountInfo", LLAPI.getAccountInfo());
|
||||
@@ -247,33 +291,33 @@ function onLoad() {
|
||||
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)
|
||||
// }
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,10 +1,13 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "es6",
|
||||
"target": "es6",
|
||||
"outDir": "dist2/"
|
||||
"module": "es6",
|
||||
"outDir": "../dist",
|
||||
"strict": false,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["renderer.ts"],
|
||||
"exclude": ["main.ts", "preload.ts"]
|
||||
// "exclude": ["main.ts", "preload.ts"]
|
||||
}
|
@@ -74,6 +74,9 @@ export type MessageElement = {
|
||||
export type SendMessage = {
|
||||
type: "text",
|
||||
content: string,
|
||||
atType?: AtType,
|
||||
atUid?: string,
|
||||
atNtUid?: string
|
||||
} | {
|
||||
type: "image",
|
||||
file: string, // 本地路径
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"target": "ESNext",
|
||||
"module": "commonjs",
|
||||
"outDir": "./dist",
|
||||
"strict": false,
|
||||
@@ -9,9 +9,7 @@
|
||||
"moduleResolution": "node",
|
||||
// "declaration": false
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"files": ["src/main.ts", "src/preload.ts"],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
|
Reference in New Issue
Block a user