@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.
Files changed (39) hide show
  1. package/README.md +8 -0
  2. package/dist/src/openclaw/bridges/whatsapp.js +21 -1
  3. package/dist/src/openclaw/bridges/whatsapp.js.map +1 -1
  4. package/dist/src/openclaw/private-file.js +87 -30
  5. package/dist/src/openclaw/private-file.js.map +1 -1
  6. package/dist/src/openclaw/shared.d.ts +9 -0
  7. package/dist/src/openclaw/shared.js +2 -1
  8. package/dist/src/openclaw/shared.js.map +1 -1
  9. package/dist/src/platform/process-owned-lock.d.ts +5 -2
  10. package/dist/src/platform/process-owned-lock.js +20 -10
  11. package/dist/src/platform/process-owned-lock.js.map +1 -1
  12. package/dist/src/servers/discord.js +25 -35
  13. package/dist/src/servers/discord.js.map +1 -1
  14. package/dist/src/servers/http.d.ts +3 -0
  15. package/dist/src/servers/http.js +15 -0
  16. package/dist/src/servers/http.js.map +1 -1
  17. package/dist/src/servers/matrix.js +8 -8
  18. package/dist/src/servers/matrix.js.map +1 -1
  19. package/dist/src/servers/mattermost.js +7 -10
  20. package/dist/src/servers/mattermost.js.map +1 -1
  21. package/dist/src/servers/recorder.d.ts +16 -6
  22. package/dist/src/servers/recorder.js +52 -12
  23. package/dist/src/servers/recorder.js.map +1 -1
  24. package/dist/src/servers/signal.js +8 -8
  25. package/dist/src/servers/signal.js.map +1 -1
  26. package/dist/src/servers/slack.js +8 -8
  27. package/dist/src/servers/slack.js.map +1 -1
  28. package/dist/src/servers/telegram.d.ts +2 -2
  29. package/dist/src/servers/telegram.js +8 -8
  30. package/dist/src/servers/telegram.js.map +1 -1
  31. package/dist/src/servers/whatsapp-baileys-websocket.d.ts +15 -0
  32. package/dist/src/servers/whatsapp-baileys-websocket.js +32 -2
  33. package/dist/src/servers/whatsapp-baileys-websocket.js.map +1 -1
  34. package/dist/src/servers/whatsapp.js +189 -29
  35. package/dist/src/servers/whatsapp.js.map +1 -1
  36. package/dist/src/servers/zalo.js +8 -7
  37. package/dist/src/servers/zalo.js.map +1 -1
  38. package/docs/channel-setup.md +65 -1
  39. package/package.json +12 -12
@@ -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 { recordServerEvent } from "./recorder.js";
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 recordServerEvent({ event, onEvent: state.onEvent, recorderPath: state.recorderPath });
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: params.recorderPath ?? path.resolve(".crabline", "servers", "zalo.jsonl"),
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 close() {
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"]}
@@ -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`. Windows
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.16",
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.1",
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.10",
70
- "baileys": "7.0.0-rc13",
71
- "matrix-js-sdk": "41.9.0",
72
- "oxfmt": "^0.60.0",
73
- "oxlint": "^1.75.0",
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.1",
75
+ "tsx": "^4.23.12",
76
76
  "typescript": "npm:@typescript/typescript6@^6.0.2",
77
- "vitest": "^4.1.10"
77
+ "vitest": "^4.1.11"
78
78
  },
79
79
  "devEngines": {
80
80
  "runtime": {
81
81
  "name": "node",
82
- "onFail": "error",
83
- "version": ">=22.13.0"
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.17.0"
89
+ "packageManager": "pnpm@11.24.0"
90
90
  }