// 运行在 Electron 主进程 下的插件入口 import {BrowserWindow, ipcMain} from 'electron'; import fs from 'fs'; 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, getGroup, getGroupMember, groupNotifies, 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, GroupMember, GroupNotifies, 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 {OB11GroupAdminNoticeEvent} from "../onebot11/event/notice/OB11GroupAdminNoticeEvent"; import {OB11GroupDecreaseEvent} from "../onebot11/event/notice/OB11GroupDecreaseEvent"; import {OB11GroupRequestEvent} from "../onebot11/event/request/OB11GroupRequest"; let running = false; // 加载插件时触发 function onLoad() { log("llonebot main onLoad"); if (!fs.existsSync(CONFIG_DIR)) { fs.mkdirSync(CONFIG_DIR, {recursive: true}); } ipcMain.handle(CHANNEL_GET_CONFIG, (event: any, arg: any) => { return getConfigUtil().getConfig() }) ipcMain.on(CHANNEL_SET_CONFIG, (event: any, arg: Config) => { let oldConfig = getConfigUtil().getConfig(); getConfigUtil().setConfig(arg) if (arg.ob11.httpPort != oldConfig.ob11.httpPort && arg.ob11.enableHttp) { ob11HTTPServer.restart(arg.ob11.httpPort); } // 判断是否启用或关闭HTTP服务 if (!arg.ob11.enableHttp) { ob11HTTPServer.stop(); } else { ob11HTTPServer.start(arg.ob11.httpPort); } // 正向ws端口变化,重启服务 if (arg.ob11.wsPort != oldConfig.ob11.wsPort) { ob11WebsocketServer.restart(arg.ob11.wsPort); } // 判断是否启用或关闭正向ws if (arg.ob11.enableWs != oldConfig.ob11.enableWs) { if (arg.ob11.enableWs) { ob11WebsocketServer.start(arg.ob11.wsPort); } else { ob11WebsocketServer.stop(); } } // 判断是否启用或关闭反向ws if (arg.ob11.enableWsReverse != oldConfig.ob11.enableWsReverse) { if (arg.ob11.enableWsReverse) { ob11ReverseWebsockets.start(); } else { ob11ReverseWebsockets.stop(); } } if (arg.ob11.enableWsReverse) { // 判断反向ws地址有变化 if (arg.ob11.wsHosts.length != oldConfig.ob11.wsHosts.length) { ob11ReverseWebsockets.restart(); } else { for (const newHost of arg.ob11.wsHosts) { if (!oldConfig.ob11.wsHosts.includes(newHost)) { ob11ReverseWebsockets.restart(); break; } } } } }) ipcMain.on(CHANNEL_LOG, (event: any, arg: any) => { log(arg); }) function postReceiveMsg(msgList: RawMessage[]) { const {debug, reportSelfMessage} = getConfigUtil().getConfig(); for (let message of msgList) { // log("收到新消息", message) message.msgShortId = msgHistory[message.msgId]?.msgShortId if (!message.msgShortId) { addHistoryMsg(message); } OB11Constructor.message(message).then((msg) => { if (debug) { msg.raw = message; } const isSelfMsg = msg.user_id.toString() == selfInfo.uin if (isSelfMsg && !reportSelfMessage) { return } postEvent(msg); // log("post msg", msg) }).catch(e => log("constructMessage error: ", e.toString())); } } async function startReceiveHook() { registerReceiveHook<{ msgList: Array }>(ReceiveCmd.NEW_MSG, (payload) => { try { postReceiveMsg(payload.msgList); } catch (e) { log("report message error: ", e.toString()); } }) registerReceiveHook<{ msgList: Array }>(ReceiveCmd.UPDATE_MSG, async (payload) => { for (const message of payload.msgList) { // log("message update", message.sendStatus, message) if (message.recallTime != "0") { // 撤回消息上报 const oriMessage = msgHistory[message.msgId] if (!oriMessage) { continue } if (message.chatType == ChatType.friend) { const friendRecallEvent = new OB11FriendRecallNoticeEvent(parseInt(message.senderUin), oriMessage.msgShortId); postEvent(friendRecallEvent); } else if (message.chatType == ChatType.group) { let operatorId = message.senderUin for (const element of message.elements) { const operatorUid = element.grayTipElement?.revokeElement.operatorUid const operator = await getGroupMember(message.peerUin, null, operatorUid) operatorId = operator.uin } const groupRecallEvent = new OB11GroupRecallNoticeEvent( parseInt(message.peerUin), parseInt(message.senderUin), parseInt(operatorId), oriMessage.msgShortId ) postEvent(groupRecallEvent); } continue } addHistoryMsg(message) } }) registerReceiveHook<{ msgRecord: RawMessage }>(ReceiveCmd.SELF_SEND_MSG, (payload) => { const {reportSelfMessage} = getConfigUtil().getConfig(); if (!reportSelfMessage) { return } // log("reportSelfMessage", payload) try { postReceiveMsg([payload.msgRecord]); } catch (e) { 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: GroupNotifies; 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; } const member1 = await getGroupMember(notify.group.groupCode, null, notify.user1.uid); let member2: GroupMember; if (notify.user2.uid){ member2 = await getGroupMember(notify.group.groupCode, null, notify.user2.uid); } if ([GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET].includes(notify.type)) { log("有管理员变动通知"); let groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent() groupAdminNoticeEvent.group_id = parseInt(notify.group.groupCode); log("开始获取变动的管理员") if(member1){ log("变动管理员获取成功") groupAdminNoticeEvent.user_id = parseInt(member1.uin); groupAdminNoticeEvent.sub_type = notify.type == GroupNotifyTypes.ADMIN_UNSET ? "unset" : "set"; postEvent(groupAdminNoticeEvent, true); } else{ log("获取群通知的成员信息失败", notify, getGroup(notify.group.groupCode)); } } else if (notify.type == GroupNotifyTypes.MEMBER_EXIT){ log("有成员退出通知"); let groupDecreaseEvent = new OB11GroupDecreaseEvent(parseInt(notify.group.groupCode), parseInt(member1.uin)) // postEvent(groupDecreaseEvent, true); } else if ([GroupNotifyTypes.JOIN_REQUEST].includes(notify.type)){ log("有加群请求"); groupNotifies[notify.seq] = notify; let groupRequestEvent = new OB11GroupRequestEvent(); groupRequestEvent.group_id = parseInt(notify.group.groupCode); let requestQQ = "" try { requestQQ = (await NTQQApi.getUserInfo(notify.user1.uid)).uin; }catch (e) { log("获取加群人QQ号失败", e) } groupRequestEvent.user_id = parseInt(requestQQ) || 0; groupRequestEvent.sub_type = "add" groupRequestEvent.comment = notify.postscript; groupRequestEvent.flag = notify.seq; postEvent(groupRequestEvent); } } }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) { try { ob11HTTPServer.start(config.ob11.httpPort) } catch (e) { log("http server start failed", e); } } if (config.ob11.enableWs) { ob11WebsocketServer.start(config.ob11.wsPort); } if (config.ob11.enableWsReverse) { ob11ReverseWebsockets.start(); } log("LLOneBot start") } let getSelfNickCount = 0; const init = async () => { try { const _ = await NTQQApi.getSelfInfo(); Object.assign(selfInfo, _); selfInfo.nick = selfInfo.uin; log("get self simple info", _); } catch (e) { log("retry get self info"); } if (selfInfo.uin) { try { const userInfo = (await NTQQApi.getUserInfo(selfInfo.uid)); log("self info", userInfo); if (userInfo) { selfInfo.nick = userInfo.nick; } else { getSelfNickCount++; if (getSelfNickCount < 10){ return setTimeout(init, 1000); } } } catch (e) { log("get self nickname failed", e.toString()); return setTimeout(init, 1000); } start().then(); } else { setTimeout(init, 1000) } } setTimeout(init, 1000); } // 创建窗口时触发 function onBrowserWindowCreated(window: BrowserWindow) { try { hookNTQQApiCall(window); hookNTQQApiReceive(window); } catch (e) { log("LLOneBot hook error: ", e.toString()) } } try { onLoad(); } catch (e: any) { console.log(e.toString()) } // 这两个函数都是可选的 export { onBrowserWindowCreated }