@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 { createHash, randomBytes, randomUUID } from "node:crypto";
2
2
  import path from "node:path";
3
3
  import { WebSocket, WebSocketServer } from "ws";
4
- import { adminAuthError, constantTimeTokenEqual, hasAdminToken, InvalidJsonBodyError, isJsonObject, isLoopbackHost, parseUnknownRequestBody, queryRecord, readTrimmedString, RequestBodyTooLargeError, startHttpJsonServer, } from "./http.js";
5
- import { recordCommittedServerEvent, recordServerEvent, } from "./recorder.js";
4
+ import { adminAuthError, createServerClose, constantTimeTokenEqual, hasAdminToken, InvalidJsonBodyError, isJsonObject, isLoopbackHost, parseUnknownRequestBody, queryRecord, readTrimmedString, RequestBodyTooLargeError, startHttpJsonServer, } from "./http.js";
5
+ import { createServerRecorder } from "./recorder.js";
6
6
  import { closeWebSocketServer } from "./websocket.js";
7
7
  const DEFAULT_HEARTBEAT_INTERVAL_MS = 45_000;
8
8
  const DEFAULT_IDENTIFY_TIMEOUT_MS = 10_000;
@@ -277,21 +277,15 @@ function dispatchGatewayEvent(state, type, data) {
277
277
  }
278
278
  }
279
279
  function recordGatewayEvent(state, body, accepted) {
280
- const pending = recordCommittedServerEvent({
281
- event: {
282
- accepted,
283
- at: new Date().toISOString(),
284
- body,
285
- method: "WS",
286
- path: "/gateway",
287
- query: {},
288
- type: "api",
289
- },
290
- onEvent: state.onEvent,
291
- recorderPath: state.recorderPath,
280
+ void state.recorder.recordCommitted({
281
+ accepted,
282
+ at: new Date().toISOString(),
283
+ body,
284
+ method: "WS",
285
+ path: "/gateway",
286
+ query: {},
287
+ type: "api",
292
288
  });
293
- state.pendingRecorderEvents.add(pending);
294
- void pending.then(() => state.pendingRecorderEvents.delete(pending), () => state.pendingRecorderEvents.delete(pending));
295
289
  }
296
290
  function readyPayload(state, sessionId) {
297
291
  return {
@@ -725,11 +719,7 @@ async function handleRequest(params) {
725
719
  };
726
720
  const response = await handleAdminInbound({ body, state: params.state });
727
721
  event.accepted = response.ok;
728
- await recordCommittedServerEvent({
729
- event,
730
- onEvent: params.state.onEvent,
731
- recorderPath: params.state.recorderPath,
732
- });
722
+ await params.state.recorder.recordCommitted(event);
733
723
  return response;
734
724
  }
735
725
  const authError = method === "GET" && url.pathname === "/api/v10/gateway"
@@ -755,11 +745,9 @@ async function handleRequest(params) {
755
745
  state: params.state,
756
746
  });
757
747
  event.accepted = response.ok;
758
- await (response.ok ? recordCommittedServerEvent : recordServerEvent)({
759
- event,
760
- onEvent: params.state.onEvent,
761
- recorderPath: params.state.recorderPath,
762
- });
748
+ await (response.ok
749
+ ? params.state.recorder.recordCommitted(event)
750
+ : params.state.recorder.record(event));
763
751
  return response;
764
752
  }
765
753
  export async function startDiscordServer(params = {}) {
@@ -770,6 +758,7 @@ export async function startDiscordServer(params = {}) {
770
758
  requireSnowflake(botUserId, "botUserId");
771
759
  const encodedApplicationId = Buffer.from(applicationId, "utf8").toString("base64url");
772
760
  const externallyBound = !isLoopbackHost(host);
761
+ const recorderPath = params.recorderPath ?? path.resolve(".crabline", "servers", "discord.jsonl");
773
762
  const state = {
774
763
  adminToken: params.adminToken ?? randomBytes(24).toString("base64url"),
775
764
  applicationId,
@@ -788,9 +777,8 @@ export async function startDiscordServer(params = {}) {
788
777
  maxGatewayPayloadBytes: positiveInteger(params.maxGatewayPayloadBytes, DEFAULT_MAX_GATEWAY_PAYLOAD_BYTES, "maxGatewayPayloadBytes"),
789
778
  messages: new Map(),
790
779
  nextSequence: 1,
791
- onEvent: params.onEvent,
792
- pendingRecorderEvents: new Set(),
793
- recorderPath: params.recorderPath ?? path.resolve(".crabline", "servers", "discord.jsonl"),
780
+ recorder: createServerRecorder({ recorderPath, onEvent: params.onEvent }),
781
+ recorderPath,
794
782
  sessions: new Map(),
795
783
  };
796
784
  const httpServer = await startHttpJsonServer({
@@ -814,12 +802,14 @@ export async function startDiscordServer(params = {}) {
814
802
  state.gatewayUrl = `${httpServer.baseUrl.replace(/^http/u, "ws")}/gateway`;
815
803
  const closeGateway = attachGatewayServer({ server: httpServer.server, state });
816
804
  return {
817
- async close() {
818
- await closeGateway();
819
- await httpServer.close();
820
- await Promise.all([...state.pendingRecorderEvents]);
821
- state.sessions.clear();
822
- },
805
+ close: createServerClose(state.recorder, async () => {
806
+ try {
807
+ await closeGateway();
808
+ }
809
+ finally {
810
+ state.sessions.clear();
811
+ }
812
+ }, () => httpServer.close()),
823
813
  manifest: {
824
814
  adminToken: state.adminToken,
825
815
  applicationId: state.applicationId,
@@ -1 +1 @@
1
- {"version":3,"file":"discord.js","sourceRoot":"","sources":["../../../src/servers/discord.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport type { IncomingMessage } from \"node:http\";\nimport path from \"node:path\";\nimport type { Duplex } from \"node:stream\";\nimport { WebSocket, WebSocketServer, type RawData } from \"ws\";\nimport {\n adminAuthError,\n constantTimeTokenEqual,\n hasAdminToken,\n InvalidJsonBodyError,\n isJsonObject,\n isLoopbackHost,\n parseUnknownRequestBody,\n queryRecord,\n readTrimmedString,\n RequestBodyTooLargeError,\n startHttpJsonServer,\n type ServerRequestEvent,\n} from \"./http.js\";\nimport {\n recordCommittedServerEvent,\n recordServerEvent,\n type ServerEventObserver,\n} from \"./recorder.js\";\nimport { closeWebSocketServer } from \"./websocket.js\";\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 45_000;\nconst DEFAULT_IDENTIFY_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_GATEWAY_PAYLOAD_BYTES = 4_096;\nconst DISCORD_EPOCH_MS = 1_420_070_400_000n;\nconst DISCORD_ID_PATTERN = /^\\d{17,20}$/u;\n\ntype DiscordUser = {\n avatar: null;\n bot?: boolean;\n discriminator: \"0\";\n global_name: string | null;\n id: string;\n username: string;\n};\n\ntype DiscordChannel = {\n guild_id?: string;\n id: string;\n last_message_id: string | null;\n name?: string;\n parent_id?: string | null;\n recipients?: DiscordUser[];\n type: number;\n};\n\ntype DiscordMessage = {\n allowed_mentions?: unknown;\n attachments: unknown[];\n author: DiscordUser;\n channel_id: string;\n components: unknown[];\n content: string;\n edited_timestamp: null;\n embeds: unknown[];\n flags: number;\n guild_id?: string;\n id: string;\n mention_everyone: boolean;\n mention_roles: string[];\n mentions: DiscordUser[];\n message_reference?: {\n channel_id: string;\n guild_id?: string;\n message_id: string;\n };\n nonce?: string | number;\n pinned: boolean;\n referenced_message?: DiscordMessage | null;\n timestamp: string;\n tts: boolean;\n type: number;\n};\n\ntype DiscordCommand = Record<string, unknown> & {\n application_id: string;\n id: string;\n version: string;\n};\n\ntype GatewayClient = {\n identified: boolean;\n sessionId?: string;\n socket: WebSocket;\n};\n\ntype GatewaySession = {\n lastSequence: number;\n};\n\ntype DiscordServerState = {\n adminToken: string;\n applicationId: string;\n botToken: string;\n botUser: DiscordUser;\n channels: Map<string, DiscordChannel>;\n commands: Map<string, DiscordCommand>;\n gatewayClients: Set<GatewayClient>;\n gatewayUrl?: string;\n guildCommands: Map<string, Map<string, DiscordCommand>>;\n guilds: Map<string, Record<string, unknown>>;\n heartbeatIntervalMs: number;\n identifyTimeoutMs: number;\n maxGatewayPayloadBytes: number;\n messages: Map<string, DiscordMessage[]>;\n nextSequence: number;\n onEvent: ServerEventObserver | undefined;\n pendingRecorderEvents: Set<Promise<void>>;\n recorderPath: string;\n sessions: Map<string, GatewaySession>;\n};\n\ntype DiscordRecorderEvent = ServerRequestEvent & { accepted?: boolean };\n\nexport type DiscordServerManifest = {\n adminToken: string;\n applicationId: string;\n baseUrl: string;\n botToken: string;\n botUserId: string;\n endpoints: {\n adminInboundUrl: string;\n apiRoot: string;\n gatewayBotUrl: string;\n gatewayUrl: string;\n };\n env: {\n DISCORD_BOT_TOKEN: string;\n };\n provider: \"discord\";\n recorderPath: string;\n version: 1;\n};\n\nexport type StartedDiscordServer = {\n close(): Promise<void>;\n manifest: DiscordServerManifest;\n};\n\nexport type StartDiscordServerParams = {\n adminToken?: string | undefined;\n applicationId?: string | undefined;\n botToken?: string | undefined;\n botUserId?: string | undefined;\n botUsername?: string | undefined;\n heartbeatIntervalMs?: number | undefined;\n host?: string | undefined;\n identifyTimeoutMs?: number | undefined;\n maxGatewayPayloadBytes?: number | undefined;\n onEvent?: ServerEventObserver | undefined;\n port?: number | undefined;\n recorderPath?: string | undefined;\n};\n\nfunction discordSnowflake(seed = 0): string {\n const timestamp = BigInt(Math.max(Date.now(), Number(DISCORD_EPOCH_MS))) - DISCORD_EPOCH_MS;\n return ((timestamp << 22n) | BigInt(seed & 0x3f_ffff)).toString();\n}\n\nexport function discordDirectChannelId(botUserId: string, recipientId: string): string {\n if (!DISCORD_ID_PATTERN.test(botUserId) || !DISCORD_ID_PATTERN.test(recipientId)) {\n throw new Error(\"Discord direct channel participants must be Discord snowflakes.\");\n }\n const digest = createHash(\"sha256\")\n .update([botUserId, recipientId].sort().join(\":\"))\n .digest(\"hex\");\n return (\n 100_000_000_000_000_000n +\n (BigInt(`0x${digest.slice(0, 16)}`) % 900_000_000_000_000_000n)\n ).toString();\n}\n\nfunction requireSnowflake(value: unknown, label: string): string {\n const id = readTrimmedString(value);\n if (!id || !DISCORD_ID_PATTERN.test(id)) {\n throw new DiscordRequestError(400, 50_035, `${label} must be a Discord snowflake.`);\n }\n return id;\n}\n\nfunction positiveInteger(value: number | undefined, fallback: number, label: string): number {\n const resolved = value ?? fallback;\n if (!Number.isSafeInteger(resolved) || resolved <= 0) {\n throw new RangeError(`${label} must be a positive safe integer.`);\n }\n return resolved;\n}\n\nclass DiscordRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: number,\n message: string,\n ) {\n super(message);\n this.name = \"DiscordRequestError\";\n }\n}\n\nfunction discordError(status: number, code: number, message: string): Response {\n return discordJson({ code, message }, status);\n}\n\nfunction rateLimitHeaders(headers?: ConstructorParameters<typeof Headers>[0]): Headers {\n return new Headers({\n \"x-ratelimit-bucket\": \"crabline-discord\",\n \"x-ratelimit-limit\": \"1000\",\n \"x-ratelimit-remaining\": \"999\",\n \"x-ratelimit-reset-after\": \"0\",\n ...Object.fromEntries(new Headers(headers)),\n });\n}\n\nfunction discordJson(value: unknown, status = 200): Response {\n return new Response(JSON.stringify(value), {\n headers: rateLimitHeaders({ \"content-type\": \"application/json\" }),\n status,\n });\n}\n\nfunction discordEmpty(status = 204): Response {\n return new Response(null, { headers: rateLimitHeaders(), status });\n}\n\nfunction authorizationError(request: IncomingMessage, state: DiscordServerState): Response | null {\n const authorization = request.headers.authorization?.trim();\n if (!authorization?.startsWith(\"Bot \")) {\n return new Response(JSON.stringify({ code: 0, message: \"401: Unauthorized\" }), {\n headers: rateLimitHeaders({\n \"content-type\": \"application/json\",\n \"www-authenticate\": 'Bot realm=\"Discord\"',\n }),\n status: 401,\n });\n }\n const token = authorization.slice(4);\n return constantTimeTokenEqual(token, state.botToken)\n ? null\n : new Response(JSON.stringify({ code: 0, message: \"401: Unauthorized\" }), {\n headers: rateLimitHeaders({ \"content-type\": \"application/json\" }),\n status: 401,\n });\n}\n\nfunction discordUser(id: string, username: string, bot = false): DiscordUser {\n return {\n avatar: null,\n ...(bot ? { bot: true } : {}),\n discriminator: \"0\",\n global_name: username,\n id,\n username,\n };\n}\n\nfunction ensureGuild(state: DiscordServerState, guildId: string): Record<string, unknown> {\n const current = state.guilds.get(guildId);\n if (current) {\n return current;\n }\n const guild = {\n afk_timeout: 300,\n channels: [],\n emojis: [],\n features: [],\n id: guildId,\n joined_at: new Date().toISOString(),\n large: false,\n member_count: 1,\n members: [\n {\n deaf: false,\n joined_at: new Date().toISOString(),\n mute: false,\n pending: false,\n roles: [],\n user: state.botUser,\n },\n ],\n name: \"Crabline Discord Guild\",\n owner_id: state.botUser.id,\n presences: [],\n roles: [\n {\n color: 0,\n hoist: false,\n id: guildId,\n managed: false,\n mentionable: false,\n name: \"@everyone\",\n permissions: \"0\",\n position: 0,\n },\n ],\n unavailable: false,\n voice_states: [],\n };\n state.guilds.set(guildId, guild);\n return guild;\n}\n\nfunction ensureChannel(params: {\n channelId: string;\n guildId?: string;\n parentId?: string;\n sender?: DiscordUser;\n state: DiscordServerState;\n}): DiscordChannel {\n const current = params.state.channels.get(params.channelId);\n if (current) {\n return current;\n }\n const channel: DiscordChannel = params.guildId\n ? {\n guild_id: params.guildId,\n id: params.channelId,\n last_message_id: null,\n name: params.parentId ? \"crabline-thread\" : \"crabline-channel\",\n parent_id: params.parentId ?? null,\n type: params.parentId ? 11 : 0,\n }\n : {\n id: params.channelId,\n last_message_id: null,\n recipients: params.sender ? [params.sender] : [],\n type: 1,\n };\n params.state.channels.set(params.channelId, channel);\n if (params.guildId) {\n const guild = ensureGuild(params.state, params.guildId);\n const channels = Array.isArray(guild.channels) ? guild.channels : [];\n guild.channels = [...channels, channel];\n }\n return channel;\n}\n\nfunction parseMentions(content: string, state: DiscordServerState): DiscordUser[] {\n const ids = new Set<string>();\n for (const match of content.matchAll(/<@!?(\\d{17,20})>/gu)) {\n ids.add(match[1]!);\n }\n return [...ids].map((id) =>\n id === state.botUser.id ? state.botUser : discordUser(id, `user-${id.slice(-6)}`),\n );\n}\n\nfunction resolveMessageReference(\n state: DiscordServerState,\n channelId: string,\n value: unknown,\n): DiscordMessage[\"message_reference\"] | undefined {\n if (!isJsonObject(value)) {\n return undefined;\n }\n const messageId = readTrimmedString(value.message_id);\n if (!messageId) {\n return undefined;\n }\n const referencedChannelId = readTrimmedString(value.channel_id) ?? channelId;\n const channel = state.channels.get(referencedChannelId);\n return {\n channel_id: referencedChannelId,\n ...(channel?.guild_id ? { guild_id: channel.guild_id } : {}),\n message_id: messageId,\n };\n}\n\nfunction findMessage(\n state: DiscordServerState,\n channelId: string,\n messageId: string,\n): DiscordMessage | undefined {\n return state.messages.get(channelId)?.find((message) => message.id === messageId);\n}\n\nfunction createMessage(params: {\n author: DiscordUser;\n body: Record<string, unknown>;\n channel: DiscordChannel;\n state: DiscordServerState;\n}): DiscordMessage {\n const content = typeof params.body.content === \"string\" ? params.body.content : \"\";\n const embeds = Array.isArray(params.body.embeds) ? params.body.embeds : [];\n const components = Array.isArray(params.body.components) ? params.body.components : [];\n const attachments = Array.isArray(params.body.attachments) ? params.body.attachments : [];\n if (!content && embeds.length === 0 && components.length === 0 && attachments.length === 0) {\n throw new DiscordRequestError(400, 50_006, \"Cannot send an empty message\");\n }\n if (content.length > 2_000) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n const reference = resolveMessageReference(\n params.state,\n params.channel.id,\n params.body.message_reference,\n );\n const referencedMessage = reference\n ? (findMessage(params.state, reference.channel_id, reference.message_id) ?? null)\n : undefined;\n const failIfNotExists = isJsonObject(params.body.message_reference)\n ? params.body.message_reference.fail_if_not_exists\n : undefined;\n if (reference && referencedMessage === null && failIfNotExists !== false) {\n throw new DiscordRequestError(404, 10_008, \"Unknown Message\");\n }\n const message: DiscordMessage = {\n ...(params.body.allowed_mentions !== undefined\n ? { allowed_mentions: params.body.allowed_mentions }\n : {}),\n attachments,\n author: params.author,\n channel_id: params.channel.id,\n components,\n content,\n edited_timestamp: null,\n embeds,\n flags: typeof params.body.flags === \"number\" ? params.body.flags : 0,\n ...(params.channel.guild_id ? { guild_id: params.channel.guild_id } : {}),\n id: discordSnowflake(params.state.nextSequence),\n mention_everyone: /@(everyone|here)\\b/u.test(content),\n mention_roles: [...content.matchAll(/<@&(\\d{17,20})>/gu)].map((match) => match[1]!),\n mentions: parseMentions(content, params.state),\n ...(reference\n ? {\n message_reference: reference,\n ...(referencedMessage !== undefined ? { referenced_message: referencedMessage } : {}),\n }\n : {}),\n ...(typeof params.body.nonce === \"string\" || typeof params.body.nonce === \"number\"\n ? { nonce: params.body.nonce }\n : {}),\n pinned: false,\n timestamp: new Date().toISOString(),\n tts: params.body.tts === true,\n type: reference ? 19 : 0,\n };\n params.state.messages.set(params.channel.id, [\n ...(params.state.messages.get(params.channel.id) ?? []),\n message,\n ]);\n params.channel.last_message_id = message.id;\n return message;\n}\n\nfunction sendGatewayPayload(socket: WebSocket, payload: unknown): boolean {\n if (socket.readyState !== WebSocket.OPEN) {\n return false;\n }\n socket.send(JSON.stringify(payload));\n return true;\n}\n\nfunction dispatchGatewayEvent(state: DiscordServerState, type: string, data: unknown): void {\n const payload = { d: data, op: 0, s: state.nextSequence++, t: type };\n for (const client of state.gatewayClients) {\n if (client.identified) {\n sendGatewayPayload(client.socket, payload);\n if (client.sessionId) {\n const session = state.sessions.get(client.sessionId);\n if (session) {\n session.lastSequence = payload.s;\n }\n }\n }\n }\n}\n\nfunction recordGatewayEvent(state: DiscordServerState, body: unknown, accepted: boolean): void {\n const pending = recordCommittedServerEvent({\n event: {\n accepted,\n at: new Date().toISOString(),\n body,\n method: \"WS\",\n path: \"/gateway\",\n query: {},\n type: \"api\",\n } as DiscordRecorderEvent,\n onEvent: state.onEvent,\n recorderPath: state.recorderPath,\n });\n state.pendingRecorderEvents.add(pending);\n void pending.then(\n () => state.pendingRecorderEvents.delete(pending),\n () => state.pendingRecorderEvents.delete(pending),\n );\n}\n\nfunction readyPayload(state: DiscordServerState, sessionId: string) {\n return {\n application: { flags: 0, id: state.applicationId },\n guilds: [...state.guilds.values()].map((guild) => ({ id: guild.id, unavailable: true })),\n resume_gateway_url: state.gatewayUrl!,\n session_id: sessionId,\n user: state.botUser,\n v: 10,\n };\n}\n\nfunction attachGatewayServer(params: {\n server: import(\"node:http\").Server;\n state: DiscordServerState;\n}) {\n const gatewayServer = new WebSocketServer({\n maxPayload: params.state.maxGatewayPayloadBytes,\n noServer: true,\n });\n const onUpgrade = (request: IncomingMessage, socket: Duplex, head: Buffer) => {\n const url = new URL(request.url ?? \"/\", \"http://127.0.0.1\");\n if (url.pathname !== \"/gateway\") {\n socket.destroy();\n return;\n }\n if ((url.searchParams.get(\"v\") ?? \"10\") !== \"10\") {\n socket.destroy();\n return;\n }\n const encoding = url.searchParams.get(\"encoding\") ?? \"json\";\n if (encoding !== \"json\") {\n socket.destroy();\n return;\n }\n gatewayServer.handleUpgrade(request, socket, head, (client) => {\n gatewayServer.emit(\"connection\", client, request);\n });\n };\n params.server.on(\"upgrade\", onUpgrade);\n\n gatewayServer.on(\"connection\", (socket) => {\n const client: GatewayClient = { identified: false, socket };\n params.state.gatewayClients.add(client);\n sendGatewayPayload(socket, {\n d: { heartbeat_interval: params.state.heartbeatIntervalMs },\n op: 10,\n });\n const identifyTimeout = setTimeout(() => {\n if (!client.identified) {\n socket.close(4_003, \"Not authenticated\");\n }\n }, params.state.identifyTimeoutMs);\n identifyTimeout.unref();\n\n socket.on(\"message\", (raw: RawData) => {\n if (Buffer.byteLength(raw.toString()) > params.state.maxGatewayPayloadBytes) {\n socket.close(4_002, \"Decode error\");\n return;\n }\n let payload: unknown;\n try {\n payload = JSON.parse(raw.toString()) as unknown;\n } catch {\n socket.close(4_002, \"Decode error\");\n return;\n }\n if (!isJsonObject(payload) || typeof payload.op !== \"number\") {\n socket.close(4_002, \"Decode error\");\n return;\n }\n recordGatewayEvent(params.state, payload, true);\n if (payload.op === 1) {\n sendGatewayPayload(socket, { d: null, op: 11 });\n return;\n }\n if (payload.op === 2) {\n if (client.identified || !isJsonObject(payload.d)) {\n socket.close(4_005, \"Already authenticated\");\n return;\n }\n const token = readTrimmedString(payload.d.token);\n if (!token || !constantTimeTokenEqual(token, params.state.botToken)) {\n socket.close(4_004, \"Authentication failed\");\n return;\n }\n clearTimeout(identifyTimeout);\n client.identified = true;\n client.sessionId = randomUUID();\n params.state.sessions.set(client.sessionId, { lastSequence: params.state.nextSequence });\n if (params.state.sessions.size > 128) {\n const oldestSessionId = params.state.sessions.keys().next().value as string | undefined;\n if (oldestSessionId) {\n params.state.sessions.delete(oldestSessionId);\n }\n }\n sendGatewayPayload(socket, {\n d: readyPayload(params.state, client.sessionId),\n op: 0,\n s: params.state.nextSequence++,\n t: \"READY\",\n });\n for (const guild of params.state.guilds.values()) {\n dispatchGatewayEvent(params.state, \"GUILD_CREATE\", guild);\n }\n return;\n }\n if (payload.op === 6) {\n if (!isJsonObject(payload.d)) {\n sendGatewayPayload(socket, { d: false, op: 9 });\n return;\n }\n const token = readTrimmedString(payload.d.token);\n const sessionId = readTrimmedString(payload.d.session_id);\n const session = sessionId ? params.state.sessions.get(sessionId) : undefined;\n if (\n !token ||\n !constantTimeTokenEqual(token, params.state.botToken) ||\n !sessionId ||\n !Number.isSafeInteger(payload.d.seq) ||\n (payload.d.seq as number) < 0 ||\n !session ||\n payload.d.seq !== session.lastSequence\n ) {\n sendGatewayPayload(socket, { d: false, op: 9 });\n return;\n }\n clearTimeout(identifyTimeout);\n client.identified = true;\n client.sessionId = sessionId;\n params.state.sessions.delete(sessionId);\n params.state.sessions.set(sessionId, session);\n const resumedSequence = params.state.nextSequence++;\n session.lastSequence = resumedSequence;\n sendGatewayPayload(socket, {\n d: {},\n op: 0,\n s: resumedSequence,\n t: \"RESUMED\",\n });\n return;\n }\n if (payload.op === 3 || payload.op === 4 || payload.op === 8) {\n return;\n }\n socket.close(4_001, \"Unknown opcode\");\n });\n socket.on(\"error\", () => undefined);\n socket.once(\"close\", () => {\n clearTimeout(identifyTimeout);\n params.state.gatewayClients.delete(client);\n });\n });\n\n return async () => {\n params.server.off(\"upgrade\", onUpgrade);\n await closeWebSocketServer(gatewayServer);\n };\n}\n\nfunction commandBody(\n state: DiscordServerState,\n body: Record<string, unknown>,\n existing?: DiscordCommand,\n guildId?: string,\n): DiscordCommand {\n const name = readTrimmedString(body.name ?? existing?.name);\n if (!name || name.length > 32 || !/^[\\w-]+$/u.test(name)) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n return {\n ...existing,\n ...body,\n application_id: state.applicationId,\n description: readTrimmedString(body.description ?? existing?.description) ?? \"\",\n ...(guildId ? { guild_id: guildId } : {}),\n id: existing?.id ?? discordSnowflake(state.nextSequence++),\n name,\n type: typeof body.type === \"number\" ? body.type : (existing?.type ?? 1),\n version: discordSnowflake(state.nextSequence++),\n };\n}\n\nasync function handleAdminInbound(params: {\n body: Record<string, unknown>;\n state: DiscordServerState;\n}): Promise<Response> {\n const requestedChannelId = requireSnowflake(params.body.channelId, \"channelId\");\n const guildId =\n params.body.guildId === undefined\n ? undefined\n : requireSnowflake(params.body.guildId, \"guildId\");\n const senderId = requireSnowflake(params.body.senderId, \"senderId\");\n const parentChannelId =\n params.body.parentChannelId === undefined\n ? undefined\n : requireSnowflake(params.body.parentChannelId, \"parentChannelId\");\n if (parentChannelId && !guildId) {\n throw new DiscordRequestError(400, 50_035, \"Threads require guildId.\");\n }\n const sender = discordUser(\n senderId,\n readTrimmedString(params.body.senderName) ?? `user-${senderId.slice(-6)}`,\n );\n const hadChannel = params.state.channels.has(requestedChannelId);\n const hadGuild = guildId ? params.state.guilds.has(guildId) : true;\n const channel = ensureChannel({\n channelId: requestedChannelId,\n ...(guildId ? { guildId } : {}),\n ...(parentChannelId ? { parentId: parentChannelId } : {}),\n sender,\n state: params.state,\n });\n const message = createMessage({\n author: sender,\n body: params.body,\n channel,\n state: params.state,\n });\n if (guildId) {\n const guild = params.state.guilds.get(guildId)!;\n const members = Array.isArray(guild.members) ? guild.members : [];\n if (\n !members.some(\n (member) =>\n isJsonObject(member) && isJsonObject(member.user) && member.user.id === sender.id,\n )\n ) {\n members.push({\n deaf: false,\n joined_at: new Date().toISOString(),\n mute: false,\n pending: false,\n roles: [],\n user: sender,\n });\n guild.members = members;\n guild.member_count = members.length;\n }\n (message as DiscordMessage & { member: Record<string, unknown> }).member = {\n deaf: false,\n joined_at: new Date().toISOString(),\n mute: false,\n pending: false,\n roles: [],\n };\n }\n if (!hadGuild && guildId) {\n dispatchGatewayEvent(params.state, \"GUILD_CREATE\", params.state.guilds.get(guildId));\n }\n if (!hadChannel) {\n dispatchGatewayEvent(params.state, \"CHANNEL_CREATE\", channel);\n }\n dispatchGatewayEvent(params.state, \"MESSAGE_CREATE\", message);\n return discordJson({ event: { d: message, op: 0, t: \"MESSAGE_CREATE\" }, message });\n}\n\nasync function handleDiscordApi(params: {\n body: unknown;\n method: string;\n pathname: string;\n state: DiscordServerState;\n}): Promise<Response> {\n const pathParts = params.pathname.split(\"/\").filter(Boolean);\n if (pathParts[0] !== \"api\" || pathParts[1] !== \"v10\") {\n return discordError(404, 0, \"404: Not Found\");\n }\n const route = pathParts.slice(2);\n if (params.method === \"GET\" && route.join(\"/\") === \"users/@me\") {\n return discordJson(params.state.botUser);\n }\n if (params.method === \"GET\" && route.join(\"/\") === \"oauth2/applications/@me\") {\n return discordJson({\n bot: params.state.botUser,\n flags: 0,\n id: params.state.applicationId,\n name: \"Crabline Discord Application\",\n owner: params.state.botUser,\n verify_key: \"crabline\",\n });\n }\n if (params.method === \"GET\" && route.join(\"/\") === \"gateway\") {\n return discordJson({ url: params.state.gatewayUrl });\n }\n if (params.method === \"GET\" && route.join(\"/\") === \"gateway/bot\") {\n return discordJson({\n session_start_limit: {\n max_concurrency: 1,\n remaining: 1_000,\n reset_after: 0,\n total: 1_000,\n },\n shards: 1,\n url: params.state.gatewayUrl,\n });\n }\n if (route[0] === \"channels\" && route.length >= 2) {\n const channelId = requireSnowflake(route[1], \"channel id\");\n const channel = params.state.channels.get(channelId);\n if (route.length === 2 && params.method === \"GET\") {\n return channel ? discordJson(channel) : discordError(404, 10_003, \"Unknown Channel\");\n }\n if (route[2] === \"typing\" && route.length === 3 && params.method === \"POST\") {\n return channel ? discordEmpty() : discordError(404, 10_003, \"Unknown Channel\");\n }\n if (route[2] === \"messages\") {\n if (!channel) {\n return discordError(404, 10_003, \"Unknown Channel\");\n }\n if (route.length === 3 && params.method === \"POST\") {\n if (!isJsonObject(params.body)) {\n throw new InvalidJsonBodyError(undefined, \"Request body must be a JSON object.\");\n }\n const message = createMessage({\n author: params.state.botUser,\n body: params.body,\n channel,\n state: params.state,\n });\n dispatchGatewayEvent(params.state, \"MESSAGE_CREATE\", message);\n return discordJson(message);\n }\n if (route.length === 3 && params.method === \"GET\") {\n return discordJson(\n [...(params.state.messages.get(channelId) ?? [])].reverse().slice(0, 50),\n );\n }\n const messageId = route[3] ? requireSnowflake(route[3], \"message id\") : undefined;\n if (\n messageId &&\n route[4] === \"reactions\" &&\n route[5] &&\n route[6] === \"@me\" &&\n (params.method === \"PUT\" || params.method === \"DELETE\")\n ) {\n return findMessage(params.state, channelId, messageId)\n ? discordEmpty()\n : discordError(404, 10_008, \"Unknown Message\");\n }\n if (messageId && params.method === \"GET\") {\n const message = findMessage(params.state, channelId, messageId);\n return message ? discordJson(message) : discordError(404, 10_008, \"Unknown Message\");\n }\n }\n }\n if (params.method === \"POST\" && route.join(\"/\") === \"users/@me/channels\") {\n if (!isJsonObject(params.body)) {\n throw new InvalidJsonBodyError(undefined, \"Request body must be a JSON object.\");\n }\n const recipientId = requireSnowflake(params.body.recipient_id, \"recipient_id\");\n const recipient = discordUser(recipientId, `user-${recipientId.slice(-6)}`);\n const channelId = discordDirectChannelId(params.state.botUser.id, recipientId);\n return discordJson(ensureChannel({ channelId, sender: recipient, state: params.state }));\n }\n if (route[0] === \"guilds\" && route[1]) {\n const guildId = requireSnowflake(route[1], \"guild id\");\n const guild = params.state.guilds.get(guildId);\n if (!guild) {\n return discordError(404, 10_004, \"Unknown Guild\");\n }\n if (route.length === 2 && params.method === \"GET\") {\n return discordJson(guild);\n }\n if (route[2] === \"channels\" && params.method === \"GET\") {\n return discordJson(\n [...params.state.channels.values()].filter((channel) => channel.guild_id === guildId),\n );\n }\n if (route[2] === \"roles\" && params.method === \"GET\") {\n return discordJson(guild.roles ?? []);\n }\n if (route[2] === \"members\" && route[3] && params.method === \"GET\") {\n const userId = requireSnowflake(route[3], \"user id\");\n const user =\n userId === params.state.botUser.id\n ? params.state.botUser\n : discordUser(userId, `user-${userId.slice(-6)}`);\n return discordJson({\n deaf: false,\n joined_at: new Date().toISOString(),\n mute: false,\n pending: false,\n roles: [],\n user,\n });\n }\n }\n if (route[0] === \"applications\" && route[1] === params.state.applicationId) {\n let commandOffset = 2;\n let guildId: string | undefined;\n if (route[2] === \"guilds\" && route[3] && route[4] === \"commands\") {\n guildId = requireSnowflake(route[3], \"guild id\");\n commandOffset = 4;\n }\n if (route[commandOffset] === \"commands\") {\n const commands = guildId\n ? (params.state.guildCommands.get(guildId) ?? new Map<string, DiscordCommand>())\n : params.state.commands;\n if (guildId && !params.state.guildCommands.has(guildId)) {\n params.state.guildCommands.set(guildId, commands);\n }\n const commandId = route[commandOffset + 1];\n if (!commandId && params.method === \"GET\") {\n return discordJson([...commands.values()]);\n }\n if (!commandId && params.method === \"PUT\") {\n if (!Array.isArray(params.body) || params.body.some((entry) => !isJsonObject(entry))) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n commands.clear();\n for (const body of params.body as Record<string, unknown>[]) {\n const command = commandBody(params.state, body, undefined, guildId);\n commands.set(command.id, command);\n }\n return discordJson([...commands.values()]);\n }\n if (!commandId && params.method === \"POST\") {\n if (!isJsonObject(params.body)) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n const name = readTrimmedString(params.body.name);\n const type = typeof params.body.type === \"number\" ? params.body.type : 1;\n const existing = [...commands.values()].find(\n (command) => command.name === name && command.type === type,\n );\n const command = commandBody(params.state, params.body, existing, guildId);\n commands.set(command.id, command);\n return discordJson(command, existing ? 200 : 201);\n }\n if (commandId) {\n const existing = commands.get(commandId);\n if (!existing) {\n return discordError(404, 10_063, \"Unknown application command\");\n }\n if (params.method === \"PATCH\") {\n if (!isJsonObject(params.body)) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n const command = commandBody(params.state, params.body, existing, guildId);\n commands.set(commandId, command);\n return discordJson(command);\n }\n if (params.method === \"DELETE\") {\n commands.delete(commandId);\n return discordEmpty();\n }\n }\n }\n }\n return discordError(404, 0, \"404: Not Found\");\n}\n\nasync function handleRequest(params: {\n request: IncomingMessage;\n state: DiscordServerState;\n}): Promise<Response> {\n const url = new URL(params.request.url ?? \"/\", \"http://127.0.0.1\");\n const method = params.request.method ?? \"GET\";\n if (url.pathname === \"/crabline/discord/inbound\") {\n if (method !== \"POST\") {\n return new Response(\"not found\", { status: 404 });\n }\n if (!hasAdminToken(params.request, params.state.adminToken)) {\n params.request.resume();\n return adminAuthError();\n }\n const body = await parseUnknownRequestBody(params.request);\n if (!isJsonObject(body)) {\n throw new InvalidJsonBodyError(undefined, \"Request body must be a JSON object.\");\n }\n const event: DiscordRecorderEvent = {\n at: new Date().toISOString(),\n body,\n method,\n path: url.pathname,\n query: queryRecord(url),\n type: \"admin\",\n };\n const response = await handleAdminInbound({ body, state: params.state });\n event.accepted = response.ok;\n await recordCommittedServerEvent({\n event,\n onEvent: params.state.onEvent,\n recorderPath: params.state.recorderPath,\n });\n return response;\n }\n const authError =\n method === \"GET\" && url.pathname === \"/api/v10/gateway\"\n ? null\n : authorizationError(params.request, params.state);\n if (authError) {\n params.request.resume();\n return authError;\n }\n const body =\n method === \"GET\" || method === \"DELETE\" ? {} : await parseUnknownRequestBody(params.request);\n const event: DiscordRecorderEvent = {\n at: new Date().toISOString(),\n ...(isJsonObject(body) && Object.keys(body).length > 0 ? { body } : {}),\n method,\n path: url.pathname,\n query: queryRecord(url),\n type: \"api\",\n };\n const response = await handleDiscordApi({\n body,\n method,\n pathname: url.pathname,\n state: params.state,\n });\n event.accepted = response.ok;\n await (response.ok ? recordCommittedServerEvent : recordServerEvent)({\n event,\n onEvent: params.state.onEvent,\n recorderPath: params.state.recorderPath,\n });\n return response;\n}\n\nexport async function startDiscordServer(\n params: StartDiscordServerParams = {},\n): Promise<StartedDiscordServer> {\n const host = params.host ?? \"127.0.0.1\";\n const applicationId = params.applicationId ?? \"135000000000000001\";\n const botUserId = params.botUserId ?? applicationId;\n requireSnowflake(applicationId, \"applicationId\");\n requireSnowflake(botUserId, \"botUserId\");\n const encodedApplicationId = Buffer.from(applicationId, \"utf8\").toString(\"base64url\");\n const externallyBound = !isLoopbackHost(host);\n const state: DiscordServerState = {\n adminToken: params.adminToken ?? randomBytes(24).toString(\"base64url\"),\n applicationId,\n botToken:\n params.botToken ??\n (externallyBound\n ? `${encodedApplicationId}.${randomBytes(6).toString(\"base64url\")}.${randomBytes(24).toString(\"base64url\")}`\n : `${encodedApplicationId}.crabline.discord`),\n botUser: discordUser(botUserId, params.botUsername ?? \"crabline\", true),\n channels: new Map(),\n commands: new Map(),\n gatewayClients: new Set(),\n guildCommands: new Map(),\n guilds: new Map(),\n heartbeatIntervalMs: positiveInteger(\n params.heartbeatIntervalMs,\n DEFAULT_HEARTBEAT_INTERVAL_MS,\n \"heartbeatIntervalMs\",\n ),\n identifyTimeoutMs: positiveInteger(\n params.identifyTimeoutMs,\n DEFAULT_IDENTIFY_TIMEOUT_MS,\n \"identifyTimeoutMs\",\n ),\n maxGatewayPayloadBytes: positiveInteger(\n params.maxGatewayPayloadBytes,\n DEFAULT_MAX_GATEWAY_PAYLOAD_BYTES,\n \"maxGatewayPayloadBytes\",\n ),\n messages: new Map(),\n nextSequence: 1,\n onEvent: params.onEvent,\n pendingRecorderEvents: new Set(),\n recorderPath: params.recorderPath ?? path.resolve(\".crabline\", \"servers\", \"discord.jsonl\"),\n sessions: new Map(),\n };\n const httpServer = await startHttpJsonServer({\n handle: (request) => handleRequest({ request, state }),\n handleError: (error) => {\n if (error instanceof DiscordRequestError) {\n return discordError(error.status, error.code, error.message);\n }\n if (error instanceof InvalidJsonBodyError) {\n return discordError(400, 50_035, \"Invalid Form Body\");\n }\n if (error instanceof RequestBodyTooLargeError) {\n return discordError(413, 40_005, \"Request entity too large\");\n }\n return undefined;\n },\n host,\n port: params.port ?? 0,\n serverName: \"Discord\",\n });\n state.gatewayUrl = `${httpServer.baseUrl.replace(/^http/u, \"ws\")}/gateway`;\n const closeGateway = attachGatewayServer({ server: httpServer.server, state });\n return {\n async close() {\n await closeGateway();\n await httpServer.close();\n await Promise.all([...state.pendingRecorderEvents]);\n state.sessions.clear();\n },\n manifest: {\n adminToken: state.adminToken,\n applicationId: state.applicationId,\n baseUrl: httpServer.baseUrl,\n botToken: state.botToken,\n botUserId: state.botUser.id,\n endpoints: {\n adminInboundUrl: `${httpServer.baseUrl}/crabline/discord/inbound`,\n apiRoot: `${httpServer.baseUrl}/api`,\n gatewayBotUrl: `${httpServer.baseUrl}/api/v10/gateway/bot`,\n gatewayUrl: state.gatewayUrl,\n },\n env: { DISCORD_BOT_TOKEN: state.botToken },\n provider: \"discord\",\n recorderPath: state.recorderPath,\n version: 1,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"discord.js","sourceRoot":"","sources":["../../../src/servers/discord.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport type { IncomingMessage } from \"node:http\";\nimport path from \"node:path\";\nimport type { Duplex } from \"node:stream\";\nimport { WebSocket, WebSocketServer, type RawData } from \"ws\";\nimport {\n adminAuthError,\n createServerClose,\n constantTimeTokenEqual,\n hasAdminToken,\n InvalidJsonBodyError,\n isJsonObject,\n isLoopbackHost,\n parseUnknownRequestBody,\n queryRecord,\n readTrimmedString,\n RequestBodyTooLargeError,\n startHttpJsonServer,\n type ServerRequestEvent,\n} from \"./http.js\";\nimport { createServerRecorder, type ServerRecorder, type ServerEventObserver } from \"./recorder.js\";\nimport { closeWebSocketServer } from \"./websocket.js\";\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 45_000;\nconst DEFAULT_IDENTIFY_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_GATEWAY_PAYLOAD_BYTES = 4_096;\nconst DISCORD_EPOCH_MS = 1_420_070_400_000n;\nconst DISCORD_ID_PATTERN = /^\\d{17,20}$/u;\n\ntype DiscordUser = {\n avatar: null;\n bot?: boolean;\n discriminator: \"0\";\n global_name: string | null;\n id: string;\n username: string;\n};\n\ntype DiscordChannel = {\n guild_id?: string;\n id: string;\n last_message_id: string | null;\n name?: string;\n parent_id?: string | null;\n recipients?: DiscordUser[];\n type: number;\n};\n\ntype DiscordMessage = {\n allowed_mentions?: unknown;\n attachments: unknown[];\n author: DiscordUser;\n channel_id: string;\n components: unknown[];\n content: string;\n edited_timestamp: null;\n embeds: unknown[];\n flags: number;\n guild_id?: string;\n id: string;\n mention_everyone: boolean;\n mention_roles: string[];\n mentions: DiscordUser[];\n message_reference?: {\n channel_id: string;\n guild_id?: string;\n message_id: string;\n };\n nonce?: string | number;\n pinned: boolean;\n referenced_message?: DiscordMessage | null;\n timestamp: string;\n tts: boolean;\n type: number;\n};\n\ntype DiscordCommand = Record<string, unknown> & {\n application_id: string;\n id: string;\n version: string;\n};\n\ntype GatewayClient = {\n identified: boolean;\n sessionId?: string;\n socket: WebSocket;\n};\n\ntype GatewaySession = {\n lastSequence: number;\n};\n\ntype DiscordServerState = {\n adminToken: string;\n applicationId: string;\n botToken: string;\n botUser: DiscordUser;\n channels: Map<string, DiscordChannel>;\n commands: Map<string, DiscordCommand>;\n gatewayClients: Set<GatewayClient>;\n gatewayUrl?: string;\n guildCommands: Map<string, Map<string, DiscordCommand>>;\n guilds: Map<string, Record<string, unknown>>;\n heartbeatIntervalMs: number;\n identifyTimeoutMs: number;\n maxGatewayPayloadBytes: number;\n messages: Map<string, DiscordMessage[]>;\n nextSequence: number;\n recorder: ServerRecorder;\n recorderPath: string;\n sessions: Map<string, GatewaySession>;\n};\n\ntype DiscordRecorderEvent = ServerRequestEvent & { accepted?: boolean };\n\nexport type DiscordServerManifest = {\n adminToken: string;\n applicationId: string;\n baseUrl: string;\n botToken: string;\n botUserId: string;\n endpoints: {\n adminInboundUrl: string;\n apiRoot: string;\n gatewayBotUrl: string;\n gatewayUrl: string;\n };\n env: {\n DISCORD_BOT_TOKEN: string;\n };\n provider: \"discord\";\n recorderPath: string;\n version: 1;\n};\n\nexport type StartedDiscordServer = {\n close(): Promise<void>;\n manifest: DiscordServerManifest;\n};\n\nexport type StartDiscordServerParams = {\n adminToken?: string | undefined;\n applicationId?: string | undefined;\n botToken?: string | undefined;\n botUserId?: string | undefined;\n botUsername?: string | undefined;\n heartbeatIntervalMs?: number | undefined;\n host?: string | undefined;\n identifyTimeoutMs?: number | undefined;\n maxGatewayPayloadBytes?: number | undefined;\n onEvent?: ServerEventObserver | undefined;\n port?: number | undefined;\n recorderPath?: string | undefined;\n};\n\nfunction discordSnowflake(seed = 0): string {\n const timestamp = BigInt(Math.max(Date.now(), Number(DISCORD_EPOCH_MS))) - DISCORD_EPOCH_MS;\n return ((timestamp << 22n) | BigInt(seed & 0x3f_ffff)).toString();\n}\n\nexport function discordDirectChannelId(botUserId: string, recipientId: string): string {\n if (!DISCORD_ID_PATTERN.test(botUserId) || !DISCORD_ID_PATTERN.test(recipientId)) {\n throw new Error(\"Discord direct channel participants must be Discord snowflakes.\");\n }\n const digest = createHash(\"sha256\")\n .update([botUserId, recipientId].sort().join(\":\"))\n .digest(\"hex\");\n return (\n 100_000_000_000_000_000n +\n (BigInt(`0x${digest.slice(0, 16)}`) % 900_000_000_000_000_000n)\n ).toString();\n}\n\nfunction requireSnowflake(value: unknown, label: string): string {\n const id = readTrimmedString(value);\n if (!id || !DISCORD_ID_PATTERN.test(id)) {\n throw new DiscordRequestError(400, 50_035, `${label} must be a Discord snowflake.`);\n }\n return id;\n}\n\nfunction positiveInteger(value: number | undefined, fallback: number, label: string): number {\n const resolved = value ?? fallback;\n if (!Number.isSafeInteger(resolved) || resolved <= 0) {\n throw new RangeError(`${label} must be a positive safe integer.`);\n }\n return resolved;\n}\n\nclass DiscordRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: number,\n message: string,\n ) {\n super(message);\n this.name = \"DiscordRequestError\";\n }\n}\n\nfunction discordError(status: number, code: number, message: string): Response {\n return discordJson({ code, message }, status);\n}\n\nfunction rateLimitHeaders(headers?: ConstructorParameters<typeof Headers>[0]): Headers {\n return new Headers({\n \"x-ratelimit-bucket\": \"crabline-discord\",\n \"x-ratelimit-limit\": \"1000\",\n \"x-ratelimit-remaining\": \"999\",\n \"x-ratelimit-reset-after\": \"0\",\n ...Object.fromEntries(new Headers(headers)),\n });\n}\n\nfunction discordJson(value: unknown, status = 200): Response {\n return new Response(JSON.stringify(value), {\n headers: rateLimitHeaders({ \"content-type\": \"application/json\" }),\n status,\n });\n}\n\nfunction discordEmpty(status = 204): Response {\n return new Response(null, { headers: rateLimitHeaders(), status });\n}\n\nfunction authorizationError(request: IncomingMessage, state: DiscordServerState): Response | null {\n const authorization = request.headers.authorization?.trim();\n if (!authorization?.startsWith(\"Bot \")) {\n return new Response(JSON.stringify({ code: 0, message: \"401: Unauthorized\" }), {\n headers: rateLimitHeaders({\n \"content-type\": \"application/json\",\n \"www-authenticate\": 'Bot realm=\"Discord\"',\n }),\n status: 401,\n });\n }\n const token = authorization.slice(4);\n return constantTimeTokenEqual(token, state.botToken)\n ? null\n : new Response(JSON.stringify({ code: 0, message: \"401: Unauthorized\" }), {\n headers: rateLimitHeaders({ \"content-type\": \"application/json\" }),\n status: 401,\n });\n}\n\nfunction discordUser(id: string, username: string, bot = false): DiscordUser {\n return {\n avatar: null,\n ...(bot ? { bot: true } : {}),\n discriminator: \"0\",\n global_name: username,\n id,\n username,\n };\n}\n\nfunction ensureGuild(state: DiscordServerState, guildId: string): Record<string, unknown> {\n const current = state.guilds.get(guildId);\n if (current) {\n return current;\n }\n const guild = {\n afk_timeout: 300,\n channels: [],\n emojis: [],\n features: [],\n id: guildId,\n joined_at: new Date().toISOString(),\n large: false,\n member_count: 1,\n members: [\n {\n deaf: false,\n joined_at: new Date().toISOString(),\n mute: false,\n pending: false,\n roles: [],\n user: state.botUser,\n },\n ],\n name: \"Crabline Discord Guild\",\n owner_id: state.botUser.id,\n presences: [],\n roles: [\n {\n color: 0,\n hoist: false,\n id: guildId,\n managed: false,\n mentionable: false,\n name: \"@everyone\",\n permissions: \"0\",\n position: 0,\n },\n ],\n unavailable: false,\n voice_states: [],\n };\n state.guilds.set(guildId, guild);\n return guild;\n}\n\nfunction ensureChannel(params: {\n channelId: string;\n guildId?: string;\n parentId?: string;\n sender?: DiscordUser;\n state: DiscordServerState;\n}): DiscordChannel {\n const current = params.state.channels.get(params.channelId);\n if (current) {\n return current;\n }\n const channel: DiscordChannel = params.guildId\n ? {\n guild_id: params.guildId,\n id: params.channelId,\n last_message_id: null,\n name: params.parentId ? \"crabline-thread\" : \"crabline-channel\",\n parent_id: params.parentId ?? null,\n type: params.parentId ? 11 : 0,\n }\n : {\n id: params.channelId,\n last_message_id: null,\n recipients: params.sender ? [params.sender] : [],\n type: 1,\n };\n params.state.channels.set(params.channelId, channel);\n if (params.guildId) {\n const guild = ensureGuild(params.state, params.guildId);\n const channels = Array.isArray(guild.channels) ? guild.channels : [];\n guild.channels = [...channels, channel];\n }\n return channel;\n}\n\nfunction parseMentions(content: string, state: DiscordServerState): DiscordUser[] {\n const ids = new Set<string>();\n for (const match of content.matchAll(/<@!?(\\d{17,20})>/gu)) {\n ids.add(match[1]!);\n }\n return [...ids].map((id) =>\n id === state.botUser.id ? state.botUser : discordUser(id, `user-${id.slice(-6)}`),\n );\n}\n\nfunction resolveMessageReference(\n state: DiscordServerState,\n channelId: string,\n value: unknown,\n): DiscordMessage[\"message_reference\"] | undefined {\n if (!isJsonObject(value)) {\n return undefined;\n }\n const messageId = readTrimmedString(value.message_id);\n if (!messageId) {\n return undefined;\n }\n const referencedChannelId = readTrimmedString(value.channel_id) ?? channelId;\n const channel = state.channels.get(referencedChannelId);\n return {\n channel_id: referencedChannelId,\n ...(channel?.guild_id ? { guild_id: channel.guild_id } : {}),\n message_id: messageId,\n };\n}\n\nfunction findMessage(\n state: DiscordServerState,\n channelId: string,\n messageId: string,\n): DiscordMessage | undefined {\n return state.messages.get(channelId)?.find((message) => message.id === messageId);\n}\n\nfunction createMessage(params: {\n author: DiscordUser;\n body: Record<string, unknown>;\n channel: DiscordChannel;\n state: DiscordServerState;\n}): DiscordMessage {\n const content = typeof params.body.content === \"string\" ? params.body.content : \"\";\n const embeds = Array.isArray(params.body.embeds) ? params.body.embeds : [];\n const components = Array.isArray(params.body.components) ? params.body.components : [];\n const attachments = Array.isArray(params.body.attachments) ? params.body.attachments : [];\n if (!content && embeds.length === 0 && components.length === 0 && attachments.length === 0) {\n throw new DiscordRequestError(400, 50_006, \"Cannot send an empty message\");\n }\n if (content.length > 2_000) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n const reference = resolveMessageReference(\n params.state,\n params.channel.id,\n params.body.message_reference,\n );\n const referencedMessage = reference\n ? (findMessage(params.state, reference.channel_id, reference.message_id) ?? null)\n : undefined;\n const failIfNotExists = isJsonObject(params.body.message_reference)\n ? params.body.message_reference.fail_if_not_exists\n : undefined;\n if (reference && referencedMessage === null && failIfNotExists !== false) {\n throw new DiscordRequestError(404, 10_008, \"Unknown Message\");\n }\n const message: DiscordMessage = {\n ...(params.body.allowed_mentions !== undefined\n ? { allowed_mentions: params.body.allowed_mentions }\n : {}),\n attachments,\n author: params.author,\n channel_id: params.channel.id,\n components,\n content,\n edited_timestamp: null,\n embeds,\n flags: typeof params.body.flags === \"number\" ? params.body.flags : 0,\n ...(params.channel.guild_id ? { guild_id: params.channel.guild_id } : {}),\n id: discordSnowflake(params.state.nextSequence),\n mention_everyone: /@(everyone|here)\\b/u.test(content),\n mention_roles: [...content.matchAll(/<@&(\\d{17,20})>/gu)].map((match) => match[1]!),\n mentions: parseMentions(content, params.state),\n ...(reference\n ? {\n message_reference: reference,\n ...(referencedMessage !== undefined ? { referenced_message: referencedMessage } : {}),\n }\n : {}),\n ...(typeof params.body.nonce === \"string\" || typeof params.body.nonce === \"number\"\n ? { nonce: params.body.nonce }\n : {}),\n pinned: false,\n timestamp: new Date().toISOString(),\n tts: params.body.tts === true,\n type: reference ? 19 : 0,\n };\n params.state.messages.set(params.channel.id, [\n ...(params.state.messages.get(params.channel.id) ?? []),\n message,\n ]);\n params.channel.last_message_id = message.id;\n return message;\n}\n\nfunction sendGatewayPayload(socket: WebSocket, payload: unknown): boolean {\n if (socket.readyState !== WebSocket.OPEN) {\n return false;\n }\n socket.send(JSON.stringify(payload));\n return true;\n}\n\nfunction dispatchGatewayEvent(state: DiscordServerState, type: string, data: unknown): void {\n const payload = { d: data, op: 0, s: state.nextSequence++, t: type };\n for (const client of state.gatewayClients) {\n if (client.identified) {\n sendGatewayPayload(client.socket, payload);\n if (client.sessionId) {\n const session = state.sessions.get(client.sessionId);\n if (session) {\n session.lastSequence = payload.s;\n }\n }\n }\n }\n}\n\nfunction recordGatewayEvent(state: DiscordServerState, body: unknown, accepted: boolean): void {\n void state.recorder.recordCommitted({\n accepted,\n at: new Date().toISOString(),\n body,\n method: \"WS\",\n path: \"/gateway\",\n query: {},\n type: \"api\",\n } as DiscordRecorderEvent);\n}\n\nfunction readyPayload(state: DiscordServerState, sessionId: string) {\n return {\n application: { flags: 0, id: state.applicationId },\n guilds: [...state.guilds.values()].map((guild) => ({ id: guild.id, unavailable: true })),\n resume_gateway_url: state.gatewayUrl!,\n session_id: sessionId,\n user: state.botUser,\n v: 10,\n };\n}\n\nfunction attachGatewayServer(params: {\n server: import(\"node:http\").Server;\n state: DiscordServerState;\n}) {\n const gatewayServer = new WebSocketServer({\n maxPayload: params.state.maxGatewayPayloadBytes,\n noServer: true,\n });\n const onUpgrade = (request: IncomingMessage, socket: Duplex, head: Buffer) => {\n const url = new URL(request.url ?? \"/\", \"http://127.0.0.1\");\n if (url.pathname !== \"/gateway\") {\n socket.destroy();\n return;\n }\n if ((url.searchParams.get(\"v\") ?? \"10\") !== \"10\") {\n socket.destroy();\n return;\n }\n const encoding = url.searchParams.get(\"encoding\") ?? \"json\";\n if (encoding !== \"json\") {\n socket.destroy();\n return;\n }\n gatewayServer.handleUpgrade(request, socket, head, (client) => {\n gatewayServer.emit(\"connection\", client, request);\n });\n };\n params.server.on(\"upgrade\", onUpgrade);\n\n gatewayServer.on(\"connection\", (socket) => {\n const client: GatewayClient = { identified: false, socket };\n params.state.gatewayClients.add(client);\n sendGatewayPayload(socket, {\n d: { heartbeat_interval: params.state.heartbeatIntervalMs },\n op: 10,\n });\n const identifyTimeout = setTimeout(() => {\n if (!client.identified) {\n socket.close(4_003, \"Not authenticated\");\n }\n }, params.state.identifyTimeoutMs);\n identifyTimeout.unref();\n\n socket.on(\"message\", (raw: RawData) => {\n if (Buffer.byteLength(raw.toString()) > params.state.maxGatewayPayloadBytes) {\n socket.close(4_002, \"Decode error\");\n return;\n }\n let payload: unknown;\n try {\n payload = JSON.parse(raw.toString()) as unknown;\n } catch {\n socket.close(4_002, \"Decode error\");\n return;\n }\n if (!isJsonObject(payload) || typeof payload.op !== \"number\") {\n socket.close(4_002, \"Decode error\");\n return;\n }\n recordGatewayEvent(params.state, payload, true);\n if (payload.op === 1) {\n sendGatewayPayload(socket, { d: null, op: 11 });\n return;\n }\n if (payload.op === 2) {\n if (client.identified || !isJsonObject(payload.d)) {\n socket.close(4_005, \"Already authenticated\");\n return;\n }\n const token = readTrimmedString(payload.d.token);\n if (!token || !constantTimeTokenEqual(token, params.state.botToken)) {\n socket.close(4_004, \"Authentication failed\");\n return;\n }\n clearTimeout(identifyTimeout);\n client.identified = true;\n client.sessionId = randomUUID();\n params.state.sessions.set(client.sessionId, { lastSequence: params.state.nextSequence });\n if (params.state.sessions.size > 128) {\n const oldestSessionId = params.state.sessions.keys().next().value as string | undefined;\n if (oldestSessionId) {\n params.state.sessions.delete(oldestSessionId);\n }\n }\n sendGatewayPayload(socket, {\n d: readyPayload(params.state, client.sessionId),\n op: 0,\n s: params.state.nextSequence++,\n t: \"READY\",\n });\n for (const guild of params.state.guilds.values()) {\n dispatchGatewayEvent(params.state, \"GUILD_CREATE\", guild);\n }\n return;\n }\n if (payload.op === 6) {\n if (!isJsonObject(payload.d)) {\n sendGatewayPayload(socket, { d: false, op: 9 });\n return;\n }\n const token = readTrimmedString(payload.d.token);\n const sessionId = readTrimmedString(payload.d.session_id);\n const session = sessionId ? params.state.sessions.get(sessionId) : undefined;\n if (\n !token ||\n !constantTimeTokenEqual(token, params.state.botToken) ||\n !sessionId ||\n !Number.isSafeInteger(payload.d.seq) ||\n (payload.d.seq as number) < 0 ||\n !session ||\n payload.d.seq !== session.lastSequence\n ) {\n sendGatewayPayload(socket, { d: false, op: 9 });\n return;\n }\n clearTimeout(identifyTimeout);\n client.identified = true;\n client.sessionId = sessionId;\n params.state.sessions.delete(sessionId);\n params.state.sessions.set(sessionId, session);\n const resumedSequence = params.state.nextSequence++;\n session.lastSequence = resumedSequence;\n sendGatewayPayload(socket, {\n d: {},\n op: 0,\n s: resumedSequence,\n t: \"RESUMED\",\n });\n return;\n }\n if (payload.op === 3 || payload.op === 4 || payload.op === 8) {\n return;\n }\n socket.close(4_001, \"Unknown opcode\");\n });\n socket.on(\"error\", () => undefined);\n socket.once(\"close\", () => {\n clearTimeout(identifyTimeout);\n params.state.gatewayClients.delete(client);\n });\n });\n\n return async () => {\n params.server.off(\"upgrade\", onUpgrade);\n await closeWebSocketServer(gatewayServer);\n };\n}\n\nfunction commandBody(\n state: DiscordServerState,\n body: Record<string, unknown>,\n existing?: DiscordCommand,\n guildId?: string,\n): DiscordCommand {\n const name = readTrimmedString(body.name ?? existing?.name);\n if (!name || name.length > 32 || !/^[\\w-]+$/u.test(name)) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n return {\n ...existing,\n ...body,\n application_id: state.applicationId,\n description: readTrimmedString(body.description ?? existing?.description) ?? \"\",\n ...(guildId ? { guild_id: guildId } : {}),\n id: existing?.id ?? discordSnowflake(state.nextSequence++),\n name,\n type: typeof body.type === \"number\" ? body.type : (existing?.type ?? 1),\n version: discordSnowflake(state.nextSequence++),\n };\n}\n\nasync function handleAdminInbound(params: {\n body: Record<string, unknown>;\n state: DiscordServerState;\n}): Promise<Response> {\n const requestedChannelId = requireSnowflake(params.body.channelId, \"channelId\");\n const guildId =\n params.body.guildId === undefined\n ? undefined\n : requireSnowflake(params.body.guildId, \"guildId\");\n const senderId = requireSnowflake(params.body.senderId, \"senderId\");\n const parentChannelId =\n params.body.parentChannelId === undefined\n ? undefined\n : requireSnowflake(params.body.parentChannelId, \"parentChannelId\");\n if (parentChannelId && !guildId) {\n throw new DiscordRequestError(400, 50_035, \"Threads require guildId.\");\n }\n const sender = discordUser(\n senderId,\n readTrimmedString(params.body.senderName) ?? `user-${senderId.slice(-6)}`,\n );\n const hadChannel = params.state.channels.has(requestedChannelId);\n const hadGuild = guildId ? params.state.guilds.has(guildId) : true;\n const channel = ensureChannel({\n channelId: requestedChannelId,\n ...(guildId ? { guildId } : {}),\n ...(parentChannelId ? { parentId: parentChannelId } : {}),\n sender,\n state: params.state,\n });\n const message = createMessage({\n author: sender,\n body: params.body,\n channel,\n state: params.state,\n });\n if (guildId) {\n const guild = params.state.guilds.get(guildId)!;\n const members = Array.isArray(guild.members) ? guild.members : [];\n if (\n !members.some(\n (member) =>\n isJsonObject(member) && isJsonObject(member.user) && member.user.id === sender.id,\n )\n ) {\n members.push({\n deaf: false,\n joined_at: new Date().toISOString(),\n mute: false,\n pending: false,\n roles: [],\n user: sender,\n });\n guild.members = members;\n guild.member_count = members.length;\n }\n (message as DiscordMessage & { member: Record<string, unknown> }).member = {\n deaf: false,\n joined_at: new Date().toISOString(),\n mute: false,\n pending: false,\n roles: [],\n };\n }\n if (!hadGuild && guildId) {\n dispatchGatewayEvent(params.state, \"GUILD_CREATE\", params.state.guilds.get(guildId));\n }\n if (!hadChannel) {\n dispatchGatewayEvent(params.state, \"CHANNEL_CREATE\", channel);\n }\n dispatchGatewayEvent(params.state, \"MESSAGE_CREATE\", message);\n return discordJson({ event: { d: message, op: 0, t: \"MESSAGE_CREATE\" }, message });\n}\n\nasync function handleDiscordApi(params: {\n body: unknown;\n method: string;\n pathname: string;\n state: DiscordServerState;\n}): Promise<Response> {\n const pathParts = params.pathname.split(\"/\").filter(Boolean);\n if (pathParts[0] !== \"api\" || pathParts[1] !== \"v10\") {\n return discordError(404, 0, \"404: Not Found\");\n }\n const route = pathParts.slice(2);\n if (params.method === \"GET\" && route.join(\"/\") === \"users/@me\") {\n return discordJson(params.state.botUser);\n }\n if (params.method === \"GET\" && route.join(\"/\") === \"oauth2/applications/@me\") {\n return discordJson({\n bot: params.state.botUser,\n flags: 0,\n id: params.state.applicationId,\n name: \"Crabline Discord Application\",\n owner: params.state.botUser,\n verify_key: \"crabline\",\n });\n }\n if (params.method === \"GET\" && route.join(\"/\") === \"gateway\") {\n return discordJson({ url: params.state.gatewayUrl });\n }\n if (params.method === \"GET\" && route.join(\"/\") === \"gateway/bot\") {\n return discordJson({\n session_start_limit: {\n max_concurrency: 1,\n remaining: 1_000,\n reset_after: 0,\n total: 1_000,\n },\n shards: 1,\n url: params.state.gatewayUrl,\n });\n }\n if (route[0] === \"channels\" && route.length >= 2) {\n const channelId = requireSnowflake(route[1], \"channel id\");\n const channel = params.state.channels.get(channelId);\n if (route.length === 2 && params.method === \"GET\") {\n return channel ? discordJson(channel) : discordError(404, 10_003, \"Unknown Channel\");\n }\n if (route[2] === \"typing\" && route.length === 3 && params.method === \"POST\") {\n return channel ? discordEmpty() : discordError(404, 10_003, \"Unknown Channel\");\n }\n if (route[2] === \"messages\") {\n if (!channel) {\n return discordError(404, 10_003, \"Unknown Channel\");\n }\n if (route.length === 3 && params.method === \"POST\") {\n if (!isJsonObject(params.body)) {\n throw new InvalidJsonBodyError(undefined, \"Request body must be a JSON object.\");\n }\n const message = createMessage({\n author: params.state.botUser,\n body: params.body,\n channel,\n state: params.state,\n });\n dispatchGatewayEvent(params.state, \"MESSAGE_CREATE\", message);\n return discordJson(message);\n }\n if (route.length === 3 && params.method === \"GET\") {\n return discordJson(\n [...(params.state.messages.get(channelId) ?? [])].reverse().slice(0, 50),\n );\n }\n const messageId = route[3] ? requireSnowflake(route[3], \"message id\") : undefined;\n if (\n messageId &&\n route[4] === \"reactions\" &&\n route[5] &&\n route[6] === \"@me\" &&\n (params.method === \"PUT\" || params.method === \"DELETE\")\n ) {\n return findMessage(params.state, channelId, messageId)\n ? discordEmpty()\n : discordError(404, 10_008, \"Unknown Message\");\n }\n if (messageId && params.method === \"GET\") {\n const message = findMessage(params.state, channelId, messageId);\n return message ? discordJson(message) : discordError(404, 10_008, \"Unknown Message\");\n }\n }\n }\n if (params.method === \"POST\" && route.join(\"/\") === \"users/@me/channels\") {\n if (!isJsonObject(params.body)) {\n throw new InvalidJsonBodyError(undefined, \"Request body must be a JSON object.\");\n }\n const recipientId = requireSnowflake(params.body.recipient_id, \"recipient_id\");\n const recipient = discordUser(recipientId, `user-${recipientId.slice(-6)}`);\n const channelId = discordDirectChannelId(params.state.botUser.id, recipientId);\n return discordJson(ensureChannel({ channelId, sender: recipient, state: params.state }));\n }\n if (route[0] === \"guilds\" && route[1]) {\n const guildId = requireSnowflake(route[1], \"guild id\");\n const guild = params.state.guilds.get(guildId);\n if (!guild) {\n return discordError(404, 10_004, \"Unknown Guild\");\n }\n if (route.length === 2 && params.method === \"GET\") {\n return discordJson(guild);\n }\n if (route[2] === \"channels\" && params.method === \"GET\") {\n return discordJson(\n [...params.state.channels.values()].filter((channel) => channel.guild_id === guildId),\n );\n }\n if (route[2] === \"roles\" && params.method === \"GET\") {\n return discordJson(guild.roles ?? []);\n }\n if (route[2] === \"members\" && route[3] && params.method === \"GET\") {\n const userId = requireSnowflake(route[3], \"user id\");\n const user =\n userId === params.state.botUser.id\n ? params.state.botUser\n : discordUser(userId, `user-${userId.slice(-6)}`);\n return discordJson({\n deaf: false,\n joined_at: new Date().toISOString(),\n mute: false,\n pending: false,\n roles: [],\n user,\n });\n }\n }\n if (route[0] === \"applications\" && route[1] === params.state.applicationId) {\n let commandOffset = 2;\n let guildId: string | undefined;\n if (route[2] === \"guilds\" && route[3] && route[4] === \"commands\") {\n guildId = requireSnowflake(route[3], \"guild id\");\n commandOffset = 4;\n }\n if (route[commandOffset] === \"commands\") {\n const commands = guildId\n ? (params.state.guildCommands.get(guildId) ?? new Map<string, DiscordCommand>())\n : params.state.commands;\n if (guildId && !params.state.guildCommands.has(guildId)) {\n params.state.guildCommands.set(guildId, commands);\n }\n const commandId = route[commandOffset + 1];\n if (!commandId && params.method === \"GET\") {\n return discordJson([...commands.values()]);\n }\n if (!commandId && params.method === \"PUT\") {\n if (!Array.isArray(params.body) || params.body.some((entry) => !isJsonObject(entry))) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n commands.clear();\n for (const body of params.body as Record<string, unknown>[]) {\n const command = commandBody(params.state, body, undefined, guildId);\n commands.set(command.id, command);\n }\n return discordJson([...commands.values()]);\n }\n if (!commandId && params.method === \"POST\") {\n if (!isJsonObject(params.body)) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n const name = readTrimmedString(params.body.name);\n const type = typeof params.body.type === \"number\" ? params.body.type : 1;\n const existing = [...commands.values()].find(\n (command) => command.name === name && command.type === type,\n );\n const command = commandBody(params.state, params.body, existing, guildId);\n commands.set(command.id, command);\n return discordJson(command, existing ? 200 : 201);\n }\n if (commandId) {\n const existing = commands.get(commandId);\n if (!existing) {\n return discordError(404, 10_063, \"Unknown application command\");\n }\n if (params.method === \"PATCH\") {\n if (!isJsonObject(params.body)) {\n throw new DiscordRequestError(400, 50_035, \"Invalid Form Body\");\n }\n const command = commandBody(params.state, params.body, existing, guildId);\n commands.set(commandId, command);\n return discordJson(command);\n }\n if (params.method === \"DELETE\") {\n commands.delete(commandId);\n return discordEmpty();\n }\n }\n }\n }\n return discordError(404, 0, \"404: Not Found\");\n}\n\nasync function handleRequest(params: {\n request: IncomingMessage;\n state: DiscordServerState;\n}): Promise<Response> {\n const url = new URL(params.request.url ?? \"/\", \"http://127.0.0.1\");\n const method = params.request.method ?? \"GET\";\n if (url.pathname === \"/crabline/discord/inbound\") {\n if (method !== \"POST\") {\n return new Response(\"not found\", { status: 404 });\n }\n if (!hasAdminToken(params.request, params.state.adminToken)) {\n params.request.resume();\n return adminAuthError();\n }\n const body = await parseUnknownRequestBody(params.request);\n if (!isJsonObject(body)) {\n throw new InvalidJsonBodyError(undefined, \"Request body must be a JSON object.\");\n }\n const event: DiscordRecorderEvent = {\n at: new Date().toISOString(),\n body,\n method,\n path: url.pathname,\n query: queryRecord(url),\n type: \"admin\",\n };\n const response = await handleAdminInbound({ body, state: params.state });\n event.accepted = response.ok;\n await params.state.recorder.recordCommitted(event);\n return response;\n }\n const authError =\n method === \"GET\" && url.pathname === \"/api/v10/gateway\"\n ? null\n : authorizationError(params.request, params.state);\n if (authError) {\n params.request.resume();\n return authError;\n }\n const body =\n method === \"GET\" || method === \"DELETE\" ? {} : await parseUnknownRequestBody(params.request);\n const event: DiscordRecorderEvent = {\n at: new Date().toISOString(),\n ...(isJsonObject(body) && Object.keys(body).length > 0 ? { body } : {}),\n method,\n path: url.pathname,\n query: queryRecord(url),\n type: \"api\",\n };\n const response = await handleDiscordApi({\n body,\n method,\n pathname: url.pathname,\n state: params.state,\n });\n event.accepted = response.ok;\n await (response.ok\n ? params.state.recorder.recordCommitted(event)\n : params.state.recorder.record(event));\n return response;\n}\n\nexport async function startDiscordServer(\n params: StartDiscordServerParams = {},\n): Promise<StartedDiscordServer> {\n const host = params.host ?? \"127.0.0.1\";\n const applicationId = params.applicationId ?? \"135000000000000001\";\n const botUserId = params.botUserId ?? applicationId;\n requireSnowflake(applicationId, \"applicationId\");\n requireSnowflake(botUserId, \"botUserId\");\n const encodedApplicationId = Buffer.from(applicationId, \"utf8\").toString(\"base64url\");\n const externallyBound = !isLoopbackHost(host);\n const recorderPath = params.recorderPath ?? path.resolve(\".crabline\", \"servers\", \"discord.jsonl\");\n const state: DiscordServerState = {\n adminToken: params.adminToken ?? randomBytes(24).toString(\"base64url\"),\n applicationId,\n botToken:\n params.botToken ??\n (externallyBound\n ? `${encodedApplicationId}.${randomBytes(6).toString(\"base64url\")}.${randomBytes(24).toString(\"base64url\")}`\n : `${encodedApplicationId}.crabline.discord`),\n botUser: discordUser(botUserId, params.botUsername ?? \"crabline\", true),\n channels: new Map(),\n commands: new Map(),\n gatewayClients: new Set(),\n guildCommands: new Map(),\n guilds: new Map(),\n heartbeatIntervalMs: positiveInteger(\n params.heartbeatIntervalMs,\n DEFAULT_HEARTBEAT_INTERVAL_MS,\n \"heartbeatIntervalMs\",\n ),\n identifyTimeoutMs: positiveInteger(\n params.identifyTimeoutMs,\n DEFAULT_IDENTIFY_TIMEOUT_MS,\n \"identifyTimeoutMs\",\n ),\n maxGatewayPayloadBytes: positiveInteger(\n params.maxGatewayPayloadBytes,\n DEFAULT_MAX_GATEWAY_PAYLOAD_BYTES,\n \"maxGatewayPayloadBytes\",\n ),\n messages: new Map(),\n nextSequence: 1,\n recorder: createServerRecorder({ recorderPath, onEvent: params.onEvent }),\n recorderPath,\n sessions: new Map(),\n };\n const httpServer = await startHttpJsonServer({\n handle: (request) => handleRequest({ request, state }),\n handleError: (error) => {\n if (error instanceof DiscordRequestError) {\n return discordError(error.status, error.code, error.message);\n }\n if (error instanceof InvalidJsonBodyError) {\n return discordError(400, 50_035, \"Invalid Form Body\");\n }\n if (error instanceof RequestBodyTooLargeError) {\n return discordError(413, 40_005, \"Request entity too large\");\n }\n return undefined;\n },\n host,\n port: params.port ?? 0,\n serverName: \"Discord\",\n });\n state.gatewayUrl = `${httpServer.baseUrl.replace(/^http/u, \"ws\")}/gateway`;\n const closeGateway = attachGatewayServer({ server: httpServer.server, state });\n return {\n close: createServerClose(\n state.recorder,\n async () => {\n try {\n await closeGateway();\n } finally {\n state.sessions.clear();\n }\n },\n () => httpServer.close(),\n ),\n manifest: {\n adminToken: state.adminToken,\n applicationId: state.applicationId,\n baseUrl: httpServer.baseUrl,\n botToken: state.botToken,\n botUserId: state.botUser.id,\n endpoints: {\n adminInboundUrl: `${httpServer.baseUrl}/crabline/discord/inbound`,\n apiRoot: `${httpServer.baseUrl}/api`,\n gatewayBotUrl: `${httpServer.baseUrl}/api/v10/gateway/bot`,\n gatewayUrl: state.gatewayUrl,\n },\n env: { DISCORD_BOT_TOKEN: state.botToken },\n provider: \"discord\",\n recorderPath: state.recorderPath,\n version: 1,\n },\n };\n}\n"]}
@@ -42,6 +42,9 @@ export declare function advertisedHostForBindAddress(host: string, boundAddress:
42
42
  export declare function assertLoopbackBindAddress(configuredHost: string, boundAddress: string, serverName: string): void;
43
43
  export declare function writeFetchResponseHeaders(response: ServerResponse, fetchResponse: Response): void;
44
44
  export declare function writeResponse(response: ServerResponse, fetchResponse: Response, maxBytes?: number): Promise<void>;
45
+ export declare function createServerClose(recorder: {
46
+ close(): Promise<void>;
47
+ }, ...closeResources: Array<() => void | Promise<void>>): () => Promise<void>;
45
48
  export declare function closeServer(server: Server, graceMs?: number): Promise<void>;
46
49
  export declare function startHttpJsonServer(params: {
47
50
  handle: (request: IncomingMessage, response: ServerResponse) => Promise<HttpJsonHandlerResult>;
@@ -341,6 +341,21 @@ export async function writeResponse(response, fetchResponse, maxBytes = DEFAULT_
341
341
  response.req?.off("aborted", onRequestAborted);
342
342
  }
343
343
  }
344
+ export function createServerClose(recorder, ...closeResources) {
345
+ let closing;
346
+ return () => (closing ??= (async () => {
347
+ const results = await Promise.allSettled(closeResources.map(async (close) => await close()));
348
+ // Let native polling responses finish during transport grace, then fence late writes.
349
+ results.push(...(await Promise.allSettled([recorder.close()])));
350
+ const errors = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
351
+ if (errors.length === 1) {
352
+ throw errors[0];
353
+ }
354
+ if (errors.length > 1) {
355
+ throw new AggregateError(errors, "Server shutdown failed.");
356
+ }
357
+ })());
358
+ }
344
359
  export function closeServer(server, graceMs = DEFAULT_SERVER_SHUTDOWN_GRACE_MS) {
345
360
  return new Promise((resolve, reject) => {
346
361
  const closeIdleInterval = setInterval(() => server.closeIdleConnections(), 25);