From c3d4b4dec8e3ac72dc57e24b3579b979e7142b61 Mon Sep 17 00:00:00 2001 From: Hi Flysoft Date: Tue, 18 Jul 2023 23:47:16 +0800 Subject: [PATCH] release 1.0.0 --- src/config.ts | 14 +++--- src/main.ts | 110 +++++++++++++++++++++++++++++++++++++++++++++-- src/renderer.ts | 11 +---- src/settings.tsx | 57 ++++++++++++++++-------- src/utils/sep.ts | 1 + 5 files changed, 152 insertions(+), 41 deletions(-) create mode 100644 src/utils/sep.ts diff --git a/src/config.ts b/src/config.ts index b5e8fce..6ae8cdc 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,20 +1,18 @@ export const id = "no-revoked-message" as const; export const defaults: PluginConfig = { - switchConfigItem: false, - anotherSwitchConfigItem: false, - inputConfigItem: "默认值", - dropdownConfigItem: "A", + maxMessagesCount: 10000, + maxRevokedMessagesCount: 5000, + autoSaveDuration: 120, }; export function getPluginConfig(config: Config | undefined) { return Object.assign({}, defaults, config?.[id] || {}); } export interface PluginConfig { - switchConfigItem: boolean; - anotherSwitchConfigItem: boolean; - inputConfigItem: string; - dropdownConfigItem: "A" | "B" | "C"; + maxMessagesCount: 100 | 1000 | 5000 | 10000 | 20000 | 50000 | 100000; + maxRevokedMessagesCount: 100 | 1000 | 5000 | 10000 | 20000 | 50000 | 100000; + autoSaveDuration: 60 | 120 | 300; } export type Config = { [X in typeof id]?: Partial; diff --git a/src/main.ts b/src/main.ts index 5a1ec87..a480377 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,10 +1,112 @@ +import { env, interrupt } from "qqntim/main"; import { getPluginConfig } from "./config"; -import * as qqntim from "qqntim/main"; +import { randomUUID } from "crypto"; +import { app } from "electron"; +import { s } from "./utils/sep"; +import { modules } from "qqntim/main"; +const { fs } = modules; export default class Entry implements QQNTim.Entry.Main { + private messages = new Map(); + private revokedMessages = new Map(); + private changesRequested = false; constructor() { - const config = getPluginConfig(qqntim.env.config.plugins.config); - console.log("[Template] Hello world!", qqntim); - console.log("[Template] 当前插件配置:", config); + const config = getPluginConfig(env.config.plugins.config); + + interrupt.ipc( + (args) => { + args?.[1]?.[0]?.payload?.msgList?.forEach((msg) => { + const id = msg.msgId; + this.messages.set(id, msg); + if (this.messages.size > config.maxMessagesCount) + for (const [id] of this.messages.entries()) { + this.messages.delete(id); + break; + } + }); + }, + { eventName: "ns-ntApi", cmdName: "nodeIKernelMsgListener/onRecvMsg", direction: "out", type: "request" }, + ); + + interrupt.ipc( + (args) => { + if (args?.[1]?.[0]?.payload?.msgList) + args[1][0].payload.msgList = args[1][0].payload.msgList.map((msg) => { + const id = msg.msgId; + if (msg.elements[0]?.grayTipElement?.revokeElement && !msg.elements[0].grayTipElement.revokeElement.isSelfOperate) { + const storedMsg = this.messages.get(id); + this.revokedMessages.set(id, storedMsg); + if (this.revokedMessages.size > config.maxRevokedMessagesCount) + for (const [id] of this.revokedMessages.entries()) { + this.revokedMessages.delete(id); + break; + } + this.changesRequested = true; + return storedMsg; + } + return msg; + }); + }, + { eventName: "ns-ntApi", cmdName: "nodeIKernelMsgListener/onMsgInfoListUpdate", direction: "out", type: "request" }, + ); + + interrupt.ipc( + (args) => { + const processMsg = (msg) => { + const id = msg.msgId; + const storedMsg = this.revokedMessages.get(id); + if (storedMsg) + return { + ...storedMsg, + elements: [ + ...storedMsg.elements, + { + elementType: 1, + elementId: randomUUID(), + textElement: { + content: "\n(已被撤回)", + atType: 0, + atUid: "0", + atTinyId: "0", + atNtUid: "", + subElementType: 0, + atChannelId: "0", + }, + }, + ], + }; + return msg; + }; + if (args?.[1]?.[0]?.payload?.msgList) args[1][0].payload.msgList = args[1][0].payload.msgList.map(processMsg); + else if (args?.[1]?.msgList) args[1].msgList = args[1].msgList.map(processMsg); + }, + { eventName: "ns-ntApi", direction: "out" }, + ); + + const dataFile = `${env.path.dataDir}${s}revoked-messages.json`; + if (fs.existsSync(dataFile)) { + this.revokedMessages = new Map(fs.readJSONSync(dataFile)); + console.log(`[NoRevokedMessages] 已成功从 ${dataFile} 加载 ${this.revokedMessages.size} 条被撤回的消息`); + } + + const saveChanges = async () => { + if (!this.changesRequested) return; + this.changesRequested = false; + console.log(`[NoRevokedMessages] 正在保存撤回已消息数据到 ${dataFile}`); + await fs.writeJSON(dataFile, Array.from(this.revokedMessages)); + }; + const scheduleSaveChanges = () => { + setTimeout(async () => { + await saveChanges(); + scheduleSaveChanges(); + }, config.autoSaveDuration * 1000); + }; + scheduleSaveChanges(); + app.on("before-quit", (event) => { + if (this.changesRequested) { + event.preventDefault(); + saveChanges().then(() => app.quit()); + } + }); } } diff --git a/src/renderer.ts b/src/renderer.ts index 9bfc233..3c4544c 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -1,10 +1 @@ -import { getPluginConfig } from "./config"; -import * as qqntim from "qqntim/renderer"; - -export default class Entry implements QQNTim.Entry.Renderer { - constructor() { - const config = getPluginConfig(qqntim.env.config.plugins.config); - console.log("[Template] Hello world!", qqntim); - console.log("[Template] 当前插件配置:", config); - } -} +export default class Entry implements QQNTim.Entry.Renderer {} diff --git a/src/settings.tsx b/src/settings.tsx index 53cdab9..9159493 100644 --- a/src/settings.tsx +++ b/src/settings.tsx @@ -8,41 +8,60 @@ import { getPluginConfig } from "./config"; export default class Entry implements QQNTim.Entry.Renderer { constructor() { // 如果不需要设置界面,将下一行注释掉即可;如果需要在设置项目旁边加一个小图标,请将 `undefined` 改为一段 HTML 代码(可以是 ``, `` 等等)。 - defineSettingsPanels(["模板插件设置", SettingsPanel, undefined]); + defineSettingsPanels(["防撤回插件", SettingsPanel, undefined]); } } function SettingsPanel({ config: _config, setConfig: _setConfig }: QQNTim.Settings.PanelProps) { const [pluginConfig, setPluginConfig] = usePluginConfig(_config, _setConfig); - const currentPluginConfigString = useMemo(() => JSON.stringify(getPluginConfig(env.config.plugins.config)), []); return ( <> - - - setPluginConfig("switchConfigItem", state)} /> + + setPluginConfig("maxMessagesCount", state)} + width="200px" + /> - {pluginConfig.switchConfigItem && ( - - setPluginConfig("anotherSwitchConfigItem", state)} /> - - )} - + setPluginConfig("dropdownConfigItem", state)} - width="150px" + selected={pluginConfig.maxRevokedMessagesCount} + onChange={(state) => setPluginConfig("maxRevokedMessagesCount", state)} + width="200px" /> - - setPluginConfig("inputConfigItem", state)} /> + + setPluginConfig("autoSaveDuration", state)} + width="200px" + /> diff --git a/src/utils/sep.ts b/src/utils/sep.ts new file mode 100644 index 0000000..cefd995 --- /dev/null +++ b/src/utils/sep.ts @@ -0,0 +1 @@ +export { sep as s } from "path";