@zoulabo/line-hive 0.1.20 → 0.1.22
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/README.md +55 -9
- package/dist/cli/config-writer.js +1 -1
- package/dist/cli/config-writer.js.map +1 -1
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -1
- package/dist/i18n.js +3 -1
- package/dist/i18n.js.map +1 -1
- package/dist/index.js +59 -3
- package/dist/index.js.map +1 -1
- package/dist/line/messages.js +141 -2
- package/dist/line/messages.js.map +1 -1
- package/dist/line/webhook.js +294 -54
- package/dist/line/webhook.js.map +1 -1
- package/dist/server.js +45 -18
- package/dist/server.js.map +1 -1
- package/dist/store/messageStore.js +123 -53
- package/dist/store/messageStore.js.map +1 -1
- package/dist/tools/ask.js +90 -44
- package/dist/tools/ask.js.map +1 -1
- package/dist/tools/createDocx.js +459 -0
- package/dist/tools/createDocx.js.map +1 -0
- package/dist/tools/createPptx.js +554 -0
- package/dist/tools/createPptx.js.map +1 -0
- package/dist/tools/createXlsx.js +360 -0
- package/dist/tools/createXlsx.js.map +1 -0
- package/dist/tools/gitReview-template.js +208 -0
- package/dist/tools/gitReview-template.js.map +1 -0
- package/dist/tools/gitReview.js +232 -0
- package/dist/tools/gitReview.js.map +1 -0
- package/dist/tools/readFile.js +22 -29
- package/dist/tools/readFile.js.map +1 -1
- package/dist/tools/renderMarkdown.js +248 -9
- package/dist/tools/renderMarkdown.js.map +1 -1
- package/dist/tools/sendMessage.js +20 -6
- package/dist/tools/sendMessage.js.map +1 -1
- package/dist/tools/setStatus.js +4 -2
- package/dist/tools/setStatus.js.map +1 -1
- package/dist/tunnel.js +1 -17
- package/dist/tunnel.js.map +1 -1
- package/dist/util/toolHelpers.js +471 -28
- package/dist/util/toolHelpers.js.map +1 -1
- package/package.json +7 -1
- package/templates/line-notification.instructions.md +137 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/line/messages.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/line/messages.ts"],"names":[],"mappings":"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"}
|
package/dist/line/webhook.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import http from "http";
|
|
2
2
|
import crypto from "crypto";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
3
5
|
import { buildDeleteQueueReply, errorMessage, parsePostbackData, textWithQuickReply, textWithQueueQuickReply, formatTimeAgo, STATUS_ICONS, getAgentDisplayName, } from "./messages.js";
|
|
4
6
|
import { sendWithTokenPool } from "../util/sendWithTokenPool.js";
|
|
5
|
-
import { CONFIG_TARGETED_AGENT } from "../constants.js";
|
|
7
|
+
import { CONFIG_TARGETED_AGENT, INCOMING_MEDIA_DIR } from "../constants.js";
|
|
8
|
+
import { getServeDir } from "../util/toolHelpers.js";
|
|
6
9
|
import { t, resolveLocale } from "../i18n.js";
|
|
7
10
|
export function verifySignature(secret, body, signature) {
|
|
8
11
|
if (!secret || !signature) {
|
|
@@ -16,6 +19,73 @@ export function verifySignature(secret, body, signature) {
|
|
|
16
19
|
return false;
|
|
17
20
|
return crypto.timingSafeEqual(hashBuf, sigBuf);
|
|
18
21
|
}
|
|
22
|
+
// ─── SSRF Protection ────────────────────────────────────────────────────────
|
|
23
|
+
/** Private/reserved CIDR ranges that should never be fetched externally */
|
|
24
|
+
const PRIVATE_RANGES = [
|
|
25
|
+
{ prefix: "10.", mask: 8 },
|
|
26
|
+
{ prefix: "127.", mask: 8 },
|
|
27
|
+
{ prefix: "169.254.", mask: 16 },
|
|
28
|
+
{ prefix: "192.168.", mask: 16 },
|
|
29
|
+
{ prefix: "0.", mask: 8 },
|
|
30
|
+
// 172.16.0.0/12
|
|
31
|
+
];
|
|
32
|
+
function isPrivateIp(ip) {
|
|
33
|
+
for (const range of PRIVATE_RANGES) {
|
|
34
|
+
if (ip.startsWith(range.prefix))
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
// 172.16.0.0 – 172.31.255.255
|
|
38
|
+
if (ip.startsWith("172.")) {
|
|
39
|
+
const second = parseInt(ip.split(".")[1], 10);
|
|
40
|
+
if (second >= 16 && second <= 31)
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
// IPv6 loopback
|
|
44
|
+
if (ip === "::1" || ip === "[::1]")
|
|
45
|
+
return true;
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check if a URL resolves to a private/reserved IP range (SSRF protection).
|
|
50
|
+
* Only checks the hostname — DNS rebinding is out of scope for this check.
|
|
51
|
+
*/
|
|
52
|
+
function isPrivateUrl(urlStr) {
|
|
53
|
+
try {
|
|
54
|
+
const parsed = new URL(urlStr);
|
|
55
|
+
return isPrivateIp(parsed.hostname);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return true; // invalid URL → reject
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// ─── Size-limited response reader ───────────────────────────────────────────
|
|
62
|
+
/**
|
|
63
|
+
* Read a fetch Response body with a hard byte limit.
|
|
64
|
+
* Prevents Content-Length TOCTOU: the actual bytes are counted during read.
|
|
65
|
+
* Returns null if the body exceeds the limit.
|
|
66
|
+
*/
|
|
67
|
+
async function readResponseWithLimit(res, maxBytes) {
|
|
68
|
+
const reader = res.body?.getReader();
|
|
69
|
+
if (!reader) {
|
|
70
|
+
// Fallback for environments without readable stream
|
|
71
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
72
|
+
return buf.length <= maxBytes ? buf : null;
|
|
73
|
+
}
|
|
74
|
+
const chunks = [];
|
|
75
|
+
let totalBytes = 0;
|
|
76
|
+
while (true) {
|
|
77
|
+
const { done, value } = await reader.read();
|
|
78
|
+
if (done)
|
|
79
|
+
break;
|
|
80
|
+
totalBytes += value.byteLength;
|
|
81
|
+
if (totalBytes > maxBytes) {
|
|
82
|
+
reader.cancel();
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
chunks.push(value);
|
|
86
|
+
}
|
|
87
|
+
return Buffer.concat(chunks);
|
|
88
|
+
}
|
|
19
89
|
function getWebhookEventId(event) {
|
|
20
90
|
return event.webhookEventId || event.message?.id || event.replyToken || `${event.timestamp}`;
|
|
21
91
|
}
|
|
@@ -42,6 +112,18 @@ async function resolveUserLocale(deps, userId) {
|
|
|
42
112
|
}
|
|
43
113
|
return "en";
|
|
44
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Register the user as default (if first user) and auto-enable restricted mode.
|
|
117
|
+
* When the first user interacts with the bot and no allowed_users list exists yet,
|
|
118
|
+
* this switches from open mode to restricted mode with the first user auto-allowed.
|
|
119
|
+
*/
|
|
120
|
+
function registerAndAutoAllow(deps, userId) {
|
|
121
|
+
const isFirst = deps.messageStore.registerDefaultUserIfMissing(userId);
|
|
122
|
+
if (isFirst && deps.messageStore.getAllowedUsers().length === 0) {
|
|
123
|
+
deps.messageStore.addAllowedUser(userId);
|
|
124
|
+
deps.logger?.info({ userId: userId.slice(0, 8) }, "First user auto-allowed, restricted mode enabled");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
45
127
|
/** Format a single agent's status into a line of text */
|
|
46
128
|
export function formatAgentStatus(agent, locale = "en") {
|
|
47
129
|
const m = t(locale);
|
|
@@ -136,8 +218,8 @@ async function replyViaPool(deps, replyToken, message, eventTimestamp) {
|
|
|
136
218
|
}
|
|
137
219
|
}
|
|
138
220
|
/**
|
|
139
|
-
* Download an image
|
|
140
|
-
* Uses the
|
|
221
|
+
* Download an image from the LINE Content API at full resolution.
|
|
222
|
+
* Uses the full content endpoint (not preview) to get the original image.
|
|
141
223
|
* For external images (forwarded), fetches from the original URL directly.
|
|
142
224
|
*/
|
|
143
225
|
async function downloadImagePreview(deps, event) {
|
|
@@ -151,10 +233,16 @@ async function downloadImagePreview(deps, event) {
|
|
|
151
233
|
deps.logger?.warn({ url: provider.originalContentUrl }, "Rejected non-HTTPS external image URL");
|
|
152
234
|
return null;
|
|
153
235
|
}
|
|
236
|
+
// Block private/reserved IP ranges (SSRF protection)
|
|
237
|
+
if (isPrivateUrl(provider.originalContentUrl)) {
|
|
238
|
+
deps.logger?.warn({ url: provider.originalContentUrl }, "Rejected external URL targeting private/reserved IP");
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
154
241
|
url = provider.originalContentUrl;
|
|
155
242
|
}
|
|
156
243
|
else if (messageId) {
|
|
157
|
-
|
|
244
|
+
// Full-resolution content endpoint (not /preview)
|
|
245
|
+
url = `https://api-data.line.me/v2/bot/message/${messageId}/content`;
|
|
158
246
|
}
|
|
159
247
|
else {
|
|
160
248
|
return null;
|
|
@@ -168,16 +256,20 @@ async function downloadImagePreview(deps, event) {
|
|
|
168
256
|
deps.logger?.warn({ status: res.status, messageId }, "Image download failed");
|
|
169
257
|
return null;
|
|
170
258
|
}
|
|
171
|
-
// Limit download size to
|
|
259
|
+
// Limit download size to 10MB to prevent memory exhaustion
|
|
260
|
+
const MAX_DOWNLOAD = 10 * 1024 * 1024;
|
|
172
261
|
const contentLength = res.headers.get("content-length");
|
|
173
|
-
if (contentLength && parseInt(contentLength, 10) >
|
|
262
|
+
if (contentLength && parseInt(contentLength, 10) > MAX_DOWNLOAD) {
|
|
174
263
|
deps.logger?.warn({ contentLength }, "Image too large, skipping download");
|
|
175
264
|
return null;
|
|
176
265
|
}
|
|
177
|
-
const buffer =
|
|
178
|
-
|
|
266
|
+
const buffer = await readResponseWithLimit(res, MAX_DOWNLOAD);
|
|
267
|
+
if (!buffer) {
|
|
268
|
+
deps.logger?.warn({ messageId }, "Image body exceeded size limit during read");
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
179
271
|
const mimeType = res.headers.get("content-type") || "image/jpeg";
|
|
180
|
-
return {
|
|
272
|
+
return { buffer, mimeType };
|
|
181
273
|
}
|
|
182
274
|
catch (error) {
|
|
183
275
|
deps.logger?.warn({ error }, "Image download error");
|
|
@@ -202,17 +294,21 @@ async function downloadFileContent(deps, event) {
|
|
|
202
294
|
deps.logger?.warn({ status: res.status, messageId }, "File download failed");
|
|
203
295
|
return null;
|
|
204
296
|
}
|
|
205
|
-
// Limit download size to
|
|
297
|
+
// Limit download size (configurable) to prevent memory exhaustion.
|
|
298
|
+
const MAX_DOWNLOAD = deps.config.maxIncomingFileBytes;
|
|
206
299
|
const contentLength = res.headers.get("content-length");
|
|
207
|
-
if (contentLength && parseInt(contentLength, 10) >
|
|
300
|
+
if (contentLength && parseInt(contentLength, 10) > MAX_DOWNLOAD) {
|
|
208
301
|
deps.logger?.warn({ contentLength }, "File too large, skipping download");
|
|
209
302
|
return null;
|
|
210
303
|
}
|
|
211
|
-
const buffer =
|
|
212
|
-
|
|
304
|
+
const buffer = await readResponseWithLimit(res, MAX_DOWNLOAD);
|
|
305
|
+
if (!buffer) {
|
|
306
|
+
deps.logger?.warn({ messageId }, "File body exceeded size limit during read");
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
213
309
|
const mimeType = res.headers.get("content-type") || "application/octet-stream";
|
|
214
310
|
return {
|
|
215
|
-
|
|
311
|
+
buffer,
|
|
216
312
|
mimeType,
|
|
217
313
|
fileName: event.message?.fileName,
|
|
218
314
|
fileSize: event.message?.fileSize,
|
|
@@ -223,6 +319,38 @@ async function downloadFileContent(deps, event) {
|
|
|
223
319
|
return null;
|
|
224
320
|
}
|
|
225
321
|
}
|
|
322
|
+
/**
|
|
323
|
+
* Write downloaded media to disk under `.line-hive-tmp/incoming/`.
|
|
324
|
+
* Returns the relative disk path (from project root) for storage in media_json.
|
|
325
|
+
*
|
|
326
|
+
* Naming: `{lineMessageId}-{sanitizedFilename}` or `{lineMessageId}.{ext}`
|
|
327
|
+
*/
|
|
328
|
+
function writeIncomingMedia(lineMessageId, buffer, mimeType, fileName) {
|
|
329
|
+
const dir = path.resolve(INCOMING_MEDIA_DIR);
|
|
330
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
331
|
+
// Derive extension from filename or mime type
|
|
332
|
+
const mimeToExt = {
|
|
333
|
+
"image/jpeg": ".jpg", "image/png": ".png", "image/gif": ".gif",
|
|
334
|
+
"image/webp": ".webp", "audio/mpeg": ".mp3", "audio/m4a": ".m4a",
|
|
335
|
+
"audio/ogg": ".ogg", "video/mp4": ".mp4", "application/pdf": ".pdf",
|
|
336
|
+
};
|
|
337
|
+
// Sanitize message ID and filename to prevent path traversal
|
|
338
|
+
const safeId = lineMessageId.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
339
|
+
let safeName;
|
|
340
|
+
if (fileName) {
|
|
341
|
+
// Sanitize user-provided filename: keep alphanumeric, dots, hyphens, underscores
|
|
342
|
+
safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
const ext = mimeToExt[mimeType] || "";
|
|
346
|
+
safeName = `${safeId}${ext}`;
|
|
347
|
+
}
|
|
348
|
+
const diskName = `${safeId}-${safeName}`;
|
|
349
|
+
const diskPath = path.join(dir, diskName);
|
|
350
|
+
fs.writeFileSync(diskPath, buffer, { mode: 0o600 });
|
|
351
|
+
// Return path relative to project root (for storage in media_json)
|
|
352
|
+
return path.join(INCOMING_MEDIA_DIR, diskName);
|
|
353
|
+
}
|
|
226
354
|
async function handleFileEvent(deps, event, userId) {
|
|
227
355
|
const replyToken = event.replyToken;
|
|
228
356
|
const webhookEventId = getWebhookEventId(event);
|
|
@@ -230,7 +358,17 @@ async function handleFileEvent(deps, event, userId) {
|
|
|
230
358
|
const fileSize = event.message?.fileSize;
|
|
231
359
|
// Download file content immediately (LINE auto-deletes content after a period)
|
|
232
360
|
const media = await downloadFileContent(deps, event);
|
|
233
|
-
|
|
361
|
+
let mediaJson = null;
|
|
362
|
+
if (media) {
|
|
363
|
+
const lineMessageId = event.message?.id ?? webhookEventId;
|
|
364
|
+
const diskPath = writeIncomingMedia(lineMessageId, media.buffer, media.mimeType, media.fileName);
|
|
365
|
+
mediaJson = JSON.stringify({
|
|
366
|
+
mimeType: media.mimeType,
|
|
367
|
+
diskPath,
|
|
368
|
+
fileName: media.fileName,
|
|
369
|
+
fileSize: media.fileSize,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
234
372
|
const locale = await resolveUserLocale(deps, userId);
|
|
235
373
|
const chatTargetedAgentId = deps.messageStore.getConfig(CONFIG_TARGETED_AGENT);
|
|
236
374
|
const sizeStr = fileSize ? ` (${Math.round(fileSize / 1024)}KB)` : "";
|
|
@@ -261,7 +399,12 @@ async function handleImageEvent(deps, event, userId) {
|
|
|
261
399
|
const webhookEventId = getWebhookEventId(event);
|
|
262
400
|
// Download image preview immediately (LINE auto-deletes content after a period)
|
|
263
401
|
const media = await downloadImagePreview(deps, event);
|
|
264
|
-
|
|
402
|
+
let mediaJson = null;
|
|
403
|
+
if (media) {
|
|
404
|
+
const lineMessageId = event.message?.id ?? webhookEventId;
|
|
405
|
+
const diskPath = writeIncomingMedia(lineMessageId, media.buffer, media.mimeType);
|
|
406
|
+
mediaJson = JSON.stringify({ mimeType: media.mimeType, diskPath });
|
|
407
|
+
}
|
|
265
408
|
// Resolve user locale
|
|
266
409
|
const locale = await resolveUserLocale(deps, userId);
|
|
267
410
|
// For chat messages, use targeted routing if user has selected an agent
|
|
@@ -277,7 +420,7 @@ async function handleImageEvent(deps, event, userId) {
|
|
|
277
420
|
}, { targetedAgentId: chatTargetedAgentId });
|
|
278
421
|
if (messageResult.deduped)
|
|
279
422
|
return;
|
|
280
|
-
// Auto-register userId
|
|
423
|
+
// Auto-register userId (no auto-allow for image events)
|
|
281
424
|
deps.messageStore.registerDefaultUserIfMissing(userId);
|
|
282
425
|
if (!replyToken)
|
|
283
426
|
return;
|
|
@@ -331,8 +474,13 @@ async function handleTextEvent(deps, event, text, userId) {
|
|
|
331
474
|
if (isControlCommand && messageResult.messageId) {
|
|
332
475
|
deps.messageStore.markMessageConsumed(messageResult.messageId);
|
|
333
476
|
}
|
|
334
|
-
// Auto-register
|
|
335
|
-
|
|
477
|
+
// Auto-register: only auto-allow on status command ("?"), not on chat/other
|
|
478
|
+
if (command.type === "status") {
|
|
479
|
+
registerAndAutoAllow(deps, userId);
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
deps.messageStore.registerDefaultUserIfMissing(userId);
|
|
483
|
+
}
|
|
336
484
|
if (!replyToken) {
|
|
337
485
|
return;
|
|
338
486
|
}
|
|
@@ -356,13 +504,21 @@ async function handlePostbackEvent(deps, event, data, userId) {
|
|
|
356
504
|
const replyToken = event.replyToken;
|
|
357
505
|
if (!replyToken)
|
|
358
506
|
return;
|
|
359
|
-
// Auto-register userId
|
|
507
|
+
// Auto-register userId (no auto-allow for postback events)
|
|
360
508
|
deps.messageStore.registerDefaultUserIfMissing(userId);
|
|
361
509
|
// Resolve user locale
|
|
362
510
|
const locale = await resolveUserLocale(deps, userId);
|
|
363
511
|
const command = parsePostbackData(data);
|
|
364
512
|
await handleCommandReply(deps, command, replyToken, null, event.timestamp, locale);
|
|
365
513
|
}
|
|
514
|
+
/**
|
|
515
|
+
* Strip [Quoting: "..."] prefix from message text for queue previews.
|
|
516
|
+
* Quoted context is preserved in the full message delivered to agents,
|
|
517
|
+
* but showing it in the 50-char preview makes it look like a separate message.
|
|
518
|
+
*/
|
|
519
|
+
function stripQuotePrefix(text) {
|
|
520
|
+
return text.replace(/^\[Quoting: "[^"]*"\]\s*/, "");
|
|
521
|
+
}
|
|
366
522
|
/**
|
|
367
523
|
* Shared command handler — routes status/select/chat commands
|
|
368
524
|
* and replies with rich messages.
|
|
@@ -488,7 +644,8 @@ async function handleCommandReply(deps, command, replyToken, messageId, eventTim
|
|
|
488
644
|
: m.queuedHeader();
|
|
489
645
|
const lines = queued.map((msg, i) => {
|
|
490
646
|
const ago = formatTimeAgo(msg.timestamp, locale);
|
|
491
|
-
const
|
|
647
|
+
const displayText = stripQuotePrefix(msg.text);
|
|
648
|
+
const preview = displayText.length > 50 ? displayText.slice(0, 50) + "…" : displayText;
|
|
492
649
|
// Only show per-line agent label when agents differ
|
|
493
650
|
const agentLabel = !allSameAgent && msg.targetAgentId
|
|
494
651
|
? ` → ${msg.targetAgentId.includes(":") ? msg.targetAgentId.split(":").pop() : msg.targetAgentId}`
|
|
@@ -516,7 +673,8 @@ async function handleCommandReply(deps, command, replyToken, messageId, eventTim
|
|
|
516
673
|
else {
|
|
517
674
|
const lines = queued.map((msg, i) => {
|
|
518
675
|
const ago = formatTimeAgo(msg.timestamp, locale);
|
|
519
|
-
const
|
|
676
|
+
const displayText = stripQuotePrefix(msg.text);
|
|
677
|
+
const preview = displayText.length > 50 ? displayText.slice(0, 50) + "…" : displayText;
|
|
520
678
|
const emoji = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣"][i] || `${i + 1}`;
|
|
521
679
|
return `${emoji} ${preview} (${ago})`;
|
|
522
680
|
});
|
|
@@ -544,7 +702,8 @@ async function handleCommandReply(deps, command, replyToken, messageId, eventTim
|
|
|
544
702
|
const allSameAgent = queued.every(msg => msg.targetAgentId && msg.targetAgentId === queued[0].targetAgentId);
|
|
545
703
|
const lines = queued.map((msg, i) => {
|
|
546
704
|
const ago = formatTimeAgo(msg.timestamp, locale);
|
|
547
|
-
const
|
|
705
|
+
const displayText = stripQuotePrefix(msg.text);
|
|
706
|
+
const preview = displayText.length > 50 ? displayText.slice(0, 50) + "…" : displayText;
|
|
548
707
|
const agentLabel = !allSameAgent && msg.targetAgentId
|
|
549
708
|
? ` → ${msg.targetAgentId.includes(":") ? msg.targetAgentId.split(":").pop() : msg.targetAgentId}`
|
|
550
709
|
: "";
|
|
@@ -600,7 +759,8 @@ async function handleCommandReply(deps, command, replyToken, messageId, eventTim
|
|
|
600
759
|
deps.logger?.info({ targetAgent: agentDisplayName }, "Chat routed to targeted agent");
|
|
601
760
|
// If agent is actively waiting (has active session), save token silently —
|
|
602
761
|
// agent will respond within seconds via line_ask polling.
|
|
603
|
-
|
|
762
|
+
// Scope to THIS agent to avoid stale sessions from dead agents suppressing acks.
|
|
763
|
+
if (deps.messageStore.getWaitingSessionForAgent(targetAgent.agentId)) {
|
|
604
764
|
deps.messageStore.saveReplyToken(replyToken, eventTimestamp ?? Date.now());
|
|
605
765
|
return;
|
|
606
766
|
}
|
|
@@ -608,7 +768,7 @@ async function handleCommandReply(deps, command, replyToken, messageId, eventTim
|
|
|
608
768
|
// send brief ack so user knows message was received and queued
|
|
609
769
|
const queueCount = deps.messageStore.countUnclaimedMessages(undefined, targetAgent.agentId);
|
|
610
770
|
const queueInfo = queueCount > 1 ? m.nQueued(queueCount) : "";
|
|
611
|
-
await replyViaPool(deps, replyToken, textWithQuickReply(m.ackQueued(agentDisplayName, queueInfo), recentStatuses, locale), eventTimestamp);
|
|
771
|
+
await replyViaPool(deps, replyToken, textWithQuickReply(m.ackQueued(agentDisplayName, queueInfo), recentStatuses, locale, { dismissMessageId: messageId ?? undefined }), eventTimestamp);
|
|
612
772
|
return;
|
|
613
773
|
}
|
|
614
774
|
// No targeted agent — fall back to needs_input routing
|
|
@@ -645,6 +805,11 @@ export async function handleWebhook(deps, body, signature) {
|
|
|
645
805
|
const userId = event.source?.userId;
|
|
646
806
|
if (!userId)
|
|
647
807
|
continue;
|
|
808
|
+
// Access control: reject messages from unauthorized users
|
|
809
|
+
if (!deps.messageStore.isUserAllowed(userId)) {
|
|
810
|
+
deps.logger?.info({ userId: userId.slice(0, 8) }, "Blocked message from unauthorized user");
|
|
811
|
+
continue;
|
|
812
|
+
}
|
|
648
813
|
if (event.type === "message" && event.message?.type === "text") {
|
|
649
814
|
const text = event.message?.text ?? "";
|
|
650
815
|
await handleTextEvent(deps, event, text, userId);
|
|
@@ -667,6 +832,14 @@ export async function handleWebhook(deps, body, signature) {
|
|
|
667
832
|
const removed = deps.messageStore.deleteByLineMessageId(event.unsend.messageId);
|
|
668
833
|
deps.logger?.info({ lineMessageId: event.unsend.messageId, removed }, "Unsend: message deleted");
|
|
669
834
|
}
|
|
835
|
+
else if (event.type === "follow") {
|
|
836
|
+
// New user added bot as friend — auto-register and auto-allow
|
|
837
|
+
registerAndAutoAllow(deps, userId);
|
|
838
|
+
// Save reply token if available
|
|
839
|
+
if (event.replyToken) {
|
|
840
|
+
deps.messageStore.saveReplyToken(event.replyToken, event.timestamp);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
670
843
|
}
|
|
671
844
|
return { statusCode: 200, body: "OK" };
|
|
672
845
|
}
|
|
@@ -675,43 +848,109 @@ export function startWebhookServer(deps) {
|
|
|
675
848
|
const server = http.createServer((req, res) => {
|
|
676
849
|
const { method, url } = req;
|
|
677
850
|
// Serve outgoing files/images for LINE to fetch or user to download
|
|
678
|
-
|
|
679
|
-
const isFilesRoute = method === "GET" && (url?.startsWith("/files/") || url?.startsWith("/images/"));
|
|
851
|
+
const isFilesRoute = (method === "GET" || method === "HEAD") && url?.startsWith("/files/");
|
|
680
852
|
if (isFilesRoute) {
|
|
681
|
-
const prefix =
|
|
853
|
+
const prefix = "/files/";
|
|
682
854
|
// Strip query string and decode percent-encoding for clean ID extraction
|
|
683
855
|
const rawId = url.slice(prefix.length).split("?")[0];
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
if (!imageId || imageId.includes("/") || imageId.includes("..")) {
|
|
856
|
+
const decodedRawId = decodeURIComponent(rawId);
|
|
857
|
+
if (!decodedRawId || decodedRawId.includes("/") || decodedRawId.includes("..") || decodedRawId.includes("\\")) {
|
|
687
858
|
res.statusCode = 404;
|
|
688
859
|
res.end("Not found");
|
|
689
860
|
return;
|
|
690
861
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
862
|
+
// Check TTL — all disk-served files MUST be tracked.
|
|
863
|
+
// Untracked files on disk return 404 (strict mode).
|
|
864
|
+
// Race: cleanup may delete between check and readFile → 404 (acceptable).
|
|
865
|
+
const fileExpiry = deps.messageStore.getServedFileExpiry(decodedRawId);
|
|
866
|
+
if (fileExpiry?.isExpired) {
|
|
867
|
+
res.statusCode = 410;
|
|
868
|
+
res.end("Gone — file expired");
|
|
695
869
|
return;
|
|
696
870
|
}
|
|
697
|
-
//
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
871
|
+
// Try disk (files MUST be tracked in served_files table)
|
|
872
|
+
const serveDir = getServeDir(deps.config);
|
|
873
|
+
const diskPath = path.resolve(serveDir, decodedRawId);
|
|
874
|
+
if (fileExpiry && diskPath.startsWith(serveDir + path.sep)) {
|
|
875
|
+
try {
|
|
876
|
+
const stat = fs.statSync(diskPath);
|
|
877
|
+
if (!stat.isFile()) {
|
|
878
|
+
res.statusCode = 404;
|
|
879
|
+
res.end("Not found");
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
const ext = path.extname(diskPath).toLowerCase();
|
|
883
|
+
const mimeMap = {
|
|
884
|
+
".html": "text/html",
|
|
885
|
+
".css": "text/css",
|
|
886
|
+
".js": "application/javascript",
|
|
887
|
+
".json": "application/json",
|
|
888
|
+
".png": "image/png",
|
|
889
|
+
".jpg": "image/jpeg",
|
|
890
|
+
".jpeg": "image/jpeg",
|
|
891
|
+
".gif": "image/gif",
|
|
892
|
+
".webp": "image/webp",
|
|
893
|
+
".svg": "image/svg+xml",
|
|
894
|
+
".pdf": "application/pdf",
|
|
895
|
+
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
896
|
+
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
897
|
+
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
898
|
+
".csv": "text/csv",
|
|
899
|
+
".txt": "text/plain",
|
|
900
|
+
};
|
|
901
|
+
const mimeType = mimeMap[ext] || "application/octet-stream";
|
|
902
|
+
const contentType = mimeType.startsWith("text/") ? `${mimeType}; charset=utf-8` : mimeType;
|
|
903
|
+
res.setHeader("Content-Type", contentType);
|
|
904
|
+
res.setHeader("Content-Length", stat.size);
|
|
905
|
+
res.setHeader("Cache-Control", "public, max-age=60");
|
|
906
|
+
res.setHeader("X-Content-Type-Options", "nosniff");
|
|
907
|
+
res.setHeader("Referrer-Policy", "no-referrer");
|
|
908
|
+
res.setHeader("Accept-Ranges", "bytes");
|
|
909
|
+
if (mimeType.startsWith("image/") || mimeType === "text/html" || mimeType === "application/pdf") {
|
|
910
|
+
res.setHeader("Content-Disposition", "inline");
|
|
911
|
+
}
|
|
912
|
+
else {
|
|
913
|
+
// Use the filename from the URL path as the download name
|
|
914
|
+
const baseName = path.basename(diskPath);
|
|
915
|
+
res.setHeader("Content-Disposition", `attachment; filename="${baseName}"`);
|
|
916
|
+
}
|
|
917
|
+
res.statusCode = 200;
|
|
918
|
+
if (method === "HEAD") {
|
|
919
|
+
res.end();
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
const stream = fs.createReadStream(diskPath);
|
|
923
|
+
stream.on("error", (err) => {
|
|
924
|
+
if (err?.code === "ENOENT") {
|
|
925
|
+
res.statusCode = 404;
|
|
926
|
+
res.end("Not found");
|
|
927
|
+
}
|
|
928
|
+
else {
|
|
929
|
+
deps.logger?.warn({ error: err instanceof Error ? err.message : err, file: decodedRawId }, "Failed to stream file");
|
|
930
|
+
// If headers already sent, just destroy.
|
|
931
|
+
try {
|
|
932
|
+
res.destroy();
|
|
933
|
+
}
|
|
934
|
+
catch { }
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
stream.pipe(res);
|
|
938
|
+
}
|
|
939
|
+
catch (err) {
|
|
940
|
+
if (err?.code === "ENOENT") {
|
|
941
|
+
res.statusCode = 404;
|
|
942
|
+
res.end("Not found");
|
|
943
|
+
}
|
|
944
|
+
else {
|
|
945
|
+
deps.logger?.warn({ error: err instanceof Error ? err.message : err, file: decodedRawId }, "Failed to serve file");
|
|
946
|
+
res.statusCode = 500;
|
|
947
|
+
res.end("Internal error");
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
return;
|
|
712
951
|
}
|
|
713
|
-
res.statusCode =
|
|
714
|
-
res.end(
|
|
952
|
+
res.statusCode = 404;
|
|
953
|
+
res.end("Not found");
|
|
715
954
|
return;
|
|
716
955
|
}
|
|
717
956
|
if (method !== "POST" || url !== deps.config.webhookPath) {
|
|
@@ -753,10 +992,11 @@ export function startWebhookServer(deps) {
|
|
|
753
992
|
deps.logger?.error({ error }, "Webhook server error");
|
|
754
993
|
throw error;
|
|
755
994
|
});
|
|
756
|
-
server.listen(deps.config.webhookPort, () => {
|
|
995
|
+
server.listen(deps.config.webhookPort, "127.0.0.1", () => {
|
|
757
996
|
deps.logger?.info({
|
|
758
997
|
port: deps.config.webhookPort,
|
|
759
|
-
path: deps.config.webhookPath
|
|
998
|
+
path: deps.config.webhookPath,
|
|
999
|
+
host: "127.0.0.1"
|
|
760
1000
|
}, "Webhook server listening");
|
|
761
1001
|
});
|
|
762
1002
|
return server;
|