




















@@ -3,6 +3,10 @@ import { rmSync } from "node:fs";
33import { readdir, readFile, stat, unlink } from "node:fs/promises";
44import type { IncomingMessage, ServerResponse } from "node:http";
55import { join } from "node:path";
6+import {
7+asDateTimestampMs,
8+resolveExpiresAtMsFromDurationMs,
9+} from "openclaw/plugin-sdk/number-runtime";
610import { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
711import { privateFileStore } from "openclaw/plugin-sdk/security-runtime";
812import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path";
@@ -64,6 +68,10 @@ async function deleteHostedZaloMediaEntry(id: string): Promise<void> {
6468}
65696670async function cleanupExpiredHostedZaloMedia(nowMs = Date.now()): Promise<void> {
71+const now = asDateTimestampMs(nowMs);
72+if (now === undefined) {
73+return;
74+}
6775let fileNames: string[];
6876try {
6977fileNames = await readdir(ZALO_OUTBOUND_MEDIA_DIR);
@@ -79,7 +87,8 @@ async function cleanupExpiredHostedZaloMedia(nowMs = Date.now()): Promise<void>
7987try {
8088const metadataRaw = await readFile(resolveHostedZaloMediaMetadataPath(id), "utf8");
8189const metadata = JSON.parse(metadataRaw) as HostedZaloMediaMetadata;
82-if (metadata.expiresAt <= nowMs) {
90+const expiresAt = asDateTimestampMs(metadata.expiresAt);
91+if (expiresAt === undefined || expiresAt <= now) {
8392await deleteHostedZaloMediaEntry(id);
8493}
8594} catch {
@@ -141,6 +150,15 @@ export async function prepareHostedZaloMediaUrl(params: {
141150await ensureHostedZaloMediaDir();
142151await cleanupExpiredHostedZaloMedia();
143152153+const now = asDateTimestampMs(Date.now());
154+const expiresAt =
155+now === undefined
156+ ? undefined
157+ : resolveExpiresAtMsFromDurationMs(ZALO_OUTBOUND_MEDIA_TTL_MS, { nowMs: now });
158+if (expiresAt === undefined) {
159+throw new Error("Zalo outbound media expiry could not be resolved");
160+}
161+144162const media = await loadOutboundMediaFromUrl(params.mediaUrl, {
145163maxBytes: params.maxBytes,
146164 ...(params.proxyUrl ? { proxyUrl: params.proxyUrl } : {}),
@@ -161,7 +179,7 @@ export async function prepareHostedZaloMediaUrl(params: {
161179 routePath,
162180 token,
163181contentType: media.contentType,
164-expiresAt: Date.now() + ZALO_OUTBOUND_MEDIA_TTL_MS,
182+ expiresAt,
165183} satisfies HostedZaloMediaMetadata);
166184} catch (error) {
167185await deleteHostedZaloMediaEntry(id);
@@ -210,7 +228,9 @@ export async function tryHandleHostedZaloMediaRequest(
210228return true;
211229}
212230213-if (entry.metadata.expiresAt <= Date.now()) {
231+const now = asDateTimestampMs(Date.now());
232+const expiresAt = asDateTimestampMs(entry.metadata.expiresAt);
233+if (now === undefined || expiresAt === undefined || expiresAt <= now) {
214234await deleteHostedZaloMediaEntry(id);
215235res.statusCode = 410;
216236res.end("Expired");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。