llonebot-dist 7.7.0 → 7.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/{index-B1KgxRHW.js → index-BvqM9dZ0.js} +5 -4
- package/assets/index-BvqM9dZ0.js.map +1 -0
- package/llbot.js +154 -295
- package/llbot.js.map +1 -1
- package/package.json +1 -1
- package/webui/assets/index-BX4zaWLx.css +1 -0
- package/webui/assets/{index-BxCgLb8I.js → index-D7CRayio.js} +15 -15
- package/webui/index.html +2 -2
- package//346/233/264/346/226/260/346/227/245/345/277/227.txt +6 -0
- package/assets/index-B1KgxRHW.js.map +0 -1
- package/webui/assets/index-BDa9Tzq8.css +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { M as Msg } from "../llbot.js";
|
|
2
|
+
import { A, a, N, O } from "../llbot.js";
|
|
2
3
|
import "node:path";
|
|
3
4
|
import "node:url";
|
|
4
5
|
import "cosmokit";
|
|
@@ -43,9 +44,9 @@ import "dns";
|
|
|
43
44
|
import "tls";
|
|
44
45
|
export {
|
|
45
46
|
A as Action,
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
a as Media,
|
|
48
|
+
Msg,
|
|
48
49
|
N as Notify,
|
|
49
50
|
O as Oidb
|
|
50
51
|
};
|
|
51
|
-
//# sourceMappingURL=index-
|
|
52
|
+
//# sourceMappingURL=index-BvqM9dZ0.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BvqM9dZ0.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/llbot.js
CHANGED
|
@@ -2127,6 +2127,11 @@ class PMHQBase {
|
|
|
2127
2127
|
wsUrl = "ws://127.0.0.1:13000/ws";
|
|
2128
2128
|
ws;
|
|
2129
2129
|
resListeners = /* @__PURE__ */ new Map();
|
|
2130
|
+
disconnectCallbacks = /* @__PURE__ */ new Map();
|
|
2131
|
+
lastConnectedTime = Date.now();
|
|
2132
|
+
disconnectCheckTimer;
|
|
2133
|
+
hasConnectedOnce = false;
|
|
2134
|
+
hasLoggedConnectionError = false;
|
|
2130
2135
|
constructor() {
|
|
2131
2136
|
console.log(process.argv);
|
|
2132
2137
|
const { pmhqHost, pmhqPort } = this.getPMHQHostPort();
|
|
@@ -2137,6 +2142,41 @@ class PMHQBase {
|
|
|
2137
2142
|
get_is_connected() {
|
|
2138
2143
|
return this.ws && this.ws.readyState === WebSocket.OPEN;
|
|
2139
2144
|
}
|
|
2145
|
+
onDisconnect(timeout2, callback) {
|
|
2146
|
+
const id2 = randomUUID();
|
|
2147
|
+
this.disconnectCallbacks.set(id2, { timeout: timeout2, callback, triggered: false });
|
|
2148
|
+
console.info(`[PMHQ] Registered disconnect callback ${id2} with timeout ${timeout2}ms`);
|
|
2149
|
+
return id2;
|
|
2150
|
+
}
|
|
2151
|
+
offDisconnect(id2) {
|
|
2152
|
+
this.disconnectCallbacks.delete(id2);
|
|
2153
|
+
}
|
|
2154
|
+
startDisconnectMonitoring() {
|
|
2155
|
+
if (this.disconnectCheckTimer) return;
|
|
2156
|
+
console.info("[PMHQ] Starting disconnect monitoring");
|
|
2157
|
+
this.disconnectCheckTimer = setInterval(() => {
|
|
2158
|
+
const isConnected = this.get_is_connected();
|
|
2159
|
+
if (isConnected) {
|
|
2160
|
+
this.lastConnectedTime = Date.now();
|
|
2161
|
+
for (const info of this.disconnectCallbacks.values()) {
|
|
2162
|
+
info.triggered = false;
|
|
2163
|
+
}
|
|
2164
|
+
} else {
|
|
2165
|
+
const disconnectedDuration = Date.now() - this.lastConnectedTime;
|
|
2166
|
+
for (const info of this.disconnectCallbacks.values()) {
|
|
2167
|
+
if (!info.triggered && disconnectedDuration >= info.timeout) {
|
|
2168
|
+
info.triggered = true;
|
|
2169
|
+
console.warn(`[PMHQ] Triggering disconnect callback, duration: ${disconnectedDuration}ms, timeout: ${info.timeout}ms`);
|
|
2170
|
+
try {
|
|
2171
|
+
info.callback(disconnectedDuration);
|
|
2172
|
+
} catch (e) {
|
|
2173
|
+
console.error("PMHQ disconnect callback error", e);
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
}, 5e3);
|
|
2179
|
+
}
|
|
2140
2180
|
getPMHQHostPort() {
|
|
2141
2181
|
let pmhqPort = "13000";
|
|
2142
2182
|
let pmhqHost = "127.0.0.1";
|
|
@@ -2194,16 +2234,27 @@ class PMHQBase {
|
|
|
2194
2234
|
};
|
|
2195
2235
|
this.ws.onerror = () => {
|
|
2196
2236
|
selfInfo.online = false;
|
|
2197
|
-
|
|
2237
|
+
if (!this.hasLoggedConnectionError) {
|
|
2238
|
+
console.error("PMHQ WebSocket 连接错误,可能 QQ 未启动,正在等待 QQ 启动进行重连...");
|
|
2239
|
+
this.hasLoggedConnectionError = true;
|
|
2240
|
+
}
|
|
2198
2241
|
reconnect();
|
|
2199
2242
|
};
|
|
2200
2243
|
this.ws.onclose = () => {
|
|
2201
2244
|
selfInfo.online = false;
|
|
2202
|
-
|
|
2245
|
+
if (!this.hasLoggedConnectionError) {
|
|
2246
|
+
console.info("PMHQ WebSocket 连接关闭,准备重连...");
|
|
2247
|
+
this.hasLoggedConnectionError = true;
|
|
2248
|
+
}
|
|
2203
2249
|
reconnect();
|
|
2204
2250
|
};
|
|
2205
2251
|
this.ws.onopen = () => {
|
|
2206
2252
|
console.info("PMHQ WebSocket 连接成功");
|
|
2253
|
+
this.hasLoggedConnectionError = false;
|
|
2254
|
+
if (!this.hasConnectedOnce) {
|
|
2255
|
+
this.hasConnectedOnce = true;
|
|
2256
|
+
this.startDisconnectMonitoring();
|
|
2257
|
+
}
|
|
2207
2258
|
};
|
|
2208
2259
|
}
|
|
2209
2260
|
async call(func, args, timeout2 = 1e4) {
|
|
@@ -10613,7 +10664,7 @@ class OB11HeartbeatEvent extends OB11BaseMetaEvent {
|
|
|
10613
10664
|
};
|
|
10614
10665
|
}
|
|
10615
10666
|
}
|
|
10616
|
-
const version$3 = "7.7.
|
|
10667
|
+
const version$3 = "7.7.1";
|
|
10617
10668
|
class OB11WebSocket {
|
|
10618
10669
|
constructor(ctx, config2) {
|
|
10619
10670
|
this.ctx = ctx;
|
|
@@ -70059,11 +70110,11 @@ function createEmailRoutes(ctx) {
|
|
|
70059
70110
|
const router2 = expressExports.Router();
|
|
70060
70111
|
router2.get("/config", async (_req, res) => {
|
|
70061
70112
|
try {
|
|
70062
|
-
|
|
70063
|
-
|
|
70064
|
-
res.status(500).json({ success: false, message: "邮件服务未初始化" });
|
|
70113
|
+
if (!ctx.emailNotification) {
|
|
70114
|
+
res.status(503).json({ success: false, message: "邮件服务未初始化,请等待登录完成" });
|
|
70065
70115
|
return;
|
|
70066
70116
|
}
|
|
70117
|
+
const emailService = ctx.emailNotification;
|
|
70067
70118
|
const config2 = emailService.getConfigManager().getConfig();
|
|
70068
70119
|
const maskedConfig = {
|
|
70069
70120
|
...config2,
|
|
@@ -70089,11 +70140,11 @@ function createEmailRoutes(ctx) {
|
|
|
70089
70140
|
});
|
|
70090
70141
|
router2.post("/config", async (req, res) => {
|
|
70091
70142
|
try {
|
|
70092
|
-
|
|
70093
|
-
|
|
70094
|
-
res.status(500).json({ success: false, message: "邮件服务未初始化" });
|
|
70143
|
+
if (!ctx.emailNotification) {
|
|
70144
|
+
res.status(503).json({ success: false, message: "邮件服务未初始化,请等待登录完成" });
|
|
70095
70145
|
return;
|
|
70096
70146
|
}
|
|
70147
|
+
const emailService = ctx.emailNotification;
|
|
70097
70148
|
const emailConfig = req.body;
|
|
70098
70149
|
if (!emailConfig) {
|
|
70099
70150
|
res.status(400).json({
|
|
@@ -70131,15 +70182,19 @@ function createEmailRoutes(ctx) {
|
|
|
70131
70182
|
});
|
|
70132
70183
|
router2.post("/test", async (req, res) => {
|
|
70133
70184
|
try {
|
|
70134
|
-
|
|
70135
|
-
|
|
70136
|
-
res.status(500).json({ success: false, message: "邮件服务未初始化" });
|
|
70185
|
+
if (!ctx.emailNotification) {
|
|
70186
|
+
res.status(503).json({ success: false, message: "邮件服务未初始化,请等待登录完成" });
|
|
70137
70187
|
return;
|
|
70138
70188
|
}
|
|
70189
|
+
const emailService = ctx.emailNotification;
|
|
70139
70190
|
const { config: testConfig } = req.body;
|
|
70140
70191
|
let emailConfig;
|
|
70141
70192
|
if (testConfig) {
|
|
70142
70193
|
emailConfig = testConfig;
|
|
70194
|
+
const currentConfig = emailService.getConfigManager().getConfig();
|
|
70195
|
+
if (emailConfig.smtp.auth.pass === "********" || emailConfig.smtp.auth.pass === "") {
|
|
70196
|
+
emailConfig.smtp.auth.pass = currentConfig.smtp.auth.pass;
|
|
70197
|
+
}
|
|
70143
70198
|
} else {
|
|
70144
70199
|
emailConfig = emailService.getConfigManager().getConfig();
|
|
70145
70200
|
}
|
|
@@ -70211,7 +70266,10 @@ class WebUIServer extends Service2 {
|
|
|
70211
70266
|
upload;
|
|
70212
70267
|
fileUpload;
|
|
70213
70268
|
uploadDir;
|
|
70214
|
-
static inject =
|
|
70269
|
+
static inject = {
|
|
70270
|
+
required: ["ntLoginApi", "ntFriendApi", "ntGroupApi", "ntSystemApi", "ntMsgApi", "ntUserApi", "ntFileApi"],
|
|
70271
|
+
optional: ["emailNotification"]
|
|
70272
|
+
};
|
|
70215
70273
|
createImageUpload() {
|
|
70216
70274
|
return multer({
|
|
70217
70275
|
storage: multer.diskStorage({
|
|
@@ -70340,7 +70398,7 @@ data: ${JSON.stringify(serializedData)}
|
|
|
70340
70398
|
if (data.type !== "recv" || data.data.cmd !== "trpc.msg.olpush.OlPushService.MsgPush") return;
|
|
70341
70399
|
try {
|
|
70342
70400
|
const { Msg: Msg2 } = await __vitePreload(async () => {
|
|
70343
|
-
const { Msg: Msg3 } = await import("./assets/index-
|
|
70401
|
+
const { Msg: Msg3 } = await import("./assets/index-BvqM9dZ0.js");
|
|
70344
70402
|
return { Msg: Msg3 };
|
|
70345
70403
|
}, true ? [] : void 0);
|
|
70346
70404
|
const pushMsg = Msg2.PushMsg.decode(Buffer.from(data.data.pb, "hex"));
|
|
@@ -81639,305 +81697,91 @@ class EmailService {
|
|
|
81639
81697
|
}
|
|
81640
81698
|
formatOfflineEmail(botInfo, reason) {
|
|
81641
81699
|
const timestamp = botInfo.timestamp.toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
81642
|
-
const
|
|
81643
|
-
const subject =
|
|
81700
|
+
const displayName = botInfo.nick ? `${botInfo.nick} (${botInfo.uin})` : botInfo.uin;
|
|
81701
|
+
const subject = "LLBot 掉线通知";
|
|
81702
|
+
const reasonSection = reason ? `<div class="info">
|
|
81703
|
+
<p><strong>掉线原因:</strong> ${reason}</p>
|
|
81704
|
+
</div>` : `<p>可能的原因:</p>
|
|
81705
|
+
<ul>
|
|
81706
|
+
<li>网络连接中断</li>
|
|
81707
|
+
<li>QQ 被强制下线</li>
|
|
81708
|
+
<li>程序异常退出</li>
|
|
81709
|
+
</ul>`;
|
|
81644
81710
|
const html = `
|
|
81645
81711
|
<!DOCTYPE html>
|
|
81646
81712
|
<html>
|
|
81647
81713
|
<head>
|
|
81648
|
-
|
|
81649
|
-
|
|
81650
|
-
|
|
81651
|
-
|
|
81652
|
-
|
|
81653
|
-
|
|
81654
|
-
|
|
81655
|
-
|
|
81656
|
-
|
|
81657
|
-
|
|
81658
|
-
.container {
|
|
81659
|
-
max-width: 600px;
|
|
81660
|
-
margin: 0 auto;
|
|
81661
|
-
background: white;
|
|
81662
|
-
border-radius: 20px;
|
|
81663
|
-
overflow: hidden;
|
|
81664
|
-
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
81665
|
-
}
|
|
81666
|
-
.header {
|
|
81667
|
-
background: linear-gradient(135deg, #ef4444 0%, #ec4899 100%);
|
|
81668
|
-
color: white;
|
|
81669
|
-
padding: 40px 32px;
|
|
81670
|
-
text-align: center;
|
|
81671
|
-
position: relative;
|
|
81672
|
-
}
|
|
81673
|
-
.header::before {
|
|
81674
|
-
content: '';
|
|
81675
|
-
position: absolute;
|
|
81676
|
-
top: 0;
|
|
81677
|
-
left: 0;
|
|
81678
|
-
right: 0;
|
|
81679
|
-
bottom: 0;
|
|
81680
|
-
background: radial-gradient(circle at 30% 50%, rgba(255,255,255,0.1) 0%, transparent 50%);
|
|
81681
|
-
}
|
|
81682
|
-
.header-content {
|
|
81683
|
-
position: relative;
|
|
81684
|
-
z-index: 1;
|
|
81685
|
-
}
|
|
81686
|
-
.icon {
|
|
81687
|
-
font-size: 56px;
|
|
81688
|
-
margin-bottom: 16px;
|
|
81689
|
-
filter: drop-shadow(0 4px 6px rgba(0,0,0,0.1));
|
|
81690
|
-
}
|
|
81691
|
-
.header h2 {
|
|
81692
|
-
font-size: 28px;
|
|
81693
|
-
font-weight: 700;
|
|
81694
|
-
margin-bottom: 8px;
|
|
81695
|
-
letter-spacing: -0.5px;
|
|
81696
|
-
}
|
|
81697
|
-
.header p {
|
|
81698
|
-
font-size: 15px;
|
|
81699
|
-
opacity: 0.95;
|
|
81700
|
-
font-weight: 500;
|
|
81701
|
-
}
|
|
81702
|
-
.content {
|
|
81703
|
-
padding: 36px 32px;
|
|
81704
|
-
}
|
|
81705
|
-
.info-card {
|
|
81706
|
-
background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
|
|
81707
|
-
border-radius: 16px;
|
|
81708
|
-
padding: 24px;
|
|
81709
|
-
margin-bottom: 24px;
|
|
81710
|
-
border: 1px solid rgba(0,0,0,0.05);
|
|
81711
|
-
}
|
|
81712
|
-
.info-item {
|
|
81713
|
-
margin: 14px 0;
|
|
81714
|
-
display: flex;
|
|
81715
|
-
align-items: flex-start;
|
|
81716
|
-
padding: 8px 0;
|
|
81717
|
-
}
|
|
81718
|
-
.info-item:not(:last-child) {
|
|
81719
|
-
border-bottom: 1px solid rgba(0,0,0,0.06);
|
|
81720
|
-
}
|
|
81721
|
-
.label {
|
|
81722
|
-
font-weight: 600;
|
|
81723
|
-
color: #374151;
|
|
81724
|
-
min-width: 90px;
|
|
81725
|
-
flex-shrink: 0;
|
|
81726
|
-
font-size: 14px;
|
|
81727
|
-
}
|
|
81728
|
-
.value {
|
|
81729
|
-
color: #6b7280;
|
|
81730
|
-
flex: 1;
|
|
81731
|
-
font-size: 14px;
|
|
81732
|
-
word-break: break-word;
|
|
81733
|
-
}
|
|
81734
|
-
.alert-message {
|
|
81735
|
-
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
|
|
81736
|
-
border-left: 4px solid #f59e0b;
|
|
81737
|
-
padding: 18px 20px;
|
|
81738
|
-
border-radius: 12px;
|
|
81739
|
-
color: #92400e;
|
|
81740
|
-
font-size: 14px;
|
|
81741
|
-
line-height: 1.6;
|
|
81742
|
-
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
81743
|
-
}
|
|
81744
|
-
.footer {
|
|
81745
|
-
text-align: center;
|
|
81746
|
-
padding: 28px 24px;
|
|
81747
|
-
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
|
|
81748
|
-
color: #9ca3af;
|
|
81749
|
-
font-size: 13px;
|
|
81750
|
-
border-top: 1px solid rgba(0,0,0,0.05);
|
|
81751
|
-
}
|
|
81752
|
-
.footer strong {
|
|
81753
|
-
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
|
81754
|
-
-webkit-background-clip: text;
|
|
81755
|
-
-webkit-text-fill-color: transparent;
|
|
81756
|
-
background-clip: text;
|
|
81757
|
-
font-weight: 600;
|
|
81758
|
-
}
|
|
81759
|
-
</style>
|
|
81714
|
+
<meta charset="utf-8">
|
|
81715
|
+
<style>
|
|
81716
|
+
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
|
81717
|
+
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
|
81718
|
+
.header { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; padding: 20px; border-radius: 8px 8px 0 0; }
|
|
81719
|
+
.content { background: #f9f9f9; padding: 20px; border-radius: 0 0 8px 8px; }
|
|
81720
|
+
.alert { background: #fff3cd; border-left: 4px solid #ffc107; padding: 15px; margin: 10px 0; }
|
|
81721
|
+
.info { background: white; padding: 15px; margin: 10px 0; }
|
|
81722
|
+
.footer { text-align: center; margin-top: 20px; color: #666; font-size: 12px; }
|
|
81723
|
+
</style>
|
|
81760
81724
|
</head>
|
|
81761
81725
|
<body>
|
|
81762
|
-
|
|
81763
|
-
|
|
81764
|
-
|
|
81765
|
-
<div class="icon">⚠️</div>
|
|
81766
|
-
<h2>机器人离线告警</h2>
|
|
81767
|
-
<p>您的 LLBot 实例已离线</p>
|
|
81768
|
-
</div>
|
|
81769
|
-
</div>
|
|
81770
|
-
<div class="content">
|
|
81771
|
-
<div class="info-card">
|
|
81772
|
-
<div class="info-item">
|
|
81773
|
-
<span class="label">机器人账号</span>
|
|
81774
|
-
<span class="value">${botInfo.uin} (${botInfo.nick})</span>
|
|
81726
|
+
<div class="container">
|
|
81727
|
+
<div class="header">
|
|
81728
|
+
<h2>⚠️ LLBot 掉线通知</h2>
|
|
81775
81729
|
</div>
|
|
81776
|
-
<div class="
|
|
81777
|
-
|
|
81778
|
-
|
|
81730
|
+
<div class="content">
|
|
81731
|
+
<div class="alert">
|
|
81732
|
+
<p><strong>⚠️ QQ 已掉线</strong></p>
|
|
81733
|
+
</div>
|
|
81734
|
+
<div class="info">
|
|
81735
|
+
<p><strong>账号信息:</strong> ${displayName}</p>
|
|
81736
|
+
<p><strong>掉线时间:</strong> ${timestamp}</p>
|
|
81737
|
+
</div>
|
|
81738
|
+
<p>您的 QQ 机器人已掉线,请及时检查并重新登录。</p>
|
|
81739
|
+
${reasonSection}
|
|
81779
81740
|
</div>
|
|
81780
|
-
<div class="
|
|
81781
|
-
|
|
81782
|
-
<span class="value">${reasonText}</span>
|
|
81741
|
+
<div class="footer">
|
|
81742
|
+
<p>此邮件由 LLBot 自动发送,请勿回复</p>
|
|
81783
81743
|
</div>
|
|
81784
|
-
</div>
|
|
81785
|
-
<div class="alert-message">
|
|
81786
|
-
💡 请检查机器人状态和日志以获取更多信息,确保服务正常运行。
|
|
81787
|
-
</div>
|
|
81788
|
-
</div>
|
|
81789
|
-
<div class="footer">
|
|
81790
|
-
Powered by <strong>LLBot</strong> · Lucky Lillia Bot
|
|
81791
81744
|
</div>
|
|
81792
|
-
</div>
|
|
81793
81745
|
</body>
|
|
81794
81746
|
</html>
|
|
81795
81747
|
`.trim();
|
|
81796
81748
|
return { subject, html };
|
|
81797
81749
|
}
|
|
81798
81750
|
formatTestEmail(timestamp) {
|
|
81799
|
-
const subject = "
|
|
81751
|
+
const subject = "LLBot 邮件通知测试";
|
|
81800
81752
|
const html = `
|
|
81801
81753
|
<!DOCTYPE html>
|
|
81802
81754
|
<html>
|
|
81803
81755
|
<head>
|
|
81804
|
-
|
|
81805
|
-
|
|
81806
|
-
|
|
81807
|
-
|
|
81808
|
-
|
|
81809
|
-
|
|
81810
|
-
|
|
81811
|
-
|
|
81812
|
-
|
|
81813
|
-
}
|
|
81814
|
-
.container {
|
|
81815
|
-
max-width: 600px;
|
|
81816
|
-
margin: 0 auto;
|
|
81817
|
-
background: white;
|
|
81818
|
-
border-radius: 20px;
|
|
81819
|
-
overflow: hidden;
|
|
81820
|
-
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
81821
|
-
}
|
|
81822
|
-
.header {
|
|
81823
|
-
background: linear-gradient(135deg, #10b981 0%, #14b8a6 100%);
|
|
81824
|
-
color: white;
|
|
81825
|
-
padding: 40px 32px;
|
|
81826
|
-
text-align: center;
|
|
81827
|
-
position: relative;
|
|
81828
|
-
}
|
|
81829
|
-
.header::before {
|
|
81830
|
-
content: '';
|
|
81831
|
-
position: absolute;
|
|
81832
|
-
top: 0;
|
|
81833
|
-
left: 0;
|
|
81834
|
-
right: 0;
|
|
81835
|
-
bottom: 0;
|
|
81836
|
-
background: radial-gradient(circle at 30% 50%, rgba(255,255,255,0.1) 0%, transparent 50%);
|
|
81837
|
-
}
|
|
81838
|
-
.header-content {
|
|
81839
|
-
position: relative;
|
|
81840
|
-
z-index: 1;
|
|
81841
|
-
}
|
|
81842
|
-
.icon {
|
|
81843
|
-
font-size: 56px;
|
|
81844
|
-
margin-bottom: 16px;
|
|
81845
|
-
filter: drop-shadow(0 4px 6px rgba(0,0,0,0.1));
|
|
81846
|
-
}
|
|
81847
|
-
.header h2 {
|
|
81848
|
-
font-size: 28px;
|
|
81849
|
-
font-weight: 700;
|
|
81850
|
-
margin-bottom: 8px;
|
|
81851
|
-
letter-spacing: -0.5px;
|
|
81852
|
-
}
|
|
81853
|
-
.header p {
|
|
81854
|
-
font-size: 15px;
|
|
81855
|
-
opacity: 0.95;
|
|
81856
|
-
font-weight: 500;
|
|
81857
|
-
}
|
|
81858
|
-
.content {
|
|
81859
|
-
padding: 36px 32px;
|
|
81860
|
-
}
|
|
81861
|
-
.success-card {
|
|
81862
|
-
background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
|
|
81863
|
-
border-radius: 16px;
|
|
81864
|
-
padding: 28px;
|
|
81865
|
-
margin-bottom: 24px;
|
|
81866
|
-
text-align: center;
|
|
81867
|
-
border: 1px solid rgba(16, 185, 129, 0.2);
|
|
81868
|
-
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
81869
|
-
}
|
|
81870
|
-
.success-card p {
|
|
81871
|
-
color: #065f46;
|
|
81872
|
-
font-size: 17px;
|
|
81873
|
-
margin: 10px 0;
|
|
81874
|
-
font-weight: 500;
|
|
81875
|
-
}
|
|
81876
|
-
.success-card .subtitle {
|
|
81877
|
-
font-size: 14px;
|
|
81878
|
-
margin-top: 12px;
|
|
81879
|
-
opacity: 0.8;
|
|
81880
|
-
font-weight: 400;
|
|
81881
|
-
}
|
|
81882
|
-
.info-box {
|
|
81883
|
-
background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
|
|
81884
|
-
border-radius: 12px;
|
|
81885
|
-
padding: 20px;
|
|
81886
|
-
margin-top: 24px;
|
|
81887
|
-
border: 1px solid rgba(0,0,0,0.05);
|
|
81888
|
-
}
|
|
81889
|
-
.info-box .label {
|
|
81890
|
-
font-weight: 600;
|
|
81891
|
-
color: #374151;
|
|
81892
|
-
margin-bottom: 6px;
|
|
81893
|
-
font-size: 13px;
|
|
81894
|
-
text-transform: uppercase;
|
|
81895
|
-
letter-spacing: 0.5px;
|
|
81896
|
-
}
|
|
81897
|
-
.info-box .value {
|
|
81898
|
-
color: #6b7280;
|
|
81899
|
-
font-size: 15px;
|
|
81900
|
-
}
|
|
81901
|
-
.footer {
|
|
81902
|
-
text-align: center;
|
|
81903
|
-
padding: 28px 24px;
|
|
81904
|
-
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
|
|
81905
|
-
color: #9ca3af;
|
|
81906
|
-
font-size: 13px;
|
|
81907
|
-
border-top: 1px solid rgba(0,0,0,0.05);
|
|
81908
|
-
}
|
|
81909
|
-
.footer strong {
|
|
81910
|
-
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
|
81911
|
-
-webkit-background-clip: text;
|
|
81912
|
-
-webkit-text-fill-color: transparent;
|
|
81913
|
-
background-clip: text;
|
|
81914
|
-
font-weight: 600;
|
|
81915
|
-
}
|
|
81916
|
-
</style>
|
|
81756
|
+
<meta charset="utf-8">
|
|
81757
|
+
<style>
|
|
81758
|
+
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
|
81759
|
+
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
|
81760
|
+
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px 8px 0 0; }
|
|
81761
|
+
.content { background: #f9f9f9; padding: 20px; border-radius: 0 0 8px 8px; }
|
|
81762
|
+
.info { background: white; padding: 15px; border-left: 4px solid #667eea; margin: 10px 0; }
|
|
81763
|
+
.footer { text-align: center; margin-top: 20px; color: #666; font-size: 12px; }
|
|
81764
|
+
</style>
|
|
81917
81765
|
</head>
|
|
81918
81766
|
<body>
|
|
81919
|
-
|
|
81920
|
-
|
|
81921
|
-
|
|
81922
|
-
|
|
81923
|
-
<
|
|
81924
|
-
|
|
81925
|
-
|
|
81926
|
-
|
|
81927
|
-
|
|
81928
|
-
|
|
81929
|
-
|
|
81930
|
-
|
|
81931
|
-
|
|
81932
|
-
|
|
81933
|
-
<div class="
|
|
81934
|
-
|
|
81935
|
-
|
|
81936
|
-
</div>
|
|
81937
|
-
<div class="footer">
|
|
81938
|
-
Powered by <strong>LLBot</strong> · Lucky Lillia Bot
|
|
81767
|
+
<div class="container">
|
|
81768
|
+
<div class="header">
|
|
81769
|
+
<h2>🎉 LLBot 邮件通知测试</h2>
|
|
81770
|
+
</div>
|
|
81771
|
+
<div class="content">
|
|
81772
|
+
<p>您好!</p>
|
|
81773
|
+
<p>这是一封来自 <strong>LLBot</strong> 的测试邮件。</p>
|
|
81774
|
+
<div class="info">
|
|
81775
|
+
<p><strong>📧 邮件配置测试成功</strong></p>
|
|
81776
|
+
<p>发送时间: ${timestamp}</p>
|
|
81777
|
+
</div>
|
|
81778
|
+
<p>如果您收到这封邮件,说明邮件通知功能已正常工作。</p>
|
|
81779
|
+
<p>当 QQ 掉线时,系统将自动向您发送通知邮件。</p>
|
|
81780
|
+
</div>
|
|
81781
|
+
<div class="footer">
|
|
81782
|
+
<p>此邮件由 LLBot 自动发送,请勿回复</p>
|
|
81783
|
+
</div>
|
|
81939
81784
|
</div>
|
|
81940
|
-
</div>
|
|
81941
81785
|
</body>
|
|
81942
81786
|
</html>
|
|
81943
81787
|
`.trim();
|
|
@@ -82043,12 +81887,14 @@ class EmailConfigManager {
|
|
|
82043
81887
|
}
|
|
82044
81888
|
}
|
|
82045
81889
|
class EmailNotificationService extends Service2 {
|
|
81890
|
+
static inject = ["logger"];
|
|
82046
81891
|
emailService;
|
|
82047
81892
|
configManager;
|
|
82048
81893
|
notificationSent = false;
|
|
82049
81894
|
hasLoggedIn = false;
|
|
82050
81895
|
configPath;
|
|
82051
81896
|
fileWatcher = null;
|
|
81897
|
+
pmhqDisconnectId = null;
|
|
82052
81898
|
constructor(ctx) {
|
|
82053
81899
|
super(ctx, "emailNotification", true);
|
|
82054
81900
|
this.configPath = path__default.join(DATA_DIR, "email_config.json");
|
|
@@ -82057,6 +81903,7 @@ class EmailNotificationService extends Service2 {
|
|
|
82057
81903
|
this.initializeConfig();
|
|
82058
81904
|
this.registerEventListeners();
|
|
82059
81905
|
this.watchConfigFile();
|
|
81906
|
+
this.registerPmhqDisconnectCallback();
|
|
82060
81907
|
}
|
|
82061
81908
|
async initializeConfig() {
|
|
82062
81909
|
try {
|
|
@@ -82072,7 +81919,7 @@ class EmailNotificationService extends Service2 {
|
|
|
82072
81919
|
let wasOffline = false;
|
|
82073
81920
|
this.ctx.on("nt/kicked-offLine", (info) => {
|
|
82074
81921
|
wasOffline = true;
|
|
82075
|
-
this.onOffline(info);
|
|
81922
|
+
this.onOffline(info.tipsDesc || info.tipsTitle);
|
|
82076
81923
|
});
|
|
82077
81924
|
const checkLoginStatus = setInterval(() => {
|
|
82078
81925
|
if (wasOffline && selfInfo.online) {
|
|
@@ -82086,6 +81933,9 @@ class EmailNotificationService extends Service2 {
|
|
|
82086
81933
|
if (this.fileWatcher) {
|
|
82087
81934
|
this.fileWatcher.close();
|
|
82088
81935
|
}
|
|
81936
|
+
if (this.pmhqDisconnectId) {
|
|
81937
|
+
pmhq.offDisconnect(this.pmhqDisconnectId);
|
|
81938
|
+
}
|
|
82089
81939
|
});
|
|
82090
81940
|
}
|
|
82091
81941
|
watchConfigFile() {
|
|
@@ -82102,7 +81952,16 @@ class EmailNotificationService extends Service2 {
|
|
|
82102
81952
|
this.ctx.logger.error("[EmailNotification] Failed to watch config file:", error2);
|
|
82103
81953
|
}
|
|
82104
81954
|
}
|
|
82105
|
-
|
|
81955
|
+
registerPmhqDisconnectCallback() {
|
|
81956
|
+
this.pmhqDisconnectId = pmhq.onDisconnect(6e4, (duration2) => {
|
|
81957
|
+
if (!this.notificationSent && this.hasLoggedIn) {
|
|
81958
|
+
this.ctx.logger.warn(`[EmailNotification] PMHQ disconnected for ${duration2}ms`);
|
|
81959
|
+
this.onOffline("可能 QQ 已经有点死了");
|
|
81960
|
+
}
|
|
81961
|
+
});
|
|
81962
|
+
this.ctx.logger.info(`[EmailNotification] Registered PMHQ disconnect callback with ID: ${this.pmhqDisconnectId}`);
|
|
81963
|
+
}
|
|
81964
|
+
onOffline(reason) {
|
|
82106
81965
|
if (!this.hasLoggedIn) {
|
|
82107
81966
|
this.ctx.logger.debug("[EmailNotification] Offline event before login, ignoring");
|
|
82108
81967
|
return;
|
|
@@ -82112,7 +81971,7 @@ class EmailNotificationService extends Service2 {
|
|
|
82112
81971
|
return;
|
|
82113
81972
|
}
|
|
82114
81973
|
this.ctx.logger.info("[EmailNotification] Bot went offline, sending notification");
|
|
82115
|
-
this.sendOfflineNotification(
|
|
81974
|
+
this.sendOfflineNotification(reason);
|
|
82116
81975
|
}
|
|
82117
81976
|
async sendOfflineNotification(reason) {
|
|
82118
81977
|
try {
|
|
@@ -82257,9 +82116,9 @@ try {
|
|
|
82257
82116
|
}
|
|
82258
82117
|
export {
|
|
82259
82118
|
Action as A,
|
|
82260
|
-
|
|
82119
|
+
Msg as M,
|
|
82261
82120
|
Notify as N,
|
|
82262
82121
|
Oidb as O,
|
|
82263
|
-
|
|
82122
|
+
Media as a
|
|
82264
82123
|
};
|
|
82265
82124
|
//# sourceMappingURL=llbot.js.map
|