mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
群成员获取研究
This commit is contained in:
parent
7a7d21d533
commit
e2759417f5
@ -5,7 +5,8 @@
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "tsc"
|
||||
"build-mac": "tsc && npm run deploy-mac",
|
||||
"deploy-mac": "cp dist/* ~/Library/Containers/com.tencent.qq/Data/Documents/LiteLoaderQQNT/plugins/LLOnebot/"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
|
85
src/global.d.ts
vendored
85
src/global.d.ts
vendored
@ -1,68 +1,6 @@
|
||||
declare enum AtType {
|
||||
notAt = 0,
|
||||
atUser = 2
|
||||
}
|
||||
import {Group, GroupMemberInfo, MessageElement, Peer, PostDataSendMsg, SendMessage, User} from "./types";
|
||||
|
||||
declare type Peer = {
|
||||
chatType: "private" | "group"
|
||||
name: string
|
||||
uid: string // qq号
|
||||
}
|
||||
|
||||
interface MessageElement {
|
||||
raw: {
|
||||
elements: {
|
||||
|
||||
replyElement: {
|
||||
senderUid: string, // 原消息发送者QQ号
|
||||
sourceMsgIsIncPic: boolean; // 原消息是否有图片
|
||||
sourceMsgText: string;
|
||||
sourceMsgIdInRecords: string; // 原消息id
|
||||
},
|
||||
textElement: {
|
||||
atType: AtType
|
||||
atUid: string,
|
||||
content: string
|
||||
},
|
||||
picElement: {
|
||||
sourcePath: string // 图片本地路径
|
||||
picWidth: number
|
||||
picHeight: number
|
||||
fileSize: number
|
||||
fileName: string
|
||||
fileUuid: string
|
||||
}
|
||||
}[]
|
||||
}
|
||||
|
||||
peer: Peer,
|
||||
sender: {
|
||||
uid: string // 一串加密的字符串
|
||||
memberName: string
|
||||
nickname: string
|
||||
}
|
||||
}
|
||||
|
||||
declare type User = {
|
||||
avatarUrl?: string;
|
||||
bio?: string; // 签名
|
||||
nickName: string;
|
||||
uid?: string; // 加密的字符串
|
||||
uin: string; // QQ号
|
||||
}
|
||||
|
||||
declare type Group = {
|
||||
uid: string; // 群号
|
||||
name: string;
|
||||
}
|
||||
|
||||
declare type SendMessage = {
|
||||
type: "text",
|
||||
content: string,
|
||||
} | {
|
||||
type: "image",
|
||||
file: string, // 这是本地路径?
|
||||
}
|
||||
|
||||
declare var LLAPI: {
|
||||
on(event: "new-messages", callback: (data: MessageElement[]) => void): void;
|
||||
@ -76,16 +14,12 @@ declare var LLAPI: {
|
||||
sendMessage(peer: Peer, message: SendMessage[]): Promise<void>;
|
||||
getGroupsList(forced: boolean): Promise<Group[]>
|
||||
getFriendsList(forced: boolean): Promise<User[]>
|
||||
getGroupMemberList(group_id: string, num: number): Promise<{result: { infos: Record<string, GroupMemberInfo> }}>
|
||||
};
|
||||
|
||||
declare type PostDataSendMsg = {
|
||||
action: "send_private_msg" | "send_group_msg" | "get_group_list",
|
||||
params: {
|
||||
user_id: string,
|
||||
group_id: string,
|
||||
message: SendMessage[];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
declare var llonebot: {
|
||||
postData: (data: any) => void
|
||||
@ -94,4 +28,11 @@ declare var llonebot: {
|
||||
updateFriends: (friends: User[]) => void
|
||||
updateGroupMembers: (data: { groupMembers: User[], group_id: string }) => void
|
||||
startExpress: () => void
|
||||
};
|
||||
};
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
LLAPI: typeof LLAPI;
|
||||
llonebot: typeof llonebot;
|
||||
}
|
||||
}
|
11
src/main.ts
11
src/main.ts
@ -1,5 +1,7 @@
|
||||
// 运行在 Electron 主进程 下的插件入口
|
||||
|
||||
import {Group, PostDataSendMsg, User} from "./types";
|
||||
|
||||
const express = require("express")
|
||||
const {ipcMain, webContents} = require('electron');
|
||||
const fs = require('fs');
|
||||
@ -24,8 +26,9 @@ function sendIPCCallSendQQMsg(postData: PostDataSendMsg) {
|
||||
sendIPCMsg(CHANNEL_SEND_MSG, postData);
|
||||
}
|
||||
|
||||
function log(msg: string){
|
||||
fs.appendFile("d:\\llonebot.log", msg + "\n", (err: any) => {
|
||||
function log(msg: any){
|
||||
let currentDateTime = new Date().toLocaleString();
|
||||
fs.appendFile("./llonebot.log", currentDateTime + ":" + msg + "\n", (err: any) => {
|
||||
|
||||
})
|
||||
}
|
||||
@ -143,6 +146,10 @@ function onLoad(plugin: any) {
|
||||
log(e.toString())
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on("llonebot_log", (event: any, arg: any) => {
|
||||
log(arg)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
// Electron 主进程 与 渲染进程 交互的桥梁
|
||||
|
||||
import {Group, PostDataSendMsg, User} from "./types";
|
||||
|
||||
const {contextBridge} = require("electron");
|
||||
const {ipcRenderer} = require('electron');
|
||||
|
||||
@ -24,6 +26,9 @@ contextBridge.exposeInMainWorld("llonebot", {
|
||||
},
|
||||
startExpress: () => {
|
||||
ipcRenderer.send("startExpress");
|
||||
},
|
||||
log: (data: any) => {
|
||||
ipcRenderer.send("log", data);
|
||||
}
|
||||
// startExpress,
|
||||
});
|
169
src/renderer.ts
169
src/renderer.ts
@ -2,16 +2,23 @@
|
||||
|
||||
// import express from "express";
|
||||
// const { ipcRenderer } = require('electron');
|
||||
enum AtType {
|
||||
notAt = 0,
|
||||
atUser = 2
|
||||
}
|
||||
import {AtType, Group, MessageElement, Peer, PostDataSendMsg, User} from "./types";
|
||||
|
||||
const host = "http://localhost:5000"
|
||||
|
||||
let self_qq: string = ""
|
||||
let groups: Group[] = []
|
||||
let friends: User[] = []
|
||||
let groupMembers: { group_id: string, groupMembers: User[] }[] = []
|
||||
let uid_maps: Record<string, User> = {} // 一串加密的字符串 -> qq号
|
||||
async function getUserInfo(uid: string): Promise<User>{
|
||||
let user = uid_maps[uid]
|
||||
if (!user){
|
||||
// 从服务器获取用户信息
|
||||
user = await window.LLAPI.getUserInfo(uid)
|
||||
uid_maps[uid] = user
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
function getFriend(qq: string) {
|
||||
return friends.find(friend => friend.uid == qq)
|
||||
@ -21,9 +28,7 @@ function getGroup(qq: string) {
|
||||
return groups.find(group => group.uid == qq)
|
||||
}
|
||||
|
||||
let self_qq: string = ""
|
||||
|
||||
let uid_maps: Record<string, string> = {} // 一串加密的字符串 -> qq号
|
||||
|
||||
function forwardMessage(message: MessageElement) {
|
||||
try {
|
||||
@ -36,79 +41,92 @@ function forwardMessage(message: MessageElement) {
|
||||
type: "message",
|
||||
detail_type: message.peer.chatType,
|
||||
sub_type: "",
|
||||
message: message.raw.elements.map(element => {
|
||||
let message_data: any = {
|
||||
data: {}
|
||||
}
|
||||
if (element.textElement?.atType == AtType.atUser) {
|
||||
message_data["type"] = "at"
|
||||
message_data["data"]["mention"] = element.textElement.atUid
|
||||
} 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
|
||||
}
|
||||
return message_data
|
||||
})
|
||||
message: []
|
||||
}
|
||||
|
||||
let group: Group
|
||||
if (message.peer.chatType == "group") {
|
||||
let group_id = message.peer.uid
|
||||
group = groups.find(group => group.uid == group_id)!
|
||||
onebot_message_data["group_id"] = message.peer.uid
|
||||
// todo: 将加密的uid转成qq号
|
||||
let groupMember = groupMembers.find(group => group.group_id == message.peer.uid)?.groupMembers.find(member => member.uid == message.sender.uid)
|
||||
onebot_message_data["user_id"] = groupMember!.uin
|
||||
let groupMember = group.members!.find(member => member.uid == message.sender.uid)
|
||||
if (groupMember) {
|
||||
console.log("群成员信息存在,使用群成员信息")
|
||||
onebot_message_data["user_id"] = groupMember.uin
|
||||
}
|
||||
else{
|
||||
console.log("群成员信息不存在,使用原始uid")
|
||||
onebot_message_data["user_id"] = message.sender.uid
|
||||
}
|
||||
console.log("收到群消息", onebot_message_data)
|
||||
} else if (message.peer.chatType == "private") {
|
||||
onebot_message_data["user_id"] = message.peer.uid
|
||||
}
|
||||
console.log("发送上传消息给ipcmain", onebot_message_data)
|
||||
llonebot.postData(onebot_message_data);
|
||||
for (let element of message.raw.elements) {
|
||||
let message_data: any = {
|
||||
data: {}
|
||||
}
|
||||
|
||||
if (element.textElement?.atType == AtType.atUser) {
|
||||
message_data["type"] = "at"
|
||||
if (element.textElement.atUid != "0") {
|
||||
message_data["data"]["mention"] = element.textElement.atUid
|
||||
} else {
|
||||
let uid = element.textElement.atNtUid
|
||||
let atMember = group!.members!.find(member => member.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
|
||||
}
|
||||
onebot_message_data.message.push(message_data)
|
||||
}
|
||||
|
||||
console.log("发送上传消息给ipc main", onebot_message_data)
|
||||
window.llonebot.postData(onebot_message_data);
|
||||
} catch (e) {
|
||||
console.log("上传消息事件失败", e)
|
||||
}
|
||||
}
|
||||
|
||||
function handleNewMessage(messages: MessageElement[]) {
|
||||
messages.forEach(message => {
|
||||
async function handleNewMessage(messages: MessageElement[]) {
|
||||
for (let message of messages) {
|
||||
if (message.peer.chatType == "group") {
|
||||
let group = groupMembers.find(group => group.group_id == message.peer.uid)
|
||||
let group = groups.find(group => group.uid == message.peer.uid)
|
||||
if (!group) {
|
||||
let members = (await window.LLAPI.getGroupMemberList(message.peer.uid + "_groupMemberList_MainWindow", 5000)).result.infos
|
||||
let membersList = Object.values(members)
|
||||
group = {
|
||||
group_id: message.peer.uid,
|
||||
groupMembers: []
|
||||
name: message.peer.name,
|
||||
uid: message.peer.uid,
|
||||
members: membersList
|
||||
}
|
||||
groupMembers.push(group)
|
||||
}
|
||||
let existMember = group!.groupMembers.find(member => member.uid == message.sender.uid)
|
||||
if (!existMember) {
|
||||
window.LLAPI.getUserInfo(message.sender.uid).then(user => {
|
||||
let member = {memberName: message.sender.memberName, uid: user.uin, nickName: user.nickName}
|
||||
// group!.groupMembers.push(member)
|
||||
group!.groupMembers.push(user)
|
||||
llonebot.updateGroupMembers(group!)
|
||||
forwardMessage(message)
|
||||
}).catch(err => {
|
||||
console.log("获取群成员信息失败", err)
|
||||
})
|
||||
}else{
|
||||
forwardMessage(message)
|
||||
groups.push(group)
|
||||
window.llonebot.updateGroups(groups);
|
||||
}
|
||||
}
|
||||
else{
|
||||
forwardMessage(message);
|
||||
}
|
||||
})
|
||||
forwardMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
async function getGroups(){
|
||||
groups = await window.LLAPI.getGroupsList(false)
|
||||
for (let group of groups) {
|
||||
group.members = [];
|
||||
}
|
||||
window.llonebot.updateGroups(groups)
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
llonebot.startExpress();
|
||||
llonebot.listenSendMessage((postData: PostDataSendMsg) => {
|
||||
window.llonebot.startExpress();
|
||||
window.llonebot.listenSendMessage((postData: PostDataSendMsg) => {
|
||||
if (postData.action == "send_private_msg" || postData.action == "send_group_msg") {
|
||||
let peer: Peer | null = null;
|
||||
if (postData.action == "send_private_msg") {
|
||||
@ -131,30 +149,25 @@ function onLoad() {
|
||||
}
|
||||
}
|
||||
if (peer) {
|
||||
LLAPI.sendMessage(peer, postData.params.message).then(res => console.log("消息发送成功:", res),
|
||||
window.LLAPI.sendMessage(peer, postData.params.message).then(res => console.log("消息发送成功:", res),
|
||||
err => console.log("消息发送失败", postData, err))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.LLAPI.getGroupsList(false).then(groupsList => {
|
||||
groups = groupsList
|
||||
llonebot.updateGroups(groupsList)
|
||||
})
|
||||
|
||||
window.LLAPI.on("new-messages", (messages) => {
|
||||
console.log("收到新消息", messages)
|
||||
// 往groupMembers里面添加群成员
|
||||
if (!self_qq){
|
||||
window.LLAPI.getAccountInfo().then(accountInfo => {
|
||||
console.log("getAccountInfo", accountInfo)
|
||||
self_qq = accountInfo.uin
|
||||
handleNewMessage(messages)
|
||||
})
|
||||
}else{
|
||||
handleNewMessage(messages)
|
||||
getGroups().then()
|
||||
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(() => {})
|
||||
}
|
||||
|
||||
window.LLAPI.on("new-messages", onNewMessages);
|
||||
|
||||
// console.log("getAccountInfo", LLAPI.getAccountInfo());
|
||||
}
|
||||
|
||||
|
89
src/types.ts
Normal file
89
src/types.ts
Normal file
@ -0,0 +1,89 @@
|
||||
export enum AtType {
|
||||
notAt = 0,
|
||||
atUser = 2
|
||||
}
|
||||
export type GroupMemberInfo = {
|
||||
avatarPath: string;
|
||||
cardName: string;
|
||||
cardType: number;
|
||||
isDelete: boolean;
|
||||
nick: string;
|
||||
qid: string;
|
||||
remark: string;
|
||||
role: number; // 群主:4, 管理员:3,群员:2
|
||||
shutUpTime: number; // 禁言时间,单位是什么暂时不清楚
|
||||
uid: string; // 加密的字符串
|
||||
uin: string; // QQ号
|
||||
}
|
||||
|
||||
export type User = {
|
||||
avatarUrl?: string;
|
||||
bio?: string; // 签名
|
||||
nickName: string;
|
||||
uid?: string; // 加密的字符串
|
||||
uin: string; // QQ号
|
||||
}
|
||||
|
||||
export type Group = {
|
||||
uid: string; // 群号
|
||||
name: string;
|
||||
members?: GroupMemberInfo[];
|
||||
}
|
||||
|
||||
export type Peer = {
|
||||
chatType: "private" | "group"
|
||||
name: string
|
||||
uid: string // qq号
|
||||
}
|
||||
|
||||
export type MessageElement = {
|
||||
raw: {
|
||||
elements: {
|
||||
|
||||
replyElement: {
|
||||
senderUid: string, // 原消息发送者QQ号
|
||||
sourceMsgIsIncPic: boolean; // 原消息是否有图片
|
||||
sourceMsgText: string;
|
||||
sourceMsgIdInRecords: string; // 原消息id
|
||||
},
|
||||
textElement: {
|
||||
atType: AtType
|
||||
atUid: string,
|
||||
content: string,
|
||||
atNtUid: string
|
||||
},
|
||||
picElement: {
|
||||
sourcePath: string // 图片本地路径
|
||||
picWidth: number
|
||||
picHeight: number
|
||||
fileSize: number
|
||||
fileName: string
|
||||
fileUuid: string
|
||||
}
|
||||
}[]
|
||||
}
|
||||
|
||||
peer: Peer,
|
||||
sender: {
|
||||
uid: string // 一串加密的字符串
|
||||
memberName: string
|
||||
nickname: string
|
||||
}
|
||||
}
|
||||
|
||||
export type SendMessage = {
|
||||
type: "text",
|
||||
content: string,
|
||||
} | {
|
||||
type: "image",
|
||||
file: string, // 本地路径
|
||||
}
|
||||
|
||||
export type PostDataSendMsg = {
|
||||
action: "send_private_msg" | "send_group_msg" | "get_group_list",
|
||||
params: {
|
||||
user_id: string,
|
||||
group_id: string,
|
||||
message: SendMessage[];
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user