@openclaw/crabline 0.1.16 → 0.1.18
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 +8 -0
- package/dist/src/openclaw/bridges/whatsapp.js +21 -1
- package/dist/src/openclaw/bridges/whatsapp.js.map +1 -1
- package/dist/src/openclaw/private-file.js +87 -30
- package/dist/src/openclaw/private-file.js.map +1 -1
- package/dist/src/openclaw/shared.d.ts +9 -0
- package/dist/src/openclaw/shared.js +2 -1
- package/dist/src/openclaw/shared.js.map +1 -1
- package/dist/src/platform/process-owned-lock.d.ts +5 -2
- package/dist/src/platform/process-owned-lock.js +20 -10
- package/dist/src/platform/process-owned-lock.js.map +1 -1
- package/dist/src/servers/discord.js +25 -35
- package/dist/src/servers/discord.js.map +1 -1
- package/dist/src/servers/http.d.ts +3 -0
- package/dist/src/servers/http.js +15 -0
- package/dist/src/servers/http.js.map +1 -1
- package/dist/src/servers/matrix.js +8 -8
- package/dist/src/servers/matrix.js.map +1 -1
- package/dist/src/servers/mattermost.js +7 -10
- package/dist/src/servers/mattermost.js.map +1 -1
- package/dist/src/servers/recorder.d.ts +16 -6
- package/dist/src/servers/recorder.js +52 -12
- package/dist/src/servers/recorder.js.map +1 -1
- package/dist/src/servers/signal.js +8 -8
- package/dist/src/servers/signal.js.map +1 -1
- package/dist/src/servers/slack.js +8 -8
- package/dist/src/servers/slack.js.map +1 -1
- package/dist/src/servers/telegram.d.ts +2 -2
- package/dist/src/servers/telegram.js +8 -8
- package/dist/src/servers/telegram.js.map +1 -1
- package/dist/src/servers/whatsapp-baileys-websocket.d.ts +15 -0
- package/dist/src/servers/whatsapp-baileys-websocket.js +32 -2
- package/dist/src/servers/whatsapp-baileys-websocket.js.map +1 -1
- package/dist/src/servers/whatsapp.js +189 -29
- package/dist/src/servers/whatsapp.js.map +1 -1
- package/dist/src/servers/zalo.js +8 -7
- package/dist/src/servers/zalo.js.map +1 -1
- package/docs/channel-setup.md +65 -1
- package/package.json +12 -12
package/dist/src/servers/zalo.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { validateHeaderValue, } from "node:http";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { adminAuthError, drainRequestBody, hasAdminToken, InvalidJsonBodyError, isJsonObject, isLoopbackHost, jsonResponse, parseUnknownRequestBody, queryRecord, readTrimmedString, RequestBodyTooLargeError, startHttpJsonServer, } from "./http.js";
|
|
5
|
-
import {
|
|
4
|
+
import { adminAuthError, createServerClose, drainRequestBody, hasAdminToken, InvalidJsonBodyError, isJsonObject, isLoopbackHost, jsonResponse, parseUnknownRequestBody, queryRecord, readTrimmedString, RequestBodyTooLargeError, startHttpJsonServer, } from "./http.js";
|
|
5
|
+
import { createServerRecorder } from "./recorder.js";
|
|
6
6
|
import { resolveMaxPendingInboundEvents } from "./pending-events.js";
|
|
7
7
|
import { postWebhookRequest, validateWebhookTarget, } from "./webhook-target.js";
|
|
8
8
|
const DEFAULT_WEBHOOK_DELIVERY_TIMEOUT_MS = 5_000;
|
|
@@ -12,7 +12,7 @@ const MAX_ZALO_REDACTION_DEPTH = 32;
|
|
|
12
12
|
const MAX_WEBHOOK_DELIVERY_TIMEOUT_MS = 30_000;
|
|
13
13
|
const MAX_ZALO_WEBHOOK_SECRET_BYTES = 256;
|
|
14
14
|
async function appendEvent(state, event) {
|
|
15
|
-
await
|
|
15
|
+
await state.recorder.record(event);
|
|
16
16
|
}
|
|
17
17
|
function zaloOk(result) {
|
|
18
18
|
return jsonResponse(result === undefined ? { ok: true } : { ok: true, result });
|
|
@@ -724,6 +724,7 @@ async function handleZaloMethod(request, response, state, url, method) {
|
|
|
724
724
|
}
|
|
725
725
|
export async function startZaloServer(params = {}) {
|
|
726
726
|
const host = params.host ?? "127.0.0.1";
|
|
727
|
+
const recorderPath = params.recorderPath ?? path.resolve(".crabline", "servers", "zalo.jsonl");
|
|
727
728
|
const state = {
|
|
728
729
|
activeWebhookRequests: new Set(),
|
|
729
730
|
activeWebhookValidations: new Set(),
|
|
@@ -739,10 +740,10 @@ export async function startZaloServer(params = {}) {
|
|
|
739
740
|
maxPendingInboundEvents: resolveMaxPendingInboundEvents(params.maxPendingInboundEvents),
|
|
740
741
|
nextMessage: 1,
|
|
741
742
|
nextUpdateOrder: 1,
|
|
742
|
-
onEvent: params.onEvent,
|
|
743
|
+
recorder: createServerRecorder({ recorderPath, onEvent: params.onEvent }),
|
|
743
744
|
pendingInboundAdmissions: 0,
|
|
744
745
|
pendingRequest: undefined,
|
|
745
|
-
recorderPath
|
|
746
|
+
recorderPath,
|
|
746
747
|
retainedUpdateBytes: 0,
|
|
747
748
|
retainedUpdateCount: 0,
|
|
748
749
|
reservedUpdateOrders: new Set(),
|
|
@@ -801,7 +802,7 @@ export async function startZaloServer(params = {}) {
|
|
|
801
802
|
version: 1,
|
|
802
803
|
};
|
|
803
804
|
return {
|
|
804
|
-
async
|
|
805
|
+
close: createServerClose(state.recorder, async () => {
|
|
805
806
|
state.closing = true;
|
|
806
807
|
for (const request of state.activeWebhookRequests) {
|
|
807
808
|
request.destroy(new Error("Zalo server is shutting down."));
|
|
@@ -813,7 +814,7 @@ export async function startZaloServer(params = {}) {
|
|
|
813
814
|
settlePendingUpdate(state, state.pendingRequest, { kind: "shutdown" });
|
|
814
815
|
}
|
|
815
816
|
await httpServer.close();
|
|
816
|
-
},
|
|
817
|
+
}),
|
|
817
818
|
manifest,
|
|
818
819
|
};
|
|
819
820
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zalo.js","sourceRoot":"","sources":["../../../src/servers/zalo.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n validateHeaderValue,\n type ClientRequest,\n type IncomingMessage,\n type ServerResponse,\n} from \"node:http\";\nimport path from \"node:path\";\nimport {\n adminAuthError,\n drainRequestBody,\n hasAdminToken,\n InvalidJsonBodyError,\n isJsonObject,\n isLoopbackHost,\n jsonResponse,\n parseUnknownRequestBody,\n queryRecord,\n readTrimmedString,\n RequestBodyTooLargeError,\n startHttpJsonServer,\n type HttpJsonHandlerResult,\n type ServerRequestEvent,\n} from \"./http.js\";\nimport { recordServerEvent, type ServerEventObserver } from \"./recorder.js\";\nimport { resolveMaxPendingInboundEvents } from \"./pending-events.js\";\nimport {\n postWebhookRequest,\n validateWebhookTarget,\n type WebhookAddress,\n} from \"./webhook-target.js\";\n\ntype ZaloChatType = \"GROUP\" | \"PRIVATE\";\n\nconst DEFAULT_WEBHOOK_DELIVERY_TIMEOUT_MS = 5_000;\nconst DEFAULT_MAX_PENDING_INBOUND_BYTES = 64 * 1024 * 1024;\nconst MAX_ACTIVE_ZALO_WEBHOOK_VALIDATIONS = 8;\nconst MAX_ZALO_REDACTION_DEPTH = 32;\nconst MAX_WEBHOOK_DELIVERY_TIMEOUT_MS = 30_000;\nconst MAX_ZALO_WEBHOOK_SECRET_BYTES = 256;\n\ntype ZaloServerEvent = ServerRequestEvent & {\n accepted?: boolean | undefined;\n};\n\ntype ZaloMessage = {\n chat: { chat_type: ZaloChatType; id: string };\n date: number;\n from: { display_name: string; id: string; is_bot: boolean };\n message_id: string;\n photo_url?: string;\n text?: string;\n};\n\ntype ZaloUpdate = {\n event_name: \"message.image.received\" | \"message.text.received\";\n message: ZaloMessage;\n};\n\ntype PendingUpdateResult =\n | { kind: \"conflict\" | \"disconnect\" | \"shutdown\" | \"timeout\" }\n | { kind: \"update\"; update: ZaloUpdate };\n\ntype PendingUpdateRequest = {\n active: boolean;\n onDisconnect(): void;\n request: IncomingMessage;\n response: ServerResponse;\n resolve(result: PendingUpdateResult): void;\n timeout: NodeJS.Timeout | undefined;\n};\n\ntype ZaloValidatedWebhookTarget = {\n addresses: WebhookAddress[] | undefined;\n};\n\ntype ZaloServerState = {\n activeWebhookRequests: Set<ClientRequest>;\n activeWebhookValidations: Set<AbortController>;\n adminToken: string;\n allowLoopbackHttpWebhook: boolean;\n botId: string;\n botName: string;\n botToken: string;\n closing: boolean;\n inboundAdmission: Promise<void>;\n maxPendingInboundBytes: number;\n maxPendingInboundEvents: number;\n nextMessage: number;\n nextUpdateOrder: number;\n onEvent: ServerEventObserver | undefined;\n pendingInboundAdmissions: number;\n pendingRequest: PendingUpdateRequest | undefined;\n recorderPath: string;\n retainedUpdateBytes: number;\n retainedUpdateCount: number;\n reservedUpdateOrders: Set<number>;\n restrictWebhookTargets: boolean;\n updateBytes: WeakMap<ZaloUpdate, number>;\n updateOrders: WeakMap<ZaloUpdate, number>;\n updates: ZaloUpdate[];\n webhook: { secretToken: string; updatedAt: number; url: string } | undefined;\n webhookDeliveryTimeoutMs: number;\n webhookTransitionPending: boolean;\n};\n\nexport type ZaloServerManifest = {\n adminToken: string;\n baseUrl: string;\n botId: string;\n botToken: string;\n endpoints: {\n adminInboundUrl: string;\n apiRoot: string;\n };\n env: {\n ZALO_API_URL: string;\n ZALO_BOT_TOKEN: string;\n };\n provider: \"zalo\";\n recorderPath: string;\n version: 1;\n};\n\nexport type StartedZaloServer = {\n close(): Promise<void>;\n manifest: ZaloServerManifest;\n};\n\nexport type StartZaloServerParams = {\n adminToken?: string | undefined;\n botId?: string | undefined;\n botName?: string | undefined;\n botToken?: string | undefined;\n host?: string | undefined;\n onEvent?: ServerEventObserver | undefined;\n port?: number | undefined;\n recorderPath?: string | undefined;\n maxPendingInboundBytes?: number | undefined;\n maxPendingInboundEvents?: number | undefined;\n webhookDeliveryTimeoutMs?: number | undefined;\n};\n\nasync function appendEvent(state: ZaloServerState, event: ZaloServerEvent): Promise<void> {\n await recordServerEvent({ event, onEvent: state.onEvent, recorderPath: state.recorderPath });\n}\n\nfunction zaloOk(result?: unknown): Response {\n return jsonResponse(result === undefined ? { ok: true } : { ok: true, result });\n}\n\nfunction zaloError(description: string, status: number): Response {\n return jsonResponse({ description, error_code: status, ok: false }, status);\n}\n\nfunction messageId(state: ZaloServerState): string {\n return `${Date.now().toString(16)}${(state.nextMessage++).toString(16).padStart(6, \"0\")}`;\n}\n\nfunction readChatType(value: unknown): ZaloChatType {\n return readTrimmedString(value)?.toUpperCase() === \"GROUP\" ? \"GROUP\" : \"PRIVATE\";\n}\n\nfunction requestParams(url: URL, body: Record<string, unknown>): Record<string, unknown> {\n return { ...Object.fromEntries(url.searchParams.entries()), ...body };\n}\n\nconst SENSITIVE_PARAM_NAMES = new Set([\n \"accesskey\",\n \"accesstoken\",\n \"apikey\",\n \"auth\",\n \"authorization\",\n \"authtoken\",\n \"bearertoken\",\n \"clientsecret\",\n \"consumersecret\",\n \"credential\",\n \"credentials\",\n \"idtoken\",\n \"key\",\n \"oauthtoken\",\n \"password\",\n \"passwd\",\n \"privatekey\",\n \"refreshtoken\",\n \"secret\",\n \"secretkey\",\n \"secrettoken\",\n \"sessiontoken\",\n \"signature\",\n \"signingsecret\",\n \"token\",\n \"webhooksecret\",\n]);\n\nfunction isSensitiveParam(name: string): boolean {\n const normalizedName = name.normalize(\"NFKC\");\n const canonicalName = normalizedName.replace(/[^A-Za-z0-9]/gu, \"\").toLowerCase();\n return (\n SENSITIVE_PARAM_NAMES.has(canonicalName) ||\n /[a-z0-9](?:credentials?|keys?|passwords?|passwds?|secrets?|signatures?|tokens?)$/u.test(\n canonicalName,\n ) ||\n /(?:^|[_-])(?:access[_-]?token|api[_-]?key|authorization|key|password|secret|signature|token)(?:$|[_-])/iu.test(\n normalizedName,\n )\n );\n}\n\nfunction isUrlParam(name: string): boolean {\n return /(?:urls?|uris?)$/iu.test(name.normalize(\"NFKC\").replace(/[^A-Za-z0-9]/gu, \"\"));\n}\n\nfunction redactParamValue(value: unknown, key: string, depth: number): unknown {\n if (isSensitiveParam(key)) {\n return \"<redacted>\";\n }\n if (Array.isArray(value)) {\n if (depth >= MAX_ZALO_REDACTION_DEPTH) {\n return \"<redacted>\";\n }\n return value.map((entry) => redactParamValue(entry, key, depth + 1));\n }\n if (isJsonObject(value)) {\n if (depth >= MAX_ZALO_REDACTION_DEPTH) {\n return \"<redacted>\";\n }\n return redactParams(value, depth + 1);\n }\n if (\n typeof value === \"string\" &&\n (isUrlParam(key) || /^(?:\\s*[a-z][a-z0-9+.-]*:)?\\/\\//iu.test(value))\n ) {\n return redactUrlCredentials(value);\n }\n return value;\n}\n\nfunction redactParams(params: Record<string, unknown>, depth = 0): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(params).map(([key, value]) => [key, redactParamValue(value, key, depth)]),\n );\n}\n\nfunction redactSensitiveSearchParams(searchParams: URLSearchParams): boolean {\n let redacted = false;\n for (const key of searchParams.keys()) {\n if (isSensitiveParam(key)) {\n searchParams.set(key, \"<redacted>\");\n redacted = true;\n }\n }\n return redacted;\n}\n\nfunction redactUrlFragment(value: string): string {\n const fragmentStart = value.indexOf(\"#\");\n return fragmentStart < 0 ? value : `${value.slice(0, fragmentStart)}#<redacted>`;\n}\n\nfunction redactMalformedUrlCredentials(value: string): string {\n const credentialRedacted = value.replace(\n /^(\\s*)((?:[a-z][a-z0-9+.-]*:)?\\/\\/)[^/?#]*@/iu,\n \"$1$2<redacted>@\",\n );\n if (credentialRedacted === value) {\n return \"<redacted>\";\n }\n const fragmentRedacted = redactUrlFragment(credentialRedacted);\n const queryStart = fragmentRedacted.indexOf(\"?\");\n const fragmentStart = fragmentRedacted.indexOf(\"#\", queryStart + 1);\n if (queryStart < 0 || (fragmentStart >= 0 && fragmentStart < queryStart)) {\n return fragmentRedacted;\n }\n const queryEnd = fragmentStart >= 0 ? fragmentStart : fragmentRedacted.length;\n const searchParams = new URLSearchParams(fragmentRedacted.slice(queryStart + 1, queryEnd));\n if (!redactSensitiveSearchParams(searchParams)) {\n return fragmentRedacted;\n }\n const search = searchParams.toString().replaceAll(\"%3Credacted%3E\", \"<redacted>\");\n return `${fragmentRedacted.slice(0, queryStart)}?${search}${fragmentRedacted.slice(queryEnd)}`;\n}\n\nfunction redactUrlCredentials(value: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return redactMalformedUrlCredentials(value);\n }\n const hasCredentials = Boolean(url.username || url.password);\n const redactedQuery = redactSensitiveSearchParams(url.searchParams);\n const hasFragment = url.hash.length > 0;\n if (!hasCredentials && !redactedQuery) {\n return hasFragment ? redactUrlFragment(value) : value;\n }\n const search = url.search.replaceAll(\"%3Credacted%3E\", \"<redacted>\");\n return `${url.protocol}//${hasCredentials ? \"<redacted>@\" : \"\"}${url.host}${url.pathname}${search}${hasFragment ? \"#<redacted>\" : \"\"}`;\n}\n\nfunction requireParam(body: Record<string, unknown>, name: string): string | Response {\n return readTrimmedString(body[name]) ?? zaloError(`${name} is required`, 400);\n}\n\nfunction firstError(...values: Array<string | Response>): Response | undefined {\n return values.find((value): value is Response => value instanceof Response);\n}\n\nfunction webhookDeliveryTimeoutMs(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value)) {\n return DEFAULT_WEBHOOK_DELIVERY_TIMEOUT_MS;\n }\n return Math.max(1, Math.min(Math.floor(value), MAX_WEBHOOK_DELIVERY_TIMEOUT_MS));\n}\n\nfunction maxPendingInboundBytes(value: number | undefined): number {\n if (value === undefined) {\n return DEFAULT_MAX_PENDING_INBOUND_BYTES;\n }\n if (!Number.isSafeInteger(value) || value < 1) {\n throw new Error(\"maxPendingInboundBytes must be a positive safe integer.\");\n }\n return value;\n}\n\nasync function validateWebhookUrl(\n url: URL,\n state: Pick<ZaloServerState, \"allowLoopbackHttpWebhook\" | \"restrictWebhookTargets\">,\n signal?: AbortSignal,\n): Promise<Response | ZaloValidatedWebhookTarget> {\n const target = await validateWebhookTarget({\n allowLoopbackHttp: state.allowLoopbackHttpWebhook,\n restrictPrivateAddresses: state.restrictWebhookTargets,\n signal,\n url,\n });\n if (\"error\" in target) {\n return target.error === \"unresolvable\"\n ? zaloError(\"url host could not be resolved\", 400)\n : target.error === \"private-address\"\n ? zaloError(\"url must not target a private or link-local address\", 400)\n : zaloError(\"url must use HTTPS\", 400);\n }\n return target;\n}\n\nfunction validateZaloWebhookSecret(secretToken: string): Response | undefined {\n if (Buffer.byteLength(secretToken) > MAX_ZALO_WEBHOOK_SECRET_BYTES) {\n return zaloError(`secret_token must not exceed ${MAX_ZALO_WEBHOOK_SECRET_BYTES} bytes`, 400);\n }\n try {\n validateHeaderValue(\"x-bot-api-secret-token\", secretToken);\n } catch {\n return zaloError(\"secret_token contains invalid HTTP header characters\", 400);\n }\n return undefined;\n}\n\nasync function validateWebhookUrlWithDeadline(\n url: URL,\n state: ZaloServerState,\n deadlineAt: number,\n): Promise<Response | ZaloValidatedWebhookTarget> {\n const remainingMs = deadlineAt - Date.now();\n if (remainingMs <= 0) {\n throw webhookTimeoutError(state.webhookDeliveryTimeoutMs);\n }\n const validation = new AbortController();\n state.activeWebhookValidations.add(validation);\n const timer = setTimeout(\n () => validation.abort(webhookTimeoutError(state.webhookDeliveryTimeoutMs)),\n remainingMs,\n );\n timer.unref();\n try {\n return await validateWebhookUrl(url, state, validation.signal);\n } finally {\n clearTimeout(timer);\n state.activeWebhookValidations.delete(validation);\n }\n}\n\nfunction webhookTimeoutError(timeoutMs: number): DOMException {\n return new DOMException(`Webhook delivery timed out after ${timeoutMs}ms`, \"TimeoutError\");\n}\n\n/** @internal */\nexport async function postZaloWebhook(params: {\n activeRequests?: Set<ClientRequest>;\n addresses?: WebhookAddress[] | undefined;\n body: string;\n shouldCancel?: (() => boolean) | undefined;\n timeoutMs: number;\n url: URL;\n verificationValue: string;\n}): Promise<number> {\n const activeRequests = params.activeRequests ?? new Set<ClientRequest>();\n const deadlineAt = Date.now() + params.timeoutMs;\n const addresses =\n params.addresses && params.addresses.length > 0 ? params.addresses : [undefined];\n let lastError: unknown;\n for (const [index, address] of addresses.entries()) {\n if (params.shouldCancel?.()) {\n throw new Error(\"Webhook delivery cancelled.\");\n }\n const remainingMs = deadlineAt - Date.now();\n if (remainingMs <= 0) {\n throw webhookTimeoutError(params.timeoutMs);\n }\n const attemptsRemaining = addresses.length - index;\n const attemptTimeoutMs = Math.max(1, Math.floor(remainingMs / attemptsRemaining));\n try {\n return await postWebhookRequest({\n activeRequests,\n address,\n body: params.body,\n headerEntries: [[\"x-bot-api-secret-token\", params.verificationValue]],\n timeoutMs: attemptTimeoutMs,\n url: params.url,\n });\n } catch (error) {\n if (params.shouldCancel?.()) {\n throw error;\n }\n lastError = error;\n if (\n error instanceof DOMException &&\n error.name === \"TimeoutError\" &&\n attemptsRemaining === 1\n ) {\n throw webhookTimeoutError(params.timeoutMs);\n }\n }\n }\n throw lastError;\n}\n\nfunction nextUpdate(\n request: IncomingMessage,\n response: ServerResponse,\n state: ZaloServerState,\n): HttpJsonHandlerResult | undefined {\n if (request.aborted || request.socket.destroyed || response.destroyed) {\n return undefined;\n }\n const update = state.updates[0];\n if (!update) {\n return undefined;\n }\n if (hasEarlierReservedPollingUpdate(state, update)) {\n return undefined;\n }\n state.updates.shift();\n reservePollingUpdate(state, update);\n return reservedUpdateResponse(state, update);\n}\n\nfunction pollingUpdateOrder(state: ZaloServerState, update: ZaloUpdate): number {\n const existing = state.updateOrders.get(update);\n if (existing !== undefined) {\n return existing;\n }\n const order = state.nextUpdateOrder++;\n state.updateOrders.set(update, order);\n return order;\n}\n\nfunction pollingUpdateBytes(state: ZaloServerState, update: ZaloUpdate): number {\n const existing = state.updateBytes.get(update);\n if (existing !== undefined) {\n return existing;\n }\n const bytes = Buffer.byteLength(JSON.stringify(update), \"utf8\");\n state.updateBytes.set(update, bytes);\n return bytes;\n}\n\nfunction retainPollingUpdate(state: ZaloServerState, update: ZaloUpdate): boolean {\n const bytes = pollingUpdateBytes(state, update);\n if (\n state.retainedUpdateCount >= state.maxPendingInboundEvents ||\n state.retainedUpdateBytes + bytes > state.maxPendingInboundBytes\n ) {\n state.updateBytes.delete(update);\n return false;\n }\n state.retainedUpdateCount += 1;\n state.retainedUpdateBytes += bytes;\n return true;\n}\n\nfunction releasePollingUpdate(state: ZaloServerState, update: ZaloUpdate): void {\n const bytes = state.updateBytes.get(update);\n if (bytes === undefined) {\n throw new Error(\"Zalo polling update retention was released without a reservation.\");\n }\n state.updateBytes.delete(update);\n state.retainedUpdateCount -= 1;\n state.retainedUpdateBytes -= bytes;\n}\n\nfunction queuePollingUpdate(state: ZaloServerState, update: ZaloUpdate): void {\n const order = pollingUpdateOrder(state, update);\n const insertionIndex = state.updates.findIndex(\n (queued) => pollingUpdateOrder(state, queued) > order,\n );\n if (insertionIndex < 0) {\n state.updates.push(update);\n } else {\n state.updates.splice(insertionIndex, 0, update);\n }\n}\n\nfunction hasEarlierReservedPollingUpdate(state: ZaloServerState, update: ZaloUpdate): boolean {\n const order = pollingUpdateOrder(state, update);\n return [...state.reservedUpdateOrders].some((reservedOrder) => reservedOrder < order);\n}\n\nfunction reservePollingUpdate(state: ZaloServerState, update: ZaloUpdate): void {\n const order = pollingUpdateOrder(state, update);\n state.reservedUpdateOrders.add(order);\n}\n\nfunction flushPendingPollingUpdate(state: ZaloServerState): void {\n const pending = state.pendingRequest;\n const update = state.updates[0];\n if (!pending || !update) {\n return;\n }\n if (!isPendingUpdateRequestLive(pending)) {\n settlePendingUpdate(state, pending, { kind: \"disconnect\" });\n return;\n }\n if (hasEarlierReservedPollingUpdate(state, update)) {\n return;\n }\n state.updates.shift();\n reservePollingUpdate(state, update);\n settlePendingUpdate(state, pending, { kind: \"update\", update });\n}\n\nfunction reservedUpdateResponse(state: ZaloServerState, update: ZaloUpdate): HttpJsonHandlerResult {\n let settled = false;\n const releaseReservation = () => {\n if (settled) {\n return false;\n }\n settled = true;\n state.reservedUpdateOrders.delete(pollingUpdateOrder(state, update));\n return true;\n };\n return {\n onWriteFailure() {\n if (!releaseReservation()) {\n return;\n }\n queuePollingUpdate(state, update);\n flushPendingPollingUpdate(state);\n },\n onWriteSuccess() {\n if (releaseReservation()) {\n releasePollingUpdate(state, update);\n flushPendingPollingUpdate(state);\n }\n },\n response: zaloOk(update),\n };\n}\n\nfunction settlePendingUpdate(\n state: ZaloServerState,\n pending: PendingUpdateRequest,\n result: PendingUpdateResult,\n): boolean {\n if (!pending.active) {\n return false;\n }\n pending.active = false;\n if (state.pendingRequest === pending) {\n state.pendingRequest = undefined;\n }\n if (pending.timeout) {\n clearTimeout(pending.timeout);\n }\n pending.request.socket.off(\"close\", pending.onDisconnect);\n pending.request.off(\"aborted\", pending.onDisconnect);\n pending.response.off(\"close\", pending.onDisconnect);\n pending.resolve(result);\n return true;\n}\n\nfunction isPendingUpdateRequestLive(pending: PendingUpdateRequest): boolean {\n return (\n !pending.request.aborted && !pending.request.socket.destroyed && !pending.response.destroyed\n );\n}\n\nasync function waitForUpdate(\n request: IncomingMessage,\n response: ServerResponse,\n state: ZaloServerState,\n timeoutSeconds: number,\n): Promise<HttpJsonHandlerResult> {\n if (request.aborted || request.socket.destroyed || response.destroyed) {\n return zaloError(\"Client closed request\", 499);\n }\n const previous = state.pendingRequest;\n if (previous) {\n settlePendingUpdate(state, previous, { kind: \"conflict\" });\n }\n const queued = nextUpdate(request, response, state);\n if (queued) {\n return queued;\n }\n if (timeoutSeconds <= 0) {\n return zaloError(\"Request timeout\", 408);\n }\n const result = await new Promise<PendingUpdateResult>((resolve) => {\n const pending: PendingUpdateRequest = {\n active: true,\n onDisconnect: () => {\n settlePendingUpdate(state, pending, { kind: \"disconnect\" });\n },\n request,\n response,\n resolve,\n timeout: undefined,\n };\n state.pendingRequest = pending;\n request.once(\"aborted\", pending.onDisconnect);\n request.socket.once(\"close\", pending.onDisconnect);\n response.once(\"close\", pending.onDisconnect);\n pending.timeout = setTimeout(() => {\n settlePendingUpdate(state, pending, { kind: \"timeout\" });\n }, timeoutSeconds * 1000);\n pending.timeout.unref();\n if (request.socket.destroyed || response.destroyed) {\n pending.onDisconnect();\n }\n });\n switch (result.kind) {\n case \"conflict\":\n return zaloError(\"Conflict: terminated by other getUpdates request\", 409);\n case \"disconnect\":\n return zaloError(\"Client closed request\", 499);\n case \"shutdown\":\n return zaloError(\"Server shutting down\", 503);\n case \"timeout\":\n return zaloError(\"Request timeout\", 408);\n case \"update\":\n return reservedUpdateResponse(state, result.update);\n }\n}\n\nfunction deliverPollingUpdate(state: ZaloServerState, update: ZaloUpdate): void {\n pollingUpdateOrder(state, update);\n if (state.updates.length > 0 || hasEarlierReservedPollingUpdate(state, update)) {\n queuePollingUpdate(state, update);\n flushPendingPollingUpdate(state);\n return;\n }\n const pending = state.pendingRequest;\n if (pending) {\n if (isPendingUpdateRequestLive(pending)) {\n reservePollingUpdate(state, update);\n settlePendingUpdate(state, pending, { kind: \"update\", update });\n return;\n }\n settlePendingUpdate(state, pending, { kind: \"disconnect\" });\n }\n queuePollingUpdate(state, update);\n}\n\nasync function deliverWebhookUpdate(\n state: ZaloServerState,\n webhook: NonNullable<ZaloServerState[\"webhook\"]>,\n update: ZaloUpdate,\n): Promise<Response | undefined> {\n const deadlineAt = Date.now() + state.webhookDeliveryTimeoutMs;\n const url = new URL(webhook.url);\n let target: Response | ZaloValidatedWebhookTarget;\n try {\n target = await validateWebhookUrlWithDeadline(url, state, deadlineAt);\n } catch (error) {\n if (error instanceof DOMException && error.name === \"TimeoutError\") {\n return zaloError(`Webhook delivery timed out after ${state.webhookDeliveryTimeoutMs}ms`, 502);\n }\n throw error;\n }\n if (target instanceof Response) {\n return target;\n }\n try {\n const remainingMs = deadlineAt - Date.now();\n if (remainingMs <= 0) {\n throw webhookTimeoutError(state.webhookDeliveryTimeoutMs);\n }\n const status = await postZaloWebhook({\n activeRequests: state.activeWebhookRequests,\n addresses: target.addresses,\n body: JSON.stringify(update),\n shouldCancel: () => state.closing,\n timeoutMs: remainingMs,\n url,\n verificationValue: webhook.secretToken,\n });\n if (status < 200 || status >= 300) {\n return zaloError(`Webhook delivery failed with HTTP ${status}`, 502);\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === \"TimeoutError\") {\n return zaloError(`Webhook delivery timed out after ${state.webhookDeliveryTimeoutMs}ms`, 502);\n }\n return zaloError(\n `Webhook delivery failed: ${error instanceof Error ? error.message : String(error)}`,\n 502,\n );\n }\n return undefined;\n}\n\nasync function handleAdminInbound(\n request: IncomingMessage,\n state: ZaloServerState,\n url: URL,\n): Promise<Response> {\n if (!hasAdminToken(request, state.adminToken)) {\n drainRequestBody(request);\n return adminAuthError();\n }\n if (state.webhookTransitionPending) {\n drainRequestBody(request);\n return zaloError(\"Webhook configuration is in progress\", 409);\n }\n const retainedUpdates = state.webhook?.url === undefined ? state.retainedUpdateCount : 0;\n if (retainedUpdates + state.pendingInboundAdmissions >= state.maxPendingInboundEvents) {\n drainRequestBody(request);\n return zaloError(\n `Pending inbound queue is full (${state.maxPendingInboundEvents} updates)`,\n 429,\n );\n }\n state.pendingInboundAdmissions += 1;\n let releaseAdmission!: () => void;\n const previousAdmission = state.inboundAdmission;\n state.inboundAdmission = new Promise<void>((resolve) => {\n releaseAdmission = resolve;\n });\n let admissionPending = true;\n let retainedPollingUpdate: ZaloUpdate | undefined;\n try {\n const parsedBody = await parseUnknownRequestBody(request);\n await previousAdmission;\n if (!isJsonObject(parsedBody)) {\n return zaloError(\"Bad Request: can't parse JSON object\", 400);\n }\n const body = parsedBody;\n const chatId = requireParam(body, \"chatId\");\n const senderId = requireParam(body, \"senderId\");\n const text = requireParam(body, \"text\");\n if (chatId instanceof Response || senderId instanceof Response || text instanceof Response) {\n return [chatId, senderId, text].find((value) => value instanceof Response) as Response;\n }\n const webhook = state.webhook;\n const update: ZaloUpdate = {\n event_name: \"message.text.received\",\n message: {\n chat: { chat_type: readChatType(body.chatType), id: chatId },\n date: Date.now(),\n from: {\n display_name: readTrimmedString(body.senderName) ?? senderId,\n id: senderId,\n is_bot: false,\n },\n message_id: messageId(state),\n text,\n },\n };\n if (!webhook?.url) {\n if (!retainPollingUpdate(state, update)) {\n return zaloError(\n `Pending inbound queue is full (${state.maxPendingInboundEvents} updates)`,\n 429,\n );\n }\n retainedPollingUpdate = update;\n state.pendingInboundAdmissions -= 1;\n admissionPending = false;\n }\n await appendEvent(state, {\n at: new Date().toISOString(),\n body: redactParams(body),\n method: request.method ?? \"POST\",\n path: url.pathname,\n query: redactParams(queryRecord(url)) as Record<string, string>,\n type: \"admin\",\n });\n if (webhook?.url) {\n const error = await deliverWebhookUpdate(state, webhook, update);\n if (error) {\n return error;\n }\n } else {\n deliverPollingUpdate(state, update);\n retainedPollingUpdate = undefined;\n }\n return zaloOk(update);\n } finally {\n if (retainedPollingUpdate) {\n releasePollingUpdate(state, retainedPollingUpdate);\n }\n await previousAdmission;\n releaseAdmission();\n if (admissionPending) {\n state.pendingInboundAdmissions -= 1;\n }\n }\n}\n\nasync function handleZaloMethod(\n request: IncomingMessage,\n response: ServerResponse,\n state: ZaloServerState,\n url: URL,\n method: string,\n): Promise<HttpJsonHandlerResult> {\n const parsedBody = await parseUnknownRequestBody(request);\n if (!isJsonObject(parsedBody)) {\n return zaloError(\"Bad Request: can't parse JSON object\", 400);\n }\n const body = requestParams(url, parsedBody);\n const event: ZaloServerEvent = {\n at: new Date().toISOString(),\n ...(Object.keys(body).length > 0 ? { body: redactParams(body) } : {}),\n method: request.method ?? \"GET\",\n path: `/bot<redacted>/${method}`,\n query: redactParams(queryRecord(url)) as Record<string, string>,\n type: \"api\",\n };\n\n if (method === \"sendMessage\" || method === \"sendPhoto\") {\n const chatId = requireParam(body, \"chat_id\");\n const content = requireParam(body, method === \"sendMessage\" ? \"text\" : \"photo\");\n const error = firstError(chatId, content);\n const sendResponse = error ?? zaloOk({ date: Date.now(), message_id: messageId(state) });\n event.accepted = sendResponse.ok;\n try {\n await appendEvent(state, event);\n } catch (appendError) {\n if (!event.accepted) {\n throw appendError;\n }\n }\n return sendResponse;\n }\n\n if (method === \"getMe\") {\n const getMeResponse = zaloOk({\n account_name: state.botName,\n account_type: \"BASIC\",\n can_join_groups: true,\n id: state.botId,\n });\n event.accepted = getMeResponse.ok;\n await appendEvent(state, event);\n return getMeResponse;\n }\n\n if (method !== \"setWebhook\") {\n await appendEvent(state, event);\n }\n if (method === \"getUpdates\") {\n if (state.webhook?.url || state.webhookTransitionPending) {\n return zaloError(\"Webhook is configured; delete it before using getUpdates\", 400);\n }\n const parsedTimeout = Number(readTrimmedString(body.timeout) ?? \"30\");\n const timeout = Number.isFinite(parsedTimeout) ? Math.max(0, Math.min(parsedTimeout, 50)) : 30;\n return await waitForUpdate(request, response, state, timeout);\n }\n if (method === \"sendChatAction\") {\n const chatId = requireParam(body, \"chat_id\");\n const action = requireParam(body, \"action\");\n const error = firstError(chatId, action);\n if (error) {\n return error;\n }\n if (action !== \"typing\" && action !== \"upload_photo\") {\n return zaloError(\"action must be typing or upload_photo\", 400);\n }\n return zaloOk();\n }\n if (method === \"setWebhook\") {\n const reject = async (result: Response): Promise<Response> => {\n if (isJsonObject(event.body) && \"url\" in event.body) {\n event.body.url = \"<redacted>\";\n }\n await appendEvent(state, event);\n return result;\n };\n const webhookUrl = requireParam(body, \"url\");\n const secretToken = requireParam(body, \"secret_token\");\n const error = firstError(webhookUrl, secretToken);\n if (error) {\n return await reject(error);\n }\n if (typeof webhookUrl !== \"string\" || typeof secretToken !== \"string\") {\n return await reject(zaloError(\"Invalid webhook parameters\", 400));\n }\n const secretError = validateZaloWebhookSecret(secretToken);\n if (secretError) {\n return await reject(secretError);\n }\n let parsedUrl: URL;\n try {\n parsedUrl = new URL(webhookUrl);\n } catch {\n return await reject(zaloError(\"url must be a valid HTTPS URL\", 400));\n }\n if (state.activeWebhookValidations.size >= MAX_ACTIVE_ZALO_WEBHOOK_VALIDATIONS) {\n return await reject(zaloError(\"Too many webhook validations\", 429));\n }\n let target: Response | ZaloValidatedWebhookTarget;\n try {\n target = await validateWebhookUrlWithDeadline(\n parsedUrl,\n state,\n Date.now() + state.webhookDeliveryTimeoutMs,\n );\n } catch {\n return await reject(zaloError(\"url host could not be resolved\", 400));\n }\n if (target instanceof Response) {\n return await reject(target);\n }\n if (state.webhookTransitionPending || state.reservedUpdateOrders.size > 0) {\n return await reject(zaloError(\"Polling deliveries are still in progress\", 409));\n }\n const webhook = { secretToken, updatedAt: Date.now(), url: parsedUrl.href };\n state.webhookTransitionPending = true;\n try {\n await state.inboundAdmission;\n if (state.reservedUpdateOrders.size > 0) {\n return await reject(zaloError(\"Polling deliveries are still in progress\", 409));\n }\n await appendEvent(state, event);\n if (state.pendingRequest) {\n settlePendingUpdate(state, state.pendingRequest, { kind: \"conflict\" });\n }\n state.webhook = webhook;\n return zaloOk({ updated_at: webhook.updatedAt, url: webhook.url });\n } finally {\n state.webhookTransitionPending = false;\n }\n }\n if (method === \"deleteWebhook\") {\n const updatedAt = Date.now();\n state.webhook = undefined;\n return zaloOk({ updated_at: updatedAt, url: \"\" });\n }\n if (method === \"getWebhookInfo\") {\n return zaloOk(\n state.webhook ? { updated_at: state.webhook.updatedAt, url: state.webhook.url } : { url: \"\" },\n );\n }\n return zaloError(\"Bad request - invalid API name\", 400);\n}\n\nexport async function startZaloServer(\n params: StartZaloServerParams = {},\n): Promise<StartedZaloServer> {\n const host = params.host ?? \"127.0.0.1\";\n const state: ZaloServerState = {\n activeWebhookRequests: new Set(),\n activeWebhookValidations: new Set(),\n adminToken: params.adminToken ?? randomBytes(24).toString(\"hex\"),\n allowLoopbackHttpWebhook: isLoopbackHost(host),\n botId: params.botId ?? \"1459232241454765289\",\n botName: params.botName ?? \"bot.crabline\",\n botToken:\n params.botToken ??\n (isLoopbackHost(host) ? \"crabline-zalo-bot-token\" : randomBytes(32).toString(\"base64url\")),\n closing: false,\n inboundAdmission: Promise.resolve(),\n maxPendingInboundBytes: maxPendingInboundBytes(params.maxPendingInboundBytes),\n maxPendingInboundEvents: resolveMaxPendingInboundEvents(params.maxPendingInboundEvents),\n nextMessage: 1,\n nextUpdateOrder: 1,\n onEvent: params.onEvent,\n pendingInboundAdmissions: 0,\n pendingRequest: undefined,\n recorderPath: params.recorderPath ?? path.resolve(\".crabline\", \"servers\", \"zalo.jsonl\"),\n retainedUpdateBytes: 0,\n retainedUpdateCount: 0,\n reservedUpdateOrders: new Set(),\n restrictWebhookTargets: true,\n updateBytes: new WeakMap(),\n updateOrders: new WeakMap(),\n updates: [],\n webhook: undefined,\n webhookDeliveryTimeoutMs: webhookDeliveryTimeoutMs(params.webhookDeliveryTimeoutMs),\n webhookTransitionPending: false,\n };\n const httpServer = await startHttpJsonServer({\n handle: async (request, response) => {\n const url = new URL(request.url ?? \"/\", `http://${request.headers.host ?? host}`);\n if (request.method === \"POST\" && url.pathname === \"/crabline/zalo/inbound\") {\n return await handleAdminInbound(request, state, url);\n }\n const match = /^\\/bot([^/]+)\\/([^/]+)$/u.exec(url.pathname);\n if (!match || (request.method !== \"GET\" && request.method !== \"POST\")) {\n return zaloError(\"Not found\", 404);\n }\n if (match[1] !== state.botToken) {\n drainRequestBody(request);\n return zaloError(\"Unauthorized\", 401);\n }\n return await handleZaloMethod(request, response, state, url, match[2] ?? \"\");\n },\n handleError: (error) => {\n if (error instanceof InvalidJsonBodyError) {\n return zaloError(\"Bad Request: can't parse JSON object\", 400);\n }\n if (error instanceof RequestBodyTooLargeError) {\n return zaloError(\"Request Entity Too Large\", 413);\n }\n return undefined;\n },\n host,\n port: params.port ?? 0,\n serverName: \"Zalo\",\n });\n const manifest: ZaloServerManifest = {\n adminToken: state.adminToken,\n baseUrl: httpServer.baseUrl,\n botId: state.botId,\n botToken: state.botToken,\n endpoints: {\n adminInboundUrl: `${httpServer.baseUrl}/crabline/zalo/inbound`,\n apiRoot: httpServer.baseUrl,\n },\n env: {\n ZALO_API_URL: httpServer.baseUrl,\n ZALO_BOT_TOKEN: state.botToken,\n },\n provider: \"zalo\",\n recorderPath: state.recorderPath,\n version: 1,\n };\n return {\n async close() {\n state.closing = true;\n for (const request of state.activeWebhookRequests) {\n request.destroy(new Error(\"Zalo server is shutting down.\"));\n }\n for (const validation of state.activeWebhookValidations) {\n validation.abort(new Error(\"Zalo server is shutting down.\"));\n }\n if (state.pendingRequest) {\n settlePendingUpdate(state, state.pendingRequest, { kind: \"shutdown\" });\n }\n await httpServer.close();\n },\n manifest,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"zalo.js","sourceRoot":"","sources":["../../../src/servers/zalo.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n validateHeaderValue,\n type ClientRequest,\n type IncomingMessage,\n type ServerResponse,\n} from \"node:http\";\nimport path from \"node:path\";\nimport {\n adminAuthError,\n createServerClose,\n drainRequestBody,\n hasAdminToken,\n InvalidJsonBodyError,\n isJsonObject,\n isLoopbackHost,\n jsonResponse,\n parseUnknownRequestBody,\n queryRecord,\n readTrimmedString,\n RequestBodyTooLargeError,\n startHttpJsonServer,\n type HttpJsonHandlerResult,\n type ServerRequestEvent,\n} from \"./http.js\";\nimport { createServerRecorder, type ServerEventObserver, type ServerRecorder } from \"./recorder.js\";\nimport { resolveMaxPendingInboundEvents } from \"./pending-events.js\";\nimport {\n postWebhookRequest,\n validateWebhookTarget,\n type WebhookAddress,\n} from \"./webhook-target.js\";\n\ntype ZaloChatType = \"GROUP\" | \"PRIVATE\";\n\nconst DEFAULT_WEBHOOK_DELIVERY_TIMEOUT_MS = 5_000;\nconst DEFAULT_MAX_PENDING_INBOUND_BYTES = 64 * 1024 * 1024;\nconst MAX_ACTIVE_ZALO_WEBHOOK_VALIDATIONS = 8;\nconst MAX_ZALO_REDACTION_DEPTH = 32;\nconst MAX_WEBHOOK_DELIVERY_TIMEOUT_MS = 30_000;\nconst MAX_ZALO_WEBHOOK_SECRET_BYTES = 256;\n\ntype ZaloServerEvent = ServerRequestEvent & {\n accepted?: boolean | undefined;\n};\n\ntype ZaloMessage = {\n chat: { chat_type: ZaloChatType; id: string };\n date: number;\n from: { display_name: string; id: string; is_bot: boolean };\n message_id: string;\n photo_url?: string;\n text?: string;\n};\n\ntype ZaloUpdate = {\n event_name: \"message.image.received\" | \"message.text.received\";\n message: ZaloMessage;\n};\n\ntype PendingUpdateResult =\n | { kind: \"conflict\" | \"disconnect\" | \"shutdown\" | \"timeout\" }\n | { kind: \"update\"; update: ZaloUpdate };\n\ntype PendingUpdateRequest = {\n active: boolean;\n onDisconnect(): void;\n request: IncomingMessage;\n response: ServerResponse;\n resolve(result: PendingUpdateResult): void;\n timeout: NodeJS.Timeout | undefined;\n};\n\ntype ZaloValidatedWebhookTarget = {\n addresses: WebhookAddress[] | undefined;\n};\n\ntype ZaloServerState = {\n activeWebhookRequests: Set<ClientRequest>;\n activeWebhookValidations: Set<AbortController>;\n adminToken: string;\n allowLoopbackHttpWebhook: boolean;\n botId: string;\n botName: string;\n botToken: string;\n closing: boolean;\n inboundAdmission: Promise<void>;\n maxPendingInboundBytes: number;\n maxPendingInboundEvents: number;\n nextMessage: number;\n nextUpdateOrder: number;\n recorder: ServerRecorder;\n pendingInboundAdmissions: number;\n pendingRequest: PendingUpdateRequest | undefined;\n recorderPath: string;\n retainedUpdateBytes: number;\n retainedUpdateCount: number;\n reservedUpdateOrders: Set<number>;\n restrictWebhookTargets: boolean;\n updateBytes: WeakMap<ZaloUpdate, number>;\n updateOrders: WeakMap<ZaloUpdate, number>;\n updates: ZaloUpdate[];\n webhook: { secretToken: string; updatedAt: number; url: string } | undefined;\n webhookDeliveryTimeoutMs: number;\n webhookTransitionPending: boolean;\n};\n\nexport type ZaloServerManifest = {\n adminToken: string;\n baseUrl: string;\n botId: string;\n botToken: string;\n endpoints: {\n adminInboundUrl: string;\n apiRoot: string;\n };\n env: {\n ZALO_API_URL: string;\n ZALO_BOT_TOKEN: string;\n };\n provider: \"zalo\";\n recorderPath: string;\n version: 1;\n};\n\nexport type StartedZaloServer = {\n close(): Promise<void>;\n manifest: ZaloServerManifest;\n};\n\nexport type StartZaloServerParams = {\n adminToken?: string | undefined;\n botId?: string | undefined;\n botName?: string | undefined;\n botToken?: string | undefined;\n host?: string | undefined;\n onEvent?: ServerEventObserver | undefined;\n port?: number | undefined;\n recorderPath?: string | undefined;\n maxPendingInboundBytes?: number | undefined;\n maxPendingInboundEvents?: number | undefined;\n webhookDeliveryTimeoutMs?: number | undefined;\n};\n\nasync function appendEvent(state: ZaloServerState, event: ZaloServerEvent): Promise<void> {\n await state.recorder.record(event);\n}\n\nfunction zaloOk(result?: unknown): Response {\n return jsonResponse(result === undefined ? { ok: true } : { ok: true, result });\n}\n\nfunction zaloError(description: string, status: number): Response {\n return jsonResponse({ description, error_code: status, ok: false }, status);\n}\n\nfunction messageId(state: ZaloServerState): string {\n return `${Date.now().toString(16)}${(state.nextMessage++).toString(16).padStart(6, \"0\")}`;\n}\n\nfunction readChatType(value: unknown): ZaloChatType {\n return readTrimmedString(value)?.toUpperCase() === \"GROUP\" ? \"GROUP\" : \"PRIVATE\";\n}\n\nfunction requestParams(url: URL, body: Record<string, unknown>): Record<string, unknown> {\n return { ...Object.fromEntries(url.searchParams.entries()), ...body };\n}\n\nconst SENSITIVE_PARAM_NAMES = new Set([\n \"accesskey\",\n \"accesstoken\",\n \"apikey\",\n \"auth\",\n \"authorization\",\n \"authtoken\",\n \"bearertoken\",\n \"clientsecret\",\n \"consumersecret\",\n \"credential\",\n \"credentials\",\n \"idtoken\",\n \"key\",\n \"oauthtoken\",\n \"password\",\n \"passwd\",\n \"privatekey\",\n \"refreshtoken\",\n \"secret\",\n \"secretkey\",\n \"secrettoken\",\n \"sessiontoken\",\n \"signature\",\n \"signingsecret\",\n \"token\",\n \"webhooksecret\",\n]);\n\nfunction isSensitiveParam(name: string): boolean {\n const normalizedName = name.normalize(\"NFKC\");\n const canonicalName = normalizedName.replace(/[^A-Za-z0-9]/gu, \"\").toLowerCase();\n return (\n SENSITIVE_PARAM_NAMES.has(canonicalName) ||\n /[a-z0-9](?:credentials?|keys?|passwords?|passwds?|secrets?|signatures?|tokens?)$/u.test(\n canonicalName,\n ) ||\n /(?:^|[_-])(?:access[_-]?token|api[_-]?key|authorization|key|password|secret|signature|token)(?:$|[_-])/iu.test(\n normalizedName,\n )\n );\n}\n\nfunction isUrlParam(name: string): boolean {\n return /(?:urls?|uris?)$/iu.test(name.normalize(\"NFKC\").replace(/[^A-Za-z0-9]/gu, \"\"));\n}\n\nfunction redactParamValue(value: unknown, key: string, depth: number): unknown {\n if (isSensitiveParam(key)) {\n return \"<redacted>\";\n }\n if (Array.isArray(value)) {\n if (depth >= MAX_ZALO_REDACTION_DEPTH) {\n return \"<redacted>\";\n }\n return value.map((entry) => redactParamValue(entry, key, depth + 1));\n }\n if (isJsonObject(value)) {\n if (depth >= MAX_ZALO_REDACTION_DEPTH) {\n return \"<redacted>\";\n }\n return redactParams(value, depth + 1);\n }\n if (\n typeof value === \"string\" &&\n (isUrlParam(key) || /^(?:\\s*[a-z][a-z0-9+.-]*:)?\\/\\//iu.test(value))\n ) {\n return redactUrlCredentials(value);\n }\n return value;\n}\n\nfunction redactParams(params: Record<string, unknown>, depth = 0): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(params).map(([key, value]) => [key, redactParamValue(value, key, depth)]),\n );\n}\n\nfunction redactSensitiveSearchParams(searchParams: URLSearchParams): boolean {\n let redacted = false;\n for (const key of searchParams.keys()) {\n if (isSensitiveParam(key)) {\n searchParams.set(key, \"<redacted>\");\n redacted = true;\n }\n }\n return redacted;\n}\n\nfunction redactUrlFragment(value: string): string {\n const fragmentStart = value.indexOf(\"#\");\n return fragmentStart < 0 ? value : `${value.slice(0, fragmentStart)}#<redacted>`;\n}\n\nfunction redactMalformedUrlCredentials(value: string): string {\n const credentialRedacted = value.replace(\n /^(\\s*)((?:[a-z][a-z0-9+.-]*:)?\\/\\/)[^/?#]*@/iu,\n \"$1$2<redacted>@\",\n );\n if (credentialRedacted === value) {\n return \"<redacted>\";\n }\n const fragmentRedacted = redactUrlFragment(credentialRedacted);\n const queryStart = fragmentRedacted.indexOf(\"?\");\n const fragmentStart = fragmentRedacted.indexOf(\"#\", queryStart + 1);\n if (queryStart < 0 || (fragmentStart >= 0 && fragmentStart < queryStart)) {\n return fragmentRedacted;\n }\n const queryEnd = fragmentStart >= 0 ? fragmentStart : fragmentRedacted.length;\n const searchParams = new URLSearchParams(fragmentRedacted.slice(queryStart + 1, queryEnd));\n if (!redactSensitiveSearchParams(searchParams)) {\n return fragmentRedacted;\n }\n const search = searchParams.toString().replaceAll(\"%3Credacted%3E\", \"<redacted>\");\n return `${fragmentRedacted.slice(0, queryStart)}?${search}${fragmentRedacted.slice(queryEnd)}`;\n}\n\nfunction redactUrlCredentials(value: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return redactMalformedUrlCredentials(value);\n }\n const hasCredentials = Boolean(url.username || url.password);\n const redactedQuery = redactSensitiveSearchParams(url.searchParams);\n const hasFragment = url.hash.length > 0;\n if (!hasCredentials && !redactedQuery) {\n return hasFragment ? redactUrlFragment(value) : value;\n }\n const search = url.search.replaceAll(\"%3Credacted%3E\", \"<redacted>\");\n return `${url.protocol}//${hasCredentials ? \"<redacted>@\" : \"\"}${url.host}${url.pathname}${search}${hasFragment ? \"#<redacted>\" : \"\"}`;\n}\n\nfunction requireParam(body: Record<string, unknown>, name: string): string | Response {\n return readTrimmedString(body[name]) ?? zaloError(`${name} is required`, 400);\n}\n\nfunction firstError(...values: Array<string | Response>): Response | undefined {\n return values.find((value): value is Response => value instanceof Response);\n}\n\nfunction webhookDeliveryTimeoutMs(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value)) {\n return DEFAULT_WEBHOOK_DELIVERY_TIMEOUT_MS;\n }\n return Math.max(1, Math.min(Math.floor(value), MAX_WEBHOOK_DELIVERY_TIMEOUT_MS));\n}\n\nfunction maxPendingInboundBytes(value: number | undefined): number {\n if (value === undefined) {\n return DEFAULT_MAX_PENDING_INBOUND_BYTES;\n }\n if (!Number.isSafeInteger(value) || value < 1) {\n throw new Error(\"maxPendingInboundBytes must be a positive safe integer.\");\n }\n return value;\n}\n\nasync function validateWebhookUrl(\n url: URL,\n state: Pick<ZaloServerState, \"allowLoopbackHttpWebhook\" | \"restrictWebhookTargets\">,\n signal?: AbortSignal,\n): Promise<Response | ZaloValidatedWebhookTarget> {\n const target = await validateWebhookTarget({\n allowLoopbackHttp: state.allowLoopbackHttpWebhook,\n restrictPrivateAddresses: state.restrictWebhookTargets,\n signal,\n url,\n });\n if (\"error\" in target) {\n return target.error === \"unresolvable\"\n ? zaloError(\"url host could not be resolved\", 400)\n : target.error === \"private-address\"\n ? zaloError(\"url must not target a private or link-local address\", 400)\n : zaloError(\"url must use HTTPS\", 400);\n }\n return target;\n}\n\nfunction validateZaloWebhookSecret(secretToken: string): Response | undefined {\n if (Buffer.byteLength(secretToken) > MAX_ZALO_WEBHOOK_SECRET_BYTES) {\n return zaloError(`secret_token must not exceed ${MAX_ZALO_WEBHOOK_SECRET_BYTES} bytes`, 400);\n }\n try {\n validateHeaderValue(\"x-bot-api-secret-token\", secretToken);\n } catch {\n return zaloError(\"secret_token contains invalid HTTP header characters\", 400);\n }\n return undefined;\n}\n\nasync function validateWebhookUrlWithDeadline(\n url: URL,\n state: ZaloServerState,\n deadlineAt: number,\n): Promise<Response | ZaloValidatedWebhookTarget> {\n const remainingMs = deadlineAt - Date.now();\n if (remainingMs <= 0) {\n throw webhookTimeoutError(state.webhookDeliveryTimeoutMs);\n }\n const validation = new AbortController();\n state.activeWebhookValidations.add(validation);\n const timer = setTimeout(\n () => validation.abort(webhookTimeoutError(state.webhookDeliveryTimeoutMs)),\n remainingMs,\n );\n timer.unref();\n try {\n return await validateWebhookUrl(url, state, validation.signal);\n } finally {\n clearTimeout(timer);\n state.activeWebhookValidations.delete(validation);\n }\n}\n\nfunction webhookTimeoutError(timeoutMs: number): DOMException {\n return new DOMException(`Webhook delivery timed out after ${timeoutMs}ms`, \"TimeoutError\");\n}\n\n/** @internal */\nexport async function postZaloWebhook(params: {\n activeRequests?: Set<ClientRequest>;\n addresses?: WebhookAddress[] | undefined;\n body: string;\n shouldCancel?: (() => boolean) | undefined;\n timeoutMs: number;\n url: URL;\n verificationValue: string;\n}): Promise<number> {\n const activeRequests = params.activeRequests ?? new Set<ClientRequest>();\n const deadlineAt = Date.now() + params.timeoutMs;\n const addresses =\n params.addresses && params.addresses.length > 0 ? params.addresses : [undefined];\n let lastError: unknown;\n for (const [index, address] of addresses.entries()) {\n if (params.shouldCancel?.()) {\n throw new Error(\"Webhook delivery cancelled.\");\n }\n const remainingMs = deadlineAt - Date.now();\n if (remainingMs <= 0) {\n throw webhookTimeoutError(params.timeoutMs);\n }\n const attemptsRemaining = addresses.length - index;\n const attemptTimeoutMs = Math.max(1, Math.floor(remainingMs / attemptsRemaining));\n try {\n return await postWebhookRequest({\n activeRequests,\n address,\n body: params.body,\n headerEntries: [[\"x-bot-api-secret-token\", params.verificationValue]],\n timeoutMs: attemptTimeoutMs,\n url: params.url,\n });\n } catch (error) {\n if (params.shouldCancel?.()) {\n throw error;\n }\n lastError = error;\n if (\n error instanceof DOMException &&\n error.name === \"TimeoutError\" &&\n attemptsRemaining === 1\n ) {\n throw webhookTimeoutError(params.timeoutMs);\n }\n }\n }\n throw lastError;\n}\n\nfunction nextUpdate(\n request: IncomingMessage,\n response: ServerResponse,\n state: ZaloServerState,\n): HttpJsonHandlerResult | undefined {\n if (request.aborted || request.socket.destroyed || response.destroyed) {\n return undefined;\n }\n const update = state.updates[0];\n if (!update) {\n return undefined;\n }\n if (hasEarlierReservedPollingUpdate(state, update)) {\n return undefined;\n }\n state.updates.shift();\n reservePollingUpdate(state, update);\n return reservedUpdateResponse(state, update);\n}\n\nfunction pollingUpdateOrder(state: ZaloServerState, update: ZaloUpdate): number {\n const existing = state.updateOrders.get(update);\n if (existing !== undefined) {\n return existing;\n }\n const order = state.nextUpdateOrder++;\n state.updateOrders.set(update, order);\n return order;\n}\n\nfunction pollingUpdateBytes(state: ZaloServerState, update: ZaloUpdate): number {\n const existing = state.updateBytes.get(update);\n if (existing !== undefined) {\n return existing;\n }\n const bytes = Buffer.byteLength(JSON.stringify(update), \"utf8\");\n state.updateBytes.set(update, bytes);\n return bytes;\n}\n\nfunction retainPollingUpdate(state: ZaloServerState, update: ZaloUpdate): boolean {\n const bytes = pollingUpdateBytes(state, update);\n if (\n state.retainedUpdateCount >= state.maxPendingInboundEvents ||\n state.retainedUpdateBytes + bytes > state.maxPendingInboundBytes\n ) {\n state.updateBytes.delete(update);\n return false;\n }\n state.retainedUpdateCount += 1;\n state.retainedUpdateBytes += bytes;\n return true;\n}\n\nfunction releasePollingUpdate(state: ZaloServerState, update: ZaloUpdate): void {\n const bytes = state.updateBytes.get(update);\n if (bytes === undefined) {\n throw new Error(\"Zalo polling update retention was released without a reservation.\");\n }\n state.updateBytes.delete(update);\n state.retainedUpdateCount -= 1;\n state.retainedUpdateBytes -= bytes;\n}\n\nfunction queuePollingUpdate(state: ZaloServerState, update: ZaloUpdate): void {\n const order = pollingUpdateOrder(state, update);\n const insertionIndex = state.updates.findIndex(\n (queued) => pollingUpdateOrder(state, queued) > order,\n );\n if (insertionIndex < 0) {\n state.updates.push(update);\n } else {\n state.updates.splice(insertionIndex, 0, update);\n }\n}\n\nfunction hasEarlierReservedPollingUpdate(state: ZaloServerState, update: ZaloUpdate): boolean {\n const order = pollingUpdateOrder(state, update);\n return [...state.reservedUpdateOrders].some((reservedOrder) => reservedOrder < order);\n}\n\nfunction reservePollingUpdate(state: ZaloServerState, update: ZaloUpdate): void {\n const order = pollingUpdateOrder(state, update);\n state.reservedUpdateOrders.add(order);\n}\n\nfunction flushPendingPollingUpdate(state: ZaloServerState): void {\n const pending = state.pendingRequest;\n const update = state.updates[0];\n if (!pending || !update) {\n return;\n }\n if (!isPendingUpdateRequestLive(pending)) {\n settlePendingUpdate(state, pending, { kind: \"disconnect\" });\n return;\n }\n if (hasEarlierReservedPollingUpdate(state, update)) {\n return;\n }\n state.updates.shift();\n reservePollingUpdate(state, update);\n settlePendingUpdate(state, pending, { kind: \"update\", update });\n}\n\nfunction reservedUpdateResponse(state: ZaloServerState, update: ZaloUpdate): HttpJsonHandlerResult {\n let settled = false;\n const releaseReservation = () => {\n if (settled) {\n return false;\n }\n settled = true;\n state.reservedUpdateOrders.delete(pollingUpdateOrder(state, update));\n return true;\n };\n return {\n onWriteFailure() {\n if (!releaseReservation()) {\n return;\n }\n queuePollingUpdate(state, update);\n flushPendingPollingUpdate(state);\n },\n onWriteSuccess() {\n if (releaseReservation()) {\n releasePollingUpdate(state, update);\n flushPendingPollingUpdate(state);\n }\n },\n response: zaloOk(update),\n };\n}\n\nfunction settlePendingUpdate(\n state: ZaloServerState,\n pending: PendingUpdateRequest,\n result: PendingUpdateResult,\n): boolean {\n if (!pending.active) {\n return false;\n }\n pending.active = false;\n if (state.pendingRequest === pending) {\n state.pendingRequest = undefined;\n }\n if (pending.timeout) {\n clearTimeout(pending.timeout);\n }\n pending.request.socket.off(\"close\", pending.onDisconnect);\n pending.request.off(\"aborted\", pending.onDisconnect);\n pending.response.off(\"close\", pending.onDisconnect);\n pending.resolve(result);\n return true;\n}\n\nfunction isPendingUpdateRequestLive(pending: PendingUpdateRequest): boolean {\n return (\n !pending.request.aborted && !pending.request.socket.destroyed && !pending.response.destroyed\n );\n}\n\nasync function waitForUpdate(\n request: IncomingMessage,\n response: ServerResponse,\n state: ZaloServerState,\n timeoutSeconds: number,\n): Promise<HttpJsonHandlerResult> {\n if (request.aborted || request.socket.destroyed || response.destroyed) {\n return zaloError(\"Client closed request\", 499);\n }\n const previous = state.pendingRequest;\n if (previous) {\n settlePendingUpdate(state, previous, { kind: \"conflict\" });\n }\n const queued = nextUpdate(request, response, state);\n if (queued) {\n return queued;\n }\n if (timeoutSeconds <= 0) {\n return zaloError(\"Request timeout\", 408);\n }\n const result = await new Promise<PendingUpdateResult>((resolve) => {\n const pending: PendingUpdateRequest = {\n active: true,\n onDisconnect: () => {\n settlePendingUpdate(state, pending, { kind: \"disconnect\" });\n },\n request,\n response,\n resolve,\n timeout: undefined,\n };\n state.pendingRequest = pending;\n request.once(\"aborted\", pending.onDisconnect);\n request.socket.once(\"close\", pending.onDisconnect);\n response.once(\"close\", pending.onDisconnect);\n pending.timeout = setTimeout(() => {\n settlePendingUpdate(state, pending, { kind: \"timeout\" });\n }, timeoutSeconds * 1000);\n pending.timeout.unref();\n if (request.socket.destroyed || response.destroyed) {\n pending.onDisconnect();\n }\n });\n switch (result.kind) {\n case \"conflict\":\n return zaloError(\"Conflict: terminated by other getUpdates request\", 409);\n case \"disconnect\":\n return zaloError(\"Client closed request\", 499);\n case \"shutdown\":\n return zaloError(\"Server shutting down\", 503);\n case \"timeout\":\n return zaloError(\"Request timeout\", 408);\n case \"update\":\n return reservedUpdateResponse(state, result.update);\n }\n}\n\nfunction deliverPollingUpdate(state: ZaloServerState, update: ZaloUpdate): void {\n pollingUpdateOrder(state, update);\n if (state.updates.length > 0 || hasEarlierReservedPollingUpdate(state, update)) {\n queuePollingUpdate(state, update);\n flushPendingPollingUpdate(state);\n return;\n }\n const pending = state.pendingRequest;\n if (pending) {\n if (isPendingUpdateRequestLive(pending)) {\n reservePollingUpdate(state, update);\n settlePendingUpdate(state, pending, { kind: \"update\", update });\n return;\n }\n settlePendingUpdate(state, pending, { kind: \"disconnect\" });\n }\n queuePollingUpdate(state, update);\n}\n\nasync function deliverWebhookUpdate(\n state: ZaloServerState,\n webhook: NonNullable<ZaloServerState[\"webhook\"]>,\n update: ZaloUpdate,\n): Promise<Response | undefined> {\n const deadlineAt = Date.now() + state.webhookDeliveryTimeoutMs;\n const url = new URL(webhook.url);\n let target: Response | ZaloValidatedWebhookTarget;\n try {\n target = await validateWebhookUrlWithDeadline(url, state, deadlineAt);\n } catch (error) {\n if (error instanceof DOMException && error.name === \"TimeoutError\") {\n return zaloError(`Webhook delivery timed out after ${state.webhookDeliveryTimeoutMs}ms`, 502);\n }\n throw error;\n }\n if (target instanceof Response) {\n return target;\n }\n try {\n const remainingMs = deadlineAt - Date.now();\n if (remainingMs <= 0) {\n throw webhookTimeoutError(state.webhookDeliveryTimeoutMs);\n }\n const status = await postZaloWebhook({\n activeRequests: state.activeWebhookRequests,\n addresses: target.addresses,\n body: JSON.stringify(update),\n shouldCancel: () => state.closing,\n timeoutMs: remainingMs,\n url,\n verificationValue: webhook.secretToken,\n });\n if (status < 200 || status >= 300) {\n return zaloError(`Webhook delivery failed with HTTP ${status}`, 502);\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === \"TimeoutError\") {\n return zaloError(`Webhook delivery timed out after ${state.webhookDeliveryTimeoutMs}ms`, 502);\n }\n return zaloError(\n `Webhook delivery failed: ${error instanceof Error ? error.message : String(error)}`,\n 502,\n );\n }\n return undefined;\n}\n\nasync function handleAdminInbound(\n request: IncomingMessage,\n state: ZaloServerState,\n url: URL,\n): Promise<Response> {\n if (!hasAdminToken(request, state.adminToken)) {\n drainRequestBody(request);\n return adminAuthError();\n }\n if (state.webhookTransitionPending) {\n drainRequestBody(request);\n return zaloError(\"Webhook configuration is in progress\", 409);\n }\n const retainedUpdates = state.webhook?.url === undefined ? state.retainedUpdateCount : 0;\n if (retainedUpdates + state.pendingInboundAdmissions >= state.maxPendingInboundEvents) {\n drainRequestBody(request);\n return zaloError(\n `Pending inbound queue is full (${state.maxPendingInboundEvents} updates)`,\n 429,\n );\n }\n state.pendingInboundAdmissions += 1;\n let releaseAdmission!: () => void;\n const previousAdmission = state.inboundAdmission;\n state.inboundAdmission = new Promise<void>((resolve) => {\n releaseAdmission = resolve;\n });\n let admissionPending = true;\n let retainedPollingUpdate: ZaloUpdate | undefined;\n try {\n const parsedBody = await parseUnknownRequestBody(request);\n await previousAdmission;\n if (!isJsonObject(parsedBody)) {\n return zaloError(\"Bad Request: can't parse JSON object\", 400);\n }\n const body = parsedBody;\n const chatId = requireParam(body, \"chatId\");\n const senderId = requireParam(body, \"senderId\");\n const text = requireParam(body, \"text\");\n if (chatId instanceof Response || senderId instanceof Response || text instanceof Response) {\n return [chatId, senderId, text].find((value) => value instanceof Response) as Response;\n }\n const webhook = state.webhook;\n const update: ZaloUpdate = {\n event_name: \"message.text.received\",\n message: {\n chat: { chat_type: readChatType(body.chatType), id: chatId },\n date: Date.now(),\n from: {\n display_name: readTrimmedString(body.senderName) ?? senderId,\n id: senderId,\n is_bot: false,\n },\n message_id: messageId(state),\n text,\n },\n };\n if (!webhook?.url) {\n if (!retainPollingUpdate(state, update)) {\n return zaloError(\n `Pending inbound queue is full (${state.maxPendingInboundEvents} updates)`,\n 429,\n );\n }\n retainedPollingUpdate = update;\n state.pendingInboundAdmissions -= 1;\n admissionPending = false;\n }\n await appendEvent(state, {\n at: new Date().toISOString(),\n body: redactParams(body),\n method: request.method ?? \"POST\",\n path: url.pathname,\n query: redactParams(queryRecord(url)) as Record<string, string>,\n type: \"admin\",\n });\n if (webhook?.url) {\n const error = await deliverWebhookUpdate(state, webhook, update);\n if (error) {\n return error;\n }\n } else {\n deliverPollingUpdate(state, update);\n retainedPollingUpdate = undefined;\n }\n return zaloOk(update);\n } finally {\n if (retainedPollingUpdate) {\n releasePollingUpdate(state, retainedPollingUpdate);\n }\n await previousAdmission;\n releaseAdmission();\n if (admissionPending) {\n state.pendingInboundAdmissions -= 1;\n }\n }\n}\n\nasync function handleZaloMethod(\n request: IncomingMessage,\n response: ServerResponse,\n state: ZaloServerState,\n url: URL,\n method: string,\n): Promise<HttpJsonHandlerResult> {\n const parsedBody = await parseUnknownRequestBody(request);\n if (!isJsonObject(parsedBody)) {\n return zaloError(\"Bad Request: can't parse JSON object\", 400);\n }\n const body = requestParams(url, parsedBody);\n const event: ZaloServerEvent = {\n at: new Date().toISOString(),\n ...(Object.keys(body).length > 0 ? { body: redactParams(body) } : {}),\n method: request.method ?? \"GET\",\n path: `/bot<redacted>/${method}`,\n query: redactParams(queryRecord(url)) as Record<string, string>,\n type: \"api\",\n };\n\n if (method === \"sendMessage\" || method === \"sendPhoto\") {\n const chatId = requireParam(body, \"chat_id\");\n const content = requireParam(body, method === \"sendMessage\" ? \"text\" : \"photo\");\n const error = firstError(chatId, content);\n const sendResponse = error ?? zaloOk({ date: Date.now(), message_id: messageId(state) });\n event.accepted = sendResponse.ok;\n try {\n await appendEvent(state, event);\n } catch (appendError) {\n if (!event.accepted) {\n throw appendError;\n }\n }\n return sendResponse;\n }\n\n if (method === \"getMe\") {\n const getMeResponse = zaloOk({\n account_name: state.botName,\n account_type: \"BASIC\",\n can_join_groups: true,\n id: state.botId,\n });\n event.accepted = getMeResponse.ok;\n await appendEvent(state, event);\n return getMeResponse;\n }\n\n if (method !== \"setWebhook\") {\n await appendEvent(state, event);\n }\n if (method === \"getUpdates\") {\n if (state.webhook?.url || state.webhookTransitionPending) {\n return zaloError(\"Webhook is configured; delete it before using getUpdates\", 400);\n }\n const parsedTimeout = Number(readTrimmedString(body.timeout) ?? \"30\");\n const timeout = Number.isFinite(parsedTimeout) ? Math.max(0, Math.min(parsedTimeout, 50)) : 30;\n return await waitForUpdate(request, response, state, timeout);\n }\n if (method === \"sendChatAction\") {\n const chatId = requireParam(body, \"chat_id\");\n const action = requireParam(body, \"action\");\n const error = firstError(chatId, action);\n if (error) {\n return error;\n }\n if (action !== \"typing\" && action !== \"upload_photo\") {\n return zaloError(\"action must be typing or upload_photo\", 400);\n }\n return zaloOk();\n }\n if (method === \"setWebhook\") {\n const reject = async (result: Response): Promise<Response> => {\n if (isJsonObject(event.body) && \"url\" in event.body) {\n event.body.url = \"<redacted>\";\n }\n await appendEvent(state, event);\n return result;\n };\n const webhookUrl = requireParam(body, \"url\");\n const secretToken = requireParam(body, \"secret_token\");\n const error = firstError(webhookUrl, secretToken);\n if (error) {\n return await reject(error);\n }\n if (typeof webhookUrl !== \"string\" || typeof secretToken !== \"string\") {\n return await reject(zaloError(\"Invalid webhook parameters\", 400));\n }\n const secretError = validateZaloWebhookSecret(secretToken);\n if (secretError) {\n return await reject(secretError);\n }\n let parsedUrl: URL;\n try {\n parsedUrl = new URL(webhookUrl);\n } catch {\n return await reject(zaloError(\"url must be a valid HTTPS URL\", 400));\n }\n if (state.activeWebhookValidations.size >= MAX_ACTIVE_ZALO_WEBHOOK_VALIDATIONS) {\n return await reject(zaloError(\"Too many webhook validations\", 429));\n }\n let target: Response | ZaloValidatedWebhookTarget;\n try {\n target = await validateWebhookUrlWithDeadline(\n parsedUrl,\n state,\n Date.now() + state.webhookDeliveryTimeoutMs,\n );\n } catch {\n return await reject(zaloError(\"url host could not be resolved\", 400));\n }\n if (target instanceof Response) {\n return await reject(target);\n }\n if (state.webhookTransitionPending || state.reservedUpdateOrders.size > 0) {\n return await reject(zaloError(\"Polling deliveries are still in progress\", 409));\n }\n const webhook = { secretToken, updatedAt: Date.now(), url: parsedUrl.href };\n state.webhookTransitionPending = true;\n try {\n await state.inboundAdmission;\n if (state.reservedUpdateOrders.size > 0) {\n return await reject(zaloError(\"Polling deliveries are still in progress\", 409));\n }\n await appendEvent(state, event);\n if (state.pendingRequest) {\n settlePendingUpdate(state, state.pendingRequest, { kind: \"conflict\" });\n }\n state.webhook = webhook;\n return zaloOk({ updated_at: webhook.updatedAt, url: webhook.url });\n } finally {\n state.webhookTransitionPending = false;\n }\n }\n if (method === \"deleteWebhook\") {\n const updatedAt = Date.now();\n state.webhook = undefined;\n return zaloOk({ updated_at: updatedAt, url: \"\" });\n }\n if (method === \"getWebhookInfo\") {\n return zaloOk(\n state.webhook ? { updated_at: state.webhook.updatedAt, url: state.webhook.url } : { url: \"\" },\n );\n }\n return zaloError(\"Bad request - invalid API name\", 400);\n}\n\nexport async function startZaloServer(\n params: StartZaloServerParams = {},\n): Promise<StartedZaloServer> {\n const host = params.host ?? \"127.0.0.1\";\n const recorderPath = params.recorderPath ?? path.resolve(\".crabline\", \"servers\", \"zalo.jsonl\");\n const state: ZaloServerState = {\n activeWebhookRequests: new Set(),\n activeWebhookValidations: new Set(),\n adminToken: params.adminToken ?? randomBytes(24).toString(\"hex\"),\n allowLoopbackHttpWebhook: isLoopbackHost(host),\n botId: params.botId ?? \"1459232241454765289\",\n botName: params.botName ?? \"bot.crabline\",\n botToken:\n params.botToken ??\n (isLoopbackHost(host) ? \"crabline-zalo-bot-token\" : randomBytes(32).toString(\"base64url\")),\n closing: false,\n inboundAdmission: Promise.resolve(),\n maxPendingInboundBytes: maxPendingInboundBytes(params.maxPendingInboundBytes),\n maxPendingInboundEvents: resolveMaxPendingInboundEvents(params.maxPendingInboundEvents),\n nextMessage: 1,\n nextUpdateOrder: 1,\n recorder: createServerRecorder({ recorderPath, onEvent: params.onEvent }),\n pendingInboundAdmissions: 0,\n pendingRequest: undefined,\n recorderPath,\n retainedUpdateBytes: 0,\n retainedUpdateCount: 0,\n reservedUpdateOrders: new Set(),\n restrictWebhookTargets: true,\n updateBytes: new WeakMap(),\n updateOrders: new WeakMap(),\n updates: [],\n webhook: undefined,\n webhookDeliveryTimeoutMs: webhookDeliveryTimeoutMs(params.webhookDeliveryTimeoutMs),\n webhookTransitionPending: false,\n };\n const httpServer = await startHttpJsonServer({\n handle: async (request, response) => {\n const url = new URL(request.url ?? \"/\", `http://${request.headers.host ?? host}`);\n if (request.method === \"POST\" && url.pathname === \"/crabline/zalo/inbound\") {\n return await handleAdminInbound(request, state, url);\n }\n const match = /^\\/bot([^/]+)\\/([^/]+)$/u.exec(url.pathname);\n if (!match || (request.method !== \"GET\" && request.method !== \"POST\")) {\n return zaloError(\"Not found\", 404);\n }\n if (match[1] !== state.botToken) {\n drainRequestBody(request);\n return zaloError(\"Unauthorized\", 401);\n }\n return await handleZaloMethod(request, response, state, url, match[2] ?? \"\");\n },\n handleError: (error) => {\n if (error instanceof InvalidJsonBodyError) {\n return zaloError(\"Bad Request: can't parse JSON object\", 400);\n }\n if (error instanceof RequestBodyTooLargeError) {\n return zaloError(\"Request Entity Too Large\", 413);\n }\n return undefined;\n },\n host,\n port: params.port ?? 0,\n serverName: \"Zalo\",\n });\n const manifest: ZaloServerManifest = {\n adminToken: state.adminToken,\n baseUrl: httpServer.baseUrl,\n botId: state.botId,\n botToken: state.botToken,\n endpoints: {\n adminInboundUrl: `${httpServer.baseUrl}/crabline/zalo/inbound`,\n apiRoot: httpServer.baseUrl,\n },\n env: {\n ZALO_API_URL: httpServer.baseUrl,\n ZALO_BOT_TOKEN: state.botToken,\n },\n provider: \"zalo\",\n recorderPath: state.recorderPath,\n version: 1,\n };\n return {\n close: createServerClose(state.recorder, async () => {\n state.closing = true;\n for (const request of state.activeWebhookRequests) {\n request.destroy(new Error(\"Zalo server is shutting down.\"));\n }\n for (const validation of state.activeWebhookValidations) {\n validation.abort(new Error(\"Zalo server is shutting down.\"));\n }\n if (state.pendingRequest) {\n settlePendingUpdate(state, state.pendingRequest, { kind: \"shutdown\" });\n }\n await httpServer.close();\n }),\n manifest,\n };\n}\n"]}
|
package/docs/channel-setup.md
CHANGED
|
@@ -231,6 +231,14 @@ credentials unless the corresponding credential is supplied.
|
|
|
231
231
|
WhatsApp is loopback-only because its HTTP and WebSocket endpoints carry bearer
|
|
232
232
|
credentials over cleartext and the built-in server does not terminate TLS.
|
|
233
233
|
|
|
234
|
+
Every public server starter initializes recorder ownership before reporting
|
|
235
|
+
readiness, without creating recorder artifacts or invoking `onEvent`.
|
|
236
|
+
Server `close()` stops new recorder admissions and drains admitted persistence
|
|
237
|
+
before it succeeds. Event observers are not part of this drain, so an observer
|
|
238
|
+
may call `close()`; stalled handlers still use the bounded transport shutdown.
|
|
239
|
+
Repeated close calls share that shutdown, including failed-transport cleanup and
|
|
240
|
+
any pending recorder lock removal.
|
|
241
|
+
|
|
234
242
|
Commands in this section use the installed-package form. In a source checkout,
|
|
235
243
|
replace `crabline` with `pnpm dev`; `pnpm exec crabline` is not available.
|
|
236
244
|
|
|
@@ -557,6 +565,57 @@ The admin ingress accepts JSON like:
|
|
|
557
565
|
}
|
|
558
566
|
```
|
|
559
567
|
|
|
568
|
+
For an OpenClaw bridge voice-note fixture, pass exactly one inline audio
|
|
569
|
+
attachment. The bridge ignores `text` for that inbound event and sets `ptt` to
|
|
570
|
+
`true`:
|
|
571
|
+
|
|
572
|
+
```json
|
|
573
|
+
{
|
|
574
|
+
"attachments": [
|
|
575
|
+
{
|
|
576
|
+
"contentBase64": "T2dnUwACAAAAAAAAAAB...",
|
|
577
|
+
"id": "voice-note-1",
|
|
578
|
+
"kind": "audio",
|
|
579
|
+
"mimeType": "audio/ogg; codecs=opus"
|
|
580
|
+
}
|
|
581
|
+
],
|
|
582
|
+
"conversation": {
|
|
583
|
+
"id": "15551234567@s.whatsapp.net",
|
|
584
|
+
"kind": "direct"
|
|
585
|
+
},
|
|
586
|
+
"senderId": "15551234567@s.whatsapp.net",
|
|
587
|
+
"text": ""
|
|
588
|
+
}
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
The bridge rejects multiple attachments, non-audio attachments, and audio
|
|
592
|
+
without inline `contentBase64`. It posts the corresponding provider control
|
|
593
|
+
payload to `endpoints.adminInboundUrl`:
|
|
594
|
+
|
|
595
|
+
```json
|
|
596
|
+
{
|
|
597
|
+
"audio": {
|
|
598
|
+
"contentBase64": "T2dnUwACAAAAAAAAAAB...",
|
|
599
|
+
"mimeType": "audio/ogg; codecs=opus",
|
|
600
|
+
"ptt": true
|
|
601
|
+
},
|
|
602
|
+
"chatJid": "15551234567@s.whatsapp.net",
|
|
603
|
+
"senderJid": "15551234567@s.whatsapp.net"
|
|
604
|
+
}
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
`audio.contentBase64` must be a non-empty canonical base64 string, `mimeType`
|
|
608
|
+
must start with `audio/`, and optional `ptt` must be a boolean. The request must
|
|
609
|
+
contain exactly one of `text` or `audio` and remains subject to the server's 1
|
|
610
|
+
MiB request-body limit. Accepted audio is exposed to Baileys as a native
|
|
611
|
+
encrypted `audioMessage` download. The server retains at most 1,000 active
|
|
612
|
+
media fixtures and 16 MiB of encrypted media in total. A fixture expires after
|
|
613
|
+
five minutes or no later than 30 seconds after its first successful download;
|
|
614
|
+
later downloads cannot extend either deadline. Capacity exhaustion returns
|
|
615
|
+
HTTP 503 without evicting an accepted, unexpired fixture. Every media URL
|
|
616
|
+
includes an independent 256-bit capability; a missing or altered capability
|
|
617
|
+
returns HTTP 404.
|
|
618
|
+
|
|
560
619
|
Outbound text sends and composing presence are recorded through the local
|
|
561
620
|
provider server's messages and presence endpoints.
|
|
562
621
|
|
|
@@ -722,7 +781,12 @@ Publication rollback removes them when possible, and the next lock-owning
|
|
|
722
781
|
publisher prunes any leftovers before staging a new generation. Post-commit
|
|
723
782
|
cleanup retains only the current and previous pointer generations.
|
|
724
783
|
|
|
725
|
-
POSIX generation directories use mode `0700` and files use mode `0600`.
|
|
784
|
+
POSIX generation directories use mode `0700` and files use mode `0600`. On macOS,
|
|
785
|
+
private directories must be ACL-free. Ancestors may retain fully understood,
|
|
786
|
+
deny-only ACLs that do not propagate to children, including entries marked as
|
|
787
|
+
inherited. Allowing, mixed, propagating, or unverifiable ancestor ACLs abort
|
|
788
|
+
publication. Crabline never removes external ancestor ACLs; their denials can
|
|
789
|
+
still cause filesystem operations to fail. Windows
|
|
726
790
|
hosts require `powershell.exe` with `Set-Acl`; Crabline resolves it from the
|
|
727
791
|
absolute local `SystemRoot` and applies a protected, inheritable DACL containing
|
|
728
792
|
only the current user SID to an empty generation directory before creating
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/crabline",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "Standalone CLI for deterministic messaging provider E2E tests",
|
|
5
5
|
"homepage": "https://github.com/openclaw/crabline#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"picocolors": "^1.1.1",
|
|
59
59
|
"proper-lockfile": "4.1.2",
|
|
60
60
|
"re2js": "2.8.6",
|
|
61
|
-
"ws": "^8.21.
|
|
61
|
+
"ws": "^8.21.3",
|
|
62
62
|
"yaml": "^2.9.0",
|
|
63
63
|
"zod": "^4.4.3"
|
|
64
64
|
},
|
|
@@ -66,25 +66,25 @@
|
|
|
66
66
|
"@types/proper-lockfile": "4.1.4",
|
|
67
67
|
"@types/ws": "^8.18.1",
|
|
68
68
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
69
|
-
"@vitest/coverage-v8": "^4.1.
|
|
70
|
-
"baileys": "7.0.0-
|
|
71
|
-
"matrix-js-sdk": "
|
|
72
|
-
"oxfmt": "^0.
|
|
73
|
-
"oxlint": "^1.
|
|
69
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
70
|
+
"baileys": "7.0.0-rc14",
|
|
71
|
+
"matrix-js-sdk": "42.2.0",
|
|
72
|
+
"oxfmt": "^0.65.0",
|
|
73
|
+
"oxlint": "^1.80.0",
|
|
74
74
|
"oxlint-tsgolint": "^7.0.2001",
|
|
75
|
-
"tsx": "^4.23.
|
|
75
|
+
"tsx": "^4.23.12",
|
|
76
76
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
77
|
-
"vitest": "^4.1.
|
|
77
|
+
"vitest": "^4.1.11"
|
|
78
78
|
},
|
|
79
79
|
"devEngines": {
|
|
80
80
|
"runtime": {
|
|
81
81
|
"name": "node",
|
|
82
|
-
"
|
|
83
|
-
"
|
|
82
|
+
"version": ">=22.13.0",
|
|
83
|
+
"onFail": "error"
|
|
84
84
|
}
|
|
85
85
|
},
|
|
86
86
|
"engines": {
|
|
87
87
|
"node": ">=22"
|
|
88
88
|
},
|
|
89
|
-
"packageManager": "pnpm@11.
|
|
89
|
+
"packageManager": "pnpm@11.24.0"
|
|
90
90
|
}
|