Skip to content

Commit 9221cb9

Browse files
committed
模块化main进程
1 parent 0a891e2 commit 9221cb9

File tree

9 files changed

+267
-235
lines changed

9 files changed

+267
-235
lines changed

src/main.js

Lines changed: 39 additions & 235 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// 运行在 Electron 主进程 下的插件入口
22
const { ipcMain, dialog, shell } = require("electron");
3-
const http = require("http");
4-
const https = require("https");
53
const path = require("path");
64
const fs = require("fs");
75

@@ -10,180 +8,24 @@ const defaultConfig = require("./defaultConfig/defaultConfig.json"); // 默认
108
const defalutLocalEmoticonsConfig = require("./defaultConfig/defalutLocalEmoticonsConfig.json"); // 默认本地表情配置文件
119
let loadOptions = require("./main_modules/loadOptions");
1210
const { loadEmoticons, onUpdateEmoticons } = require("./main_modules/localEmoticons");
11+
const { LimitedMap } = require("./main_modules/LimitedMap");
12+
const { MessageRecallList } = require("./main_modules/MessageRecallList");
13+
const { globalBroadcast } = require("./main_modules/globalBroadcast");
14+
const { processPic } = require("./main_modules/processPic");
15+
const { replaceArk } = require("./main_modules/replaceArk");
16+
const { debounce } = require("./main_modules/debounce");
17+
const { log } = require("./main_modules/log");
1318

1419
let mainMessage, recordMessageRecallIdList, messageRecallPath, messageRecallJson;
1520

16-
let log = function (...args) {
17-
console.log(...args);
18-
};
19-
20-
// 自定义limitMap,在达到指定数量后清空最后一条记录
21-
class LimitedMap {
22-
constructor(limit) {
23-
this.limit = limit;
24-
this.map = new Map();
25-
this.keys = [];
26-
}
27-
set(key, value) {
28-
// 如果当前map存储消息超过指定大小,则删除最后一条数据
29-
if (this.map.size >= this.limit) {
30-
const oldestKey = this.keys.shift();
31-
this.map.delete(oldestKey);
32-
}
33-
this.map.set(key, value);
34-
this.keys.push(key);
35-
}
36-
get(key) {
37-
return this.map.get(key);
38-
}
39-
has(key) {
40-
return this.map.has(key);
41-
}
42-
delete(key) {
43-
const index = this.keys.indexOf(key);
44-
if (index !== -1) {
45-
this.keys.splice(index, 1);
46-
}
47-
this.map.delete(key);
48-
}
49-
}
50-
51-
// 撤回消息切片管理
52-
class MessageRecallList {
53-
constructor(messageRecallJson, messageRecallPath = false, limit = 0) {
54-
log(
55-
`新的历史记录实例,目标文件 ${path.basename(messageRecallJson)} 实例状态 ${
56-
messageRecallPath ? "读写" : "只读"
57-
} 切片大小 ${limit}`,
58-
);
59-
this.limit = limit;
60-
this.messageRecallPath = messageRecallPath;
61-
this.latestPath = messageRecallJson;
62-
this.newFileEvent = [];
63-
this.map = new Map(JSON.parse(fs.readFileSync(this.latestPath, { encoding: "utf-8" }))); // 从文件中初始化撤回信息
64-
}
65-
set(key, value) {
66-
if (this.messageRecallPath) {
67-
this.map.set(key, value);
68-
if (this.map.size >= this.limit) {
69-
log("缓存撤回消息超过阈值,开始切片");
70-
const newFileName = `${new Date().getTime()}.json`;
71-
fs.writeFileSync(path.join(this.messageRecallPath, newFileName), JSON.stringify(Array.from(this.map)));
72-
this.newFileEvent.forEach((callback) => callback(newFileName));
73-
this.map = new Map();
74-
}
75-
fs.writeFileSync(this.latestPath, JSON.stringify(Array.from(this.map)));
76-
} else {
77-
console.error("该实例工作在只读模式");
78-
}
79-
}
80-
// 如果产生新的切片文件,将会调用该方法传入的回调
81-
onNewFile(callback) {
82-
if (this.messageRecallPath) {
83-
this.newFileEvent.push(callback);
84-
} else {
85-
console.error("该实例工作在只读模式");
86-
}
87-
}
88-
get(key) {
89-
return this.map.get(key);
90-
}
91-
has(key) {
92-
return this.map.has(key);
93-
}
94-
delete(key) {
95-
if (this.messageRecallPath) {
96-
this.map.delete(key);
97-
} else {
98-
console.error("该实例工作在只读模式");
99-
}
100-
}
101-
}
102-
10321
const listenList = []; // 所有打开过的窗口对象
10422
const catchMsgList = new LimitedMap(2000); // 内存缓存消息记录-用于根据消息id获取撤回原始内容
10523
const messageRecallFileList = []; // 所有撤回消息本地切片列表
10624
let peer = null; // 激活聊天界面信息
10725
let historyMessageRecallList = new Map(); // 只读历史消息实例暂存数组
10826
let localEmoticonsList = []; // 本地表情包数据
109-
11027
let options, localEmoticonsConfig; // 配置数据
11128

112-
// 向所有未销毁页面发送广播
113-
function globalBroadcast(channel, data) {
114-
listenList.forEach((window) => {
115-
if (!window.isDestroyed()) {
116-
window.webContents.send(channel, data);
117-
}
118-
});
119-
}
120-
121-
// 下载被撤回的图片
122-
function processPic(msgItem) {
123-
msgItem?.elements?.forEach(async (el) => {
124-
if (el?.picElement) {
125-
log("该消息含有图片", el);
126-
const pic = el.picElement;
127-
const picName = pic.md5HexStr.toUpperCase();
128-
const picUrl = `https://gchat.qpic.cn/gchatpic_new/0/0-0-${picName}/`;
129-
if (!fs.existsSync(pic.sourcePath)) {
130-
log("下载原图", `${picUrl}0`);
131-
const body = await downloadPic(`${picUrl}0`);
132-
fs.mkdirSync(path.dirname(pic.sourcePath), { recursive: true });
133-
fs.writeFileSync(pic.sourcePath, body);
134-
}
135-
// 修复本地数据中的错误
136-
if (pic?.thumbPath && (pic.thumbPath instanceof Array || pic.thumbPath instanceof Object)) {
137-
pic.thumbPath = new Map([
138-
[0, pic.sourcePath.replace("Ori", "Thumb").replace(pic.md5HexStr, pic.md5HexStr + "_0")],
139-
[198, pic.sourcePath.replace("Ori", "Thumb").replace(pic.md5HexStr, pic.md5HexStr + "_198")],
140-
[720, pic.sourcePath.replace("Ori", "Thumb").replace(pic.md5HexStr, pic.md5HexStr + "_720")],
141-
]);
142-
}
143-
if (pic?.thumbPath && (pic.thumbPath instanceof Array || pic.thumbPath instanceof Map)) {
144-
pic.thumbPath.forEach(async (el, key) => {
145-
if (!fs.existsSync(el)) {
146-
log("下载缩略图", `${picUrl}${key}`);
147-
const body = await downloadPic(`${picUrl}${key}`);
148-
fs.mkdirSync(path.dirname(el), { recursive: true });
149-
fs.writeFileSync(el, body);
150-
}
151-
});
152-
}
153-
}
154-
});
155-
}
156-
157-
// 下载方法
158-
function downloadPic(url) {
159-
const protocolModule = url.startsWith("https") ? https : http;
160-
return new Promise((resolve, reject) => {
161-
function doRequest(url) {
162-
log("下载撤回消息中的图片", url);
163-
protocolModule.get(url, (response) => {
164-
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
165-
doRequest(response.headers.location);
166-
} else {
167-
const chunks = [];
168-
response.on("data", (chunk) => {
169-
chunks.push(chunk);
170-
});
171-
response.on("end", () => {
172-
const responseData = Buffer.concat(chunks);
173-
resolve(responseData); // 解析 Promise 并传递数据
174-
log("下载图片完成");
175-
});
176-
response.on("error", (err) => {
177-
log("下载图片失败", err);
178-
reject(err); // 解析 Promise 并传递错误
179-
});
180-
}
181-
});
182-
}
183-
doRequest(url);
184-
});
185-
}
186-
18729
// 加载插件时触发
18830
function onLoad(plugin) {
18931
const pluginDataPath = plugin.path.data;
@@ -250,7 +92,7 @@ function onLoad(plugin) {
25092
debounce(() => {
25193
const cssText = sass.compile(styleSassPath).css;
25294
fs.writeFileSync(stylePath, cssText);
253-
globalBroadcast("LiteLoader.lite_tools.updateStyle", cssText);
95+
globalBroadcast(listenList, "LiteLoader.lite_tools.updateStyle", cssText);
25496
}, 100),
25597
);
25698
// 监听并编译global.scss
@@ -260,7 +102,7 @@ function onLoad(plugin) {
260102
debounce(() => {
261103
const cssText = sass.compile(globalScssPath).css;
262104
fs.writeFileSync(globalPath, cssText);
263-
globalBroadcast("LiteLoader.lite_tools.updateGlobalStyle", cssText);
105+
globalBroadcast(listenList, "LiteLoader.lite_tools.updateGlobalStyle", cssText);
264106
}, 100),
265107
);
266108
// 监听并编译view.scss
@@ -270,7 +112,7 @@ function onLoad(plugin) {
270112
debounce(() => {
271113
const cssText = sass.compile(settingScssPath).css;
272114
fs.writeFileSync(settingPath, cssText);
273-
globalBroadcast("LiteLoader.lite_tools.updateSettingStyle");
115+
globalBroadcast(listenList, "LiteLoader.lite_tools.updateSettingStyle");
274116
}, 100),
275117
);
276118
} catch {
@@ -290,7 +132,13 @@ function onLoad(plugin) {
290132
// 监听本地表情包文件夹内的更新
291133
onUpdateEmoticons((emoticonsList) => {
292134
console.log("本地表情包更新", emoticonsList.length);
293-
globalBroadcast("LiteLoader.lite_tools.updateEmoticons", emoticonsList);
135+
if (options.localEmoticons.commonlyEmoticons) {
136+
emoticonsList.unshift({
137+
name: "常用表情",
138+
list: localEmoticonsConfig.commonlyEmoticons,
139+
});
140+
}
141+
globalBroadcast(listenList, "LiteLoader.lite_tools.updateEmoticons", emoticonsList);
294142
localEmoticonsList = emoticonsList;
295143
});
296144

@@ -348,7 +196,7 @@ function onLoad(plugin) {
348196
concat = options.textAreaFuncList.concat(list);
349197
options.textAreaFuncList = concat.filter((item) => !res.has(item["name"]) && res.set(item["name"], 1));
350198
fs.writeFileSync(settingsPath, JSON.stringify(options, null, 4));
351-
globalBroadcast("LiteLoader.lite_tools.updateOptions", options);
199+
globalBroadcast(listenList, "LiteLoader.lite_tools.updateOptions", options);
352200
});
353201

354202
// 更新聊天框上方功能列表
@@ -357,21 +205,22 @@ function onLoad(plugin) {
357205
concat = options.chatAreaFuncList.concat(list);
358206
options.chatAreaFuncList = concat.filter((item) => !res.has(item["name"]) && res.set(item["name"], 1));
359207
fs.writeFileSync(settingsPath, JSON.stringify(options, null, 4));
360-
globalBroadcast("LiteLoader.lite_tools.updateOptions", options);
208+
globalBroadcast(listenList, "LiteLoader.lite_tools.updateOptions", options);
361209
});
362210

363211
// 修改配置信息
364212
ipcMain.on("LiteLoader.lite_tools.setOptions", (event, opt) => {
365213
log("%c更新配置信息", "background:#1a5d1a;color:#fff;", opt);
366-
options = opt;
367-
fs.writeFileSync(settingsPath, JSON.stringify(options, null, 4));
368214
// 判断是否启用了本地表情包功能
369-
if (options.localEmoticons.enabled) {
370-
if (options.localEmoticons.localPath) {
371-
loadEmoticons(options.localEmoticons.localPath);
215+
if (opt.localEmoticons.enabled) {
216+
if (opt.localEmoticons.localPath && options.localEmoticons.localPath !== opt.localEmoticons.localPath) {
217+
resetCommonlyEmoticons(); // 重置常用表情
218+
loadEmoticons(opt.localEmoticons.localPath);
372219
}
373220
}
374-
globalBroadcast("LiteLoader.lite_tools.updateOptions", options);
221+
options = opt;
222+
fs.writeFileSync(settingsPath, JSON.stringify(options, null, 4));
223+
globalBroadcast(listenList, "LiteLoader.lite_tools.updateOptions", options);
375224
});
376225

377226
// 获取配置信息
@@ -436,7 +285,7 @@ function onLoad(plugin) {
436285
if (!result.canceled) {
437286
options.background.url = path.join(result.filePaths[0]).replace(/\\/g, "/");
438287
fs.writeFileSync(settingsPath, JSON.stringify(options, null, 4));
439-
globalBroadcast("LiteLoader.lite_tools.updateOptions", options);
288+
globalBroadcast(listenList, "LiteLoader.lite_tools.updateOptions", options);
440289
}
441290
})
442291
.catch((err) => {
@@ -455,15 +304,17 @@ function onLoad(plugin) {
455304
.then((result) => {
456305
console.log("选择了文件夹", result);
457306
if (!result.canceled) {
458-
options.localEmoticons.localPath = path.join(result.filePaths[0]).replace(/\\/g, "/");
459-
fs.writeFileSync(settingsPath, JSON.stringify(options, null, 4));
307+
const newPath = path.join(result.filePaths[0]).replace(/\\/g, "/");
460308
// 判断是否启用了本地表情包功能
461309
if (options.localEmoticons.enabled) {
462-
if (options.localEmoticons.localPath) {
463-
loadEmoticons(options.localEmoticons.localPath);
310+
if (newPath && options.localEmoticons.localPath !== newPath) {
311+
resetCommonlyEmoticons();
312+
loadEmoticons(newPath);
464313
}
465314
}
466-
globalBroadcast("LiteLoader.lite_tools.updateOptions", options);
315+
options.localEmoticons.localPath = newPath;
316+
fs.writeFileSync(settingsPath, JSON.stringify(options, null, 4));
317+
globalBroadcast(listenList, "LiteLoader.lite_tools.updateOptions", options);
467318
}
468319
})
469320
.catch((err) => {
@@ -761,7 +612,7 @@ function onBrowserWindowCreated(window, plugin) {
761612
origMsgSenderNick: msgItem.elements[0].grayTipElement.revokeElement.origMsgSenderNick, // 发送消息角色
762613
recallTime: msgItem.recallTime, // 撤回时间
763614
};
764-
globalBroadcast("LiteLoader.lite_tools.onMessageRecall", {
615+
globalBroadcast(listenList, "LiteLoader.lite_tools.onMessageRecall", {
765616
msgId: findInCatch.msgId,
766617
recallData,
767618
});
@@ -793,57 +644,10 @@ function onBrowserWindowCreated(window, plugin) {
793644
window.webContents.send = patched_send;
794645
}
795646

796-
// 卡片替换函数
797-
function replaceArk(json, msg_seq) {
798-
log("%c替换小程序卡片", "background:#fba1b7;color:#fff;", json);
799-
return JSON.stringify({
800-
app: "com.tencent.structmsg",
801-
config: json.config,
802-
desc: "新闻",
803-
extra: { app_type: 1, appid: json.meta.detail_1.appid, msg_seq, uin: json.meta.detail_1.host.uin },
804-
meta: {
805-
news: {
806-
action: "",
807-
android_pkg_name: "",
808-
app_type: 1,
809-
appid: json.meta.detail_1.appid,
810-
ctime: json.config.ctime,
811-
desc: json.meta.detail_1.desc,
812-
jumpUrl: json.meta.detail_1.qqdocurl.replace(/\\/g, ""),
813-
preview: json.meta.detail_1.preview,
814-
source_icon: json.meta.detail_1.icon,
815-
source_url: "",
816-
tag: getArkData(json),
817-
title: getArkData(json),
818-
uin: json.meta.detail_1.host.uin,
819-
},
820-
},
821-
prompt: `[分享]${getArkData(json)}`,
822-
ver: "0.0.0.1",
823-
view: "news",
824-
});
825-
}
826-
827-
// appid对应小程序名称
828-
const appidName = new Map([
829-
["1109224783", "微博"],
830-
["1109937557", "哔哩哔哩"],
831-
]);
832-
833-
// 获取ark卡片对应内容
834-
function getArkData(json) {
835-
return json.meta.detail_1.title || appidName.get(json.meta.detail_1.appid) || json.meta.detail_1.desc;
836-
}
837-
838-
// 防抖函数
839-
function debounce(fn, time) {
840-
let timer = null;
841-
return function (...args) {
842-
timer && clearTimeout(timer);
843-
timer = setTimeout(() => {
844-
fn.apply(this, args);
845-
}, time);
846-
};
647+
// 重置常用表情列表
648+
function resetCommonlyEmoticons() {
649+
localEmoticonsConfig.commonlyEmoticons = [];
650+
fs.writeFileSync(localEmoticonsPath, JSON.stringify(localEmoticonsConfig, null, 4));
847651
}
848652

849653
// 这两个函数都是可选的

0 commit comments

Comments
 (0)