feat: enforce read-only wechat archive ingestion

This commit is contained in:
Codex
2026-06-13 06:22:04 +00:00
parent edb040d31a
commit 37f48d4655
5 changed files with 250 additions and 37 deletions
+12 -3
View File
@@ -825,16 +825,24 @@ function archiveContentPayload(body: Record<string, unknown>): Record<string, un
const message = recordFrom(body.message);
const archive = recordFrom(body.archive);
const media = recordFrom(message.media);
const langbotData = recordFrom(body.data);
const langbotMessage = recordFrom(langbotData.message);
const langbotComponents = Array.isArray(langbotMessage.root) ? langbotMessage.root : [];
const langbotPlain = langbotComponents
.filter((item) => recordFrom(item).type === "Plain")
.map((item) => stringFrom(recordFrom(item).text))
.join("");
const langbotImage = recordFrom(langbotComponents.find((item) => recordFrom(item).type === "Image"));
const messageType = stringFrom(message.messageType || body.messageType || "text").toLowerCase();
const remotePath = stringFrom(archive.remotePath);
if (!isValidArchiveRemotePath(remotePath)) throw new Error("archive.remotePath is outside the WeChat archive root");
const filename = stringFrom(archive.filename || remotePath.split("/").filter(Boolean).pop() || "wechat-archive.txt");
if (messageType === "image") {
const dataBase64 = stringFrom(media.dataBase64 || archive.dataBase64 || body.dataBase64);
const dataBase64 = stringFrom(media.dataBase64 || archive.dataBase64 || body.dataBase64 || langbotImage.base64);
if (!dataBase64) throw new Error("image archive payload is missing media.dataBase64");
return { dataBase64, filename, remotePath, maxBytes: 10 * 1024 * 1024 };
}
const text = stringFrom(message.text || body.text || body.message || body.content);
const text = stringFrom(message.text || body.text || body.message || body.content || langbotPlain);
const payloadHash = new Bun.CryptoHasher("sha256").update(JSON.stringify(body)).digest("hex");
const content = `${text}\n\n---\nsource=unidesk-wechat-archive\npayloadSha256=${payloadHash}\n`;
return { content, filename, remotePath, maxBytes: 10 * 1024 * 1024 };
@@ -912,7 +920,8 @@ async function wechatArchiveWebhook(req: Request): Promise<Response> {
logger(ok ? "info" : "warn", "wechat_archive_upload_finished", { ok, jobId, remotePath, fsIdPresent: fsId.length > 0 });
return jsonResponse({
ok,
response: ok ? `已归档到百度网盘:${remotePath}` : "归档失败",
skip_pipeline: ok,
readOnly: true,
archive: {
remotePath,
fsId,