mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
feat: group admin change notice
This commit is contained in:
@@ -2,6 +2,8 @@ import fs from "fs";
|
||||
import {Config, OB11Config} from "./types";
|
||||
import {mergeNewProperties} from "./utils";
|
||||
|
||||
export const HOOK_LOG = false;
|
||||
|
||||
export class ConfigUtil {
|
||||
private readonly configPath: string;
|
||||
private config: Config | null = null;
|
||||
|
@@ -43,7 +43,7 @@ export async function getGroup(qq: string): Promise<Group | undefined> {
|
||||
return group
|
||||
}
|
||||
|
||||
export async function getGroupMember(groupQQ: string, memberQQ: string=null, memberUid: string=null) {
|
||||
export async function getGroupMember(groupQQ: string, memberQQ: string, memberUid: string=null) {
|
||||
const group = await getGroup(groupQQ)
|
||||
if (group) {
|
||||
let filterFunc: (member: GroupMember) => boolean
|
||||
|
@@ -6,17 +6,17 @@ import {Config} from "../common/types";
|
||||
import {CHANNEL_GET_CONFIG, CHANNEL_LOG, CHANNEL_SET_CONFIG,} from "../common/channels";
|
||||
import {ob11WebsocketServer} from "../onebot11/server/ws/WebsocketServer";
|
||||
import {CONFIG_DIR, getConfigUtil, log} from "../common/utils";
|
||||
import {addHistoryMsg, getGroupMember, msgHistory, selfInfo} from "../common/data";
|
||||
import {addHistoryMsg, getGroup, getGroupMember, msgHistory, selfInfo} from "../common/data";
|
||||
import {hookNTQQApiCall, hookNTQQApiReceive, ReceiveCmd, registerReceiveHook} from "../ntqqapi/hook";
|
||||
import {OB11Constructor} from "../onebot11/constructor";
|
||||
import {NTQQApi} from "../ntqqapi/ntcall";
|
||||
import {ChatType, RawMessage} from "../ntqqapi/types";
|
||||
import {ChatType, GroupNotify, GroupNotifyTypes, RawMessage} from "../ntqqapi/types";
|
||||
import {ob11HTTPServer} from "../onebot11/server/http";
|
||||
import {OB11FriendRecallNoticeEvent} from "../onebot11/event/notice/OB11FriendRecallNoticeEvent";
|
||||
import {OB11GroupRecallNoticeEvent} from "../onebot11/event/notice/OB11GroupRecallNoticeEvent";
|
||||
import {postEvent} from "../onebot11/server/postevent";
|
||||
import {ob11ReverseWebsockets} from "../onebot11/server/ws/ReverseWebsocket";
|
||||
import {EventType} from "../onebot11/event/OB11BaseEvent";
|
||||
import {OB11GroupAdminNoticeEvent} from "../onebot11/event/notice/OB11GroupAdminNoticeEvent";
|
||||
|
||||
|
||||
let running = false;
|
||||
@@ -105,8 +105,7 @@ function onLoad() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function start() {
|
||||
async function startReceiveHook() {
|
||||
registerReceiveHook<{ msgList: Array<RawMessage> }>(ReceiveCmd.NEW_MSG, (payload) => {
|
||||
try {
|
||||
postReceiveMsg(payload.msgList);
|
||||
@@ -159,6 +158,55 @@ function onLoad() {
|
||||
log("report self message error: ", e.toString());
|
||||
}
|
||||
})
|
||||
registerReceiveHook<{
|
||||
"doubt": boolean,
|
||||
"oldestUnreadSeq": string,
|
||||
"unreadCount": number
|
||||
}>(ReceiveCmd.UNREAD_GROUP_NOTIFY, async (payload) => {
|
||||
if (payload.unreadCount) {
|
||||
log("开始获取群通知详情")
|
||||
let notify: GroupNotify;
|
||||
try {
|
||||
notify = await NTQQApi.getGroupNotifies();
|
||||
}catch (e) {
|
||||
// log("获取群通知详情失败", e);
|
||||
return
|
||||
}
|
||||
|
||||
const notifies = notify.notifies.slice(0, payload.unreadCount)
|
||||
log("获取群通知详情完成", notifies, payload);
|
||||
try {
|
||||
for (const notify of notifies) {
|
||||
if (parseInt(notify.seq) / 1000 < startTime){
|
||||
continue;
|
||||
}
|
||||
if ([GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET].includes(notify.type)) {
|
||||
log("有管理员变动通知");
|
||||
let groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent()
|
||||
groupAdminNoticeEvent.group_id = parseInt(notify.group.groupCode);
|
||||
log("开始获取变动的管理员")
|
||||
const member = await getGroupMember(notify.group.groupCode, null, notify.user1.uid);
|
||||
if(member){
|
||||
log("变动管理员获取成功")
|
||||
groupAdminNoticeEvent.user_id = parseInt(member.uin);
|
||||
groupAdminNoticeEvent.sub_type = notify.type == GroupNotifyTypes.ADMIN_UNSET ? "unset" : "set";
|
||||
postEvent(groupAdminNoticeEvent, true);
|
||||
}
|
||||
else{
|
||||
log("获取群通知的成员信息失败", notify, getGroup(notify.group.groupCode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch (e) {
|
||||
log("解析群通知失败", e.stack);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
let startTime = 0;
|
||||
async function start() {
|
||||
startTime = Date.now();
|
||||
startReceiveHook().then();
|
||||
NTQQApi.getGroups(true).then()
|
||||
const config = getConfigUtil().getConfig()
|
||||
if (config.ob11.enableHttp) {
|
||||
@@ -168,16 +216,17 @@ function onLoad() {
|
||||
log("http server start failed", e);
|
||||
}
|
||||
}
|
||||
if (config.ob11.enableWs){
|
||||
if (config.ob11.enableWs) {
|
||||
ob11WebsocketServer.start(config.ob11.wsPort);
|
||||
}
|
||||
if (config.ob11.enableWsReverse){
|
||||
if (config.ob11.enableWsReverse) {
|
||||
ob11ReverseWebsockets.start();
|
||||
}
|
||||
|
||||
log("LLOneBot start")
|
||||
}
|
||||
|
||||
let getSelfNickCount = 0;
|
||||
const init = async () => {
|
||||
try {
|
||||
const _ = await NTQQApi.getSelfInfo();
|
||||
@@ -194,7 +243,10 @@ function onLoad() {
|
||||
if (userInfo) {
|
||||
selfInfo.nick = userInfo.nick;
|
||||
} else {
|
||||
return setTimeout(init, 1000);
|
||||
getSelfNickCount++;
|
||||
if (getSelfNickCount < 10){
|
||||
return setTimeout(init, 1000);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log("get self nickname failed", e.toString());
|
||||
|
@@ -7,6 +7,7 @@ import {OB11GroupDecreaseEvent} from "../onebot11/event/notice/OB11GroupDecrease
|
||||
import {OB11GroupIncreaseEvent} from "../onebot11/event/notice/OB11GroupIncreaseEvent";
|
||||
import {v4 as uuidv4} from "uuid"
|
||||
import {postEvent} from "../onebot11/server/postevent";
|
||||
import {HOOK_LOG} from "../common/config";
|
||||
|
||||
export let hookApiCallbacks: Record<string, (apiReturn: any) => void> = {}
|
||||
|
||||
@@ -19,7 +20,8 @@ export enum ReceiveCmd {
|
||||
GROUPS_UNIX = "onGroupListUpdate",
|
||||
FRIENDS = "onBuddyListChange",
|
||||
MEDIA_DOWNLOAD_COMPLETE = "nodeIKernelMsgListener/onRichMediaDownloadComplete",
|
||||
UNREAD_GROUP_NOTICE = "nodeIKernelGroupListener/onGroupNotifiesUnreadCountUpdated"
|
||||
UNREAD_GROUP_NOTIFY = "nodeIKernelGroupListener/onGroupNotifiesUnreadCountUpdated",
|
||||
GROUP_NOTIFY = "nodeIKernelGroupListener/onGroupSingleScreenNotifies"
|
||||
}
|
||||
|
||||
interface NTQQApiReturnData<PayloadType = unknown> extends Array<any> {
|
||||
@@ -45,7 +47,7 @@ let receiveHooks: Array<{
|
||||
export function hookNTQQApiReceive(window: BrowserWindow) {
|
||||
const originalSend = window.webContents.send;
|
||||
const patchSend = (channel: string, ...args: NTQQApiReturnData) => {
|
||||
// log(`received ntqq api message: ${channel}`, JSON.stringify(args))
|
||||
HOOK_LOG && log(`received ntqq api message: ${channel}`, JSON.stringify(args))
|
||||
if (args?.[1] instanceof Array) {
|
||||
for (let receiveData of args?.[1]) {
|
||||
const ntQQApiMethodName = receiveData.cmdName;
|
||||
@@ -89,15 +91,15 @@ export function hookNTQQApiCall(window: BrowserWindow) {
|
||||
|
||||
const proxyIpcMsg = new Proxy(ipc_message_proxy, {
|
||||
apply(target, thisArg, args) {
|
||||
log("call NTQQ api", thisArg, args);
|
||||
HOOK_LOG && log("call NTQQ api", thisArg, args);
|
||||
return target.apply(thisArg, args);
|
||||
},
|
||||
});
|
||||
// if (webContents._events["-ipc-message"]?.[0]) {
|
||||
// webContents._events["-ipc-message"][0] = proxyIpcMsg;
|
||||
// } else {
|
||||
// webContents._events["-ipc-message"] = proxyIpcMsg;
|
||||
// }
|
||||
if (webContents._events["-ipc-message"]?.[0]) {
|
||||
webContents._events["-ipc-message"][0] = proxyIpcMsg;
|
||||
} else {
|
||||
webContents._events["-ipc-message"] = proxyIpcMsg;
|
||||
}
|
||||
}
|
||||
|
||||
export function registerReceiveHook<PayloadType>(method: ReceiveCmd, hookFunc: (payload: PayloadType) => void): string {
|
||||
@@ -253,9 +255,3 @@ registerReceiveHook<{ msgRecord: RawMessage }>(ReceiveCmd.SELF_SEND_MSG, ({msgRe
|
||||
}
|
||||
})
|
||||
|
||||
registerReceiveHook<{"doubt": boolean,"oldestUnreadSeq": string,"unreadCount": number}>(ReceiveCmd.UNREAD_GROUP_NOTICE, (payload)=>{
|
||||
log("收到群通知", payload);
|
||||
if (payload.unreadCount){
|
||||
|
||||
}
|
||||
})
|
@@ -1,7 +1,17 @@
|
||||
import {ipcMain} from "electron";
|
||||
import {hookApiCallbacks, ReceiveCmd, registerReceiveHook, removeReceiveHook} from "./hook";
|
||||
import {log} from "../common/utils";
|
||||
import {ChatType, Friend, Group, GroupMember, RawMessage, SelfInfo, SendMessageElement, User} from "./types";
|
||||
import {
|
||||
ChatType,
|
||||
Friend,
|
||||
Group,
|
||||
GroupMember,
|
||||
GroupNotify,
|
||||
RawMessage,
|
||||
SelfInfo,
|
||||
SendMessageElement,
|
||||
User
|
||||
} from "./types";
|
||||
import * as fs from "fs";
|
||||
import {addHistoryMsg, msgHistory, selfInfo} from "../common/data";
|
||||
import {v4 as uuidv4} from "uuid"
|
||||
@@ -42,7 +52,7 @@ export enum NTQQApiMethod {
|
||||
SEND_MSG = "nodeIKernelMsgService/sendMsg",
|
||||
DOWNLOAD_MEDIA = "nodeIKernelMsgService/downloadRichMedia",
|
||||
MULTI_FORWARD_MSG = "nodeIKernelMsgService/multiForwardMsgWithComment", // 合并转发
|
||||
GET_GROUP_NOTICE = "nodeIKernelGroupListener/onGroupSingleScreenNotifies",
|
||||
GET_GROUP_NOTICE = "nodeIKernelGroupService/getSingleScreenNotifies",
|
||||
}
|
||||
|
||||
enum NTQQApiChannel {
|
||||
@@ -63,7 +73,7 @@ enum CallBackType {
|
||||
}
|
||||
|
||||
interface NTQQApiParams {
|
||||
methodName: NTQQApiMethod,
|
||||
methodName: NTQQApiMethod | string,
|
||||
className?: NTQQApiClass,
|
||||
channel?: NTQQApiChannel,
|
||||
classNameIsRegister?: boolean
|
||||
@@ -77,7 +87,7 @@ function callNTQQApi<ReturnType>(params: NTQQApiParams) {
|
||||
let {
|
||||
className, methodName, channel, args,
|
||||
cbCmd, timeoutSecond: timeout,
|
||||
cmdCB
|
||||
classNameIsRegister, cmdCB
|
||||
} = params;
|
||||
className = className ?? NTQQApiClass.NT_API;
|
||||
channel = channel ?? NTQQApiChannel.IPC_UP_2;
|
||||
@@ -89,6 +99,11 @@ function callNTQQApi<ReturnType>(params: NTQQApiParams) {
|
||||
// log("callNTQQApiPromise", channel, className, methodName, args, uuid)
|
||||
const _timeout = timeout * 1000
|
||||
let success = false
|
||||
let eventName = className + "-" + channel[channel.length - 1];
|
||||
if (classNameIsRegister) {
|
||||
eventName += "-register";
|
||||
}
|
||||
const apiArgs = [methodName, ...args]
|
||||
if (!cbCmd) {
|
||||
// QQ后端会返回结果,并且可以插根据uuid识别
|
||||
hookApiCallbacks[uuid] = (r: ReturnType) => {
|
||||
@@ -123,12 +138,11 @@ function callNTQQApi<ReturnType>(params: NTQQApiParams) {
|
||||
setTimeout(() => {
|
||||
// log("ntqq api timeout", success, channel, className, methodName)
|
||||
if (!success) {
|
||||
log(`ntqq api timeout ${channel}, ${className}, ${methodName}`)
|
||||
reject(`ntqq api timeout ${channel}, ${className}, ${methodName}`)
|
||||
log(`ntqq api timeout ${channel}, ${eventName}, ${methodName}`, apiArgs);
|
||||
reject(`ntqq api timeout ${channel}, ${eventName}, ${methodName}, ${apiArgs}`)
|
||||
}
|
||||
}, _timeout)
|
||||
const eventName = className + "-" + channel[channel.length - 1];
|
||||
const apiArgs = [methodName, ...args]
|
||||
|
||||
ipcMain.emit(
|
||||
channel,
|
||||
{},
|
||||
@@ -242,6 +256,7 @@ export class NTQQApi {
|
||||
}
|
||||
// log(uidMaps);
|
||||
// log("members info", values);
|
||||
log(`get group ${groupQQ} members success`)
|
||||
return members
|
||||
} catch (e) {
|
||||
log(`get group ${groupQQ} members failed`, e)
|
||||
@@ -481,4 +496,21 @@ export class NTQQApi {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
static async getGroupNotifies() {
|
||||
// 获取管理员变更
|
||||
// 加群通知,退出通知,需要管理员权限
|
||||
await callNTQQApi<GeneralCallResult>({
|
||||
methodName: ReceiveCmd.GROUP_NOTIFY,
|
||||
classNameIsRegister: true,
|
||||
})
|
||||
return await callNTQQApi<GroupNotify>({
|
||||
methodName: NTQQApiMethod.GET_GROUP_NOTICE,
|
||||
cbCmd: ReceiveCmd.GROUP_NOTIFY,
|
||||
args:[
|
||||
{"doubt":false,"startSeq":"","number":14},
|
||||
null
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
@@ -241,3 +241,30 @@ export interface RawMessage {
|
||||
faceElement: FaceElement;
|
||||
}[];
|
||||
}
|
||||
|
||||
export enum GroupNotifyTypes{
|
||||
ADMIN_SET = 8,
|
||||
ADMIN_UNSET = 12
|
||||
}
|
||||
|
||||
export interface GroupNotify {
|
||||
doubt: boolean,
|
||||
nextStartSeq: string,
|
||||
notifies: [{
|
||||
seq: string, // 转成数字,再除以1000应该就是时间戳?
|
||||
type: GroupNotifyTypes,
|
||||
status: 0, // 未知
|
||||
group: { groupCode: string, groupName: string },
|
||||
user1: { uid: string, nickName: string }, // 被设置管理员的人
|
||||
user2: { uid: string, nickName: string }, // 操作者
|
||||
actionUser: { uid: string, nickName: string }, //未知
|
||||
actionTime: string,
|
||||
invitationExt: {
|
||||
srcType: number, // 0?未知
|
||||
groupCode: string, waitStatus: number
|
||||
},
|
||||
postscript: string,
|
||||
repeatSeqs: [],
|
||||
warningTips: string
|
||||
}]
|
||||
}
|
@@ -114,7 +114,7 @@ export class OB11Constructor {
|
||||
message_data["type"] = "reply"
|
||||
const replyMsg = getHistoryMsgBySeq(element.replyElement.replayMsgSeq)
|
||||
if (replyMsg) {
|
||||
message_data["data"]["id"] = replyMsg.msgShortId
|
||||
message_data["data"]["id"] = replyMsg.msgShortId.toString()
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import {OB11BaseNoticeEvent} from "./OB11BaseNoticeEvent";
|
||||
import {OB11GroupNoticeEvent} from "./OB11GroupNoticeEvent";
|
||||
|
||||
export class OB11GroupAdminNoticeEvent extends OB11BaseNoticeEvent {
|
||||
export class OB11GroupAdminNoticeEvent extends OB11GroupNoticeEvent {
|
||||
notice_type = "group_admin"
|
||||
sub_type: string // "set" | "unset"
|
||||
sub_type: "set" | "unset" // "set" | "unset"
|
||||
}
|
@@ -29,10 +29,10 @@ export function postWsEvent(event: PostEventType) {
|
||||
}
|
||||
}
|
||||
|
||||
export function postEvent(msg: PostEventType) {
|
||||
export function postEvent(msg: PostEventType, reportSelf=false) {
|
||||
const config = getConfigUtil().getConfig();
|
||||
// 判断msg是否是event
|
||||
if (!config.reportSelfMessage) {
|
||||
if (!config.reportSelfMessage && !reportSelf) {
|
||||
if ((msg as OB11Message).user_id.toString() == selfInfo.uin) {
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user