lunibee 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/builders/commands.d.ts +1 -1
- package/dist/builders/components.d.ts +9 -11
- package/dist/builders/embed.d.ts +1 -1
- package/dist/builders/index.d.ts +1 -1
- package/dist/builders/index.js +87 -1298
- package/dist/builders/index.js.map +3 -11
- package/dist/chunks/index-0wn81eng.js +2492 -0
- package/dist/chunks/index-0wn81eng.js.map +17 -0
- package/dist/chunks/index-2en489j6.js +40 -0
- package/dist/chunks/index-2en489j6.js.map +10 -0
- package/dist/chunks/index-3hyps48a.js +203 -0
- package/dist/chunks/index-3hyps48a.js.map +11 -0
- package/dist/chunks/index-57c5n3ms.js +2274 -0
- package/dist/chunks/index-57c5n3ms.js.map +19 -0
- package/dist/chunks/index-5yx92e36.js +1170 -0
- package/dist/chunks/index-5yx92e36.js.map +14 -0
- package/dist/chunks/index-690bp093.js +95 -0
- package/dist/chunks/index-690bp093.js.map +10 -0
- package/dist/chunks/index-7fp2hvmg.js +2155 -0
- package/dist/chunks/index-7fp2hvmg.js.map +24 -0
- package/dist/chunks/index-cnmsajvk.js +1119 -0
- package/dist/chunks/index-cnmsajvk.js.map +12 -0
- package/dist/chunks/index-fdvgk2sw.js +1310 -0
- package/dist/chunks/index-fdvgk2sw.js.map +21 -0
- package/dist/chunks/index-gyvps8b9.js +214 -0
- package/dist/chunks/index-gyvps8b9.js.map +12 -0
- package/dist/chunks/index-jzg4bh99.js +1533 -0
- package/dist/chunks/index-jzg4bh99.js.map +21 -0
- package/dist/chunks/index-mgw2yvrm.js +3547 -0
- package/dist/chunks/index-mgw2yvrm.js.map +25 -0
- package/dist/chunks/index-yh76b55h.js +3449 -0
- package/dist/chunks/index-yh76b55h.js.map +29 -0
- package/dist/collection/index.js +9 -1118
- package/dist/collection/index.js.map +3 -6
- package/dist/core/api.d.ts +3 -3
- package/dist/core/channel-create.d.ts +2 -2
- package/dist/core/commands.d.ts +3 -3
- package/dist/core/events.d.ts +4 -4
- package/dist/core/handles.d.ts +4 -4
- package/dist/core/index.d.ts +25 -20
- package/dist/core/index.js +68 -10130
- package/dist/core/index.js.map +3 -65
- package/dist/core/permissions.d.ts +1 -1
- package/dist/core/redis-cache.d.ts +1 -1
- package/dist/formatters/index.js +41 -110
- package/dist/formatters/index.js.map +3 -4
- package/dist/handlers/index.js +5 -37
- package/dist/handlers/index.js.map +3 -4
- package/dist/index.d.ts +21 -21
- package/dist/index.js +641 -16325
- package/dist/index.js.map +3 -92
- package/dist/managers/advanced.d.ts +3 -3
- package/dist/managers/application.d.ts +2 -2
- package/dist/managers/base.d.ts +1 -1
- package/dist/managers/emoji.d.ts +2 -2
- package/dist/managers/guild-resources.d.ts +6 -6
- package/dist/managers/guild.d.ts +3 -3
- package/dist/managers/index.d.ts +4 -8
- package/dist/managers/index.js +51 -4060
- package/dist/managers/index.js.map +3 -29
- package/dist/managers/member.d.ts +2 -2
- package/dist/managers/message.d.ts +14 -6
- package/dist/managers/role.d.ts +2 -2
- package/dist/managers/thread.d.ts +3 -3
- package/dist/managers/user.d.ts +7 -4
- package/dist/rest/index.d.ts +10 -35
- package/dist/rest/index.js +57 -2184
- package/dist/rest/index.js.map +3 -18
- package/dist/rest/limiter.d.ts +9 -1
- package/dist/rest/webhook.d.ts +2 -8
- package/dist/sharding/bus.d.ts +2 -2
- package/dist/sharding/cluster.d.ts +45 -5
- package/dist/sharding/context.d.ts +45 -3
- package/dist/sharding/gateway-bot.d.ts +2 -1
- package/dist/sharding/health.d.ts +1 -1
- package/dist/sharding/identify.d.ts +12 -0
- package/dist/sharding/index.d.ts +44 -11
- package/dist/sharding/index.js +60 -4620
- package/dist/sharding/index.js.map +3 -33
- package/dist/sharding/supervisor.d.ts +4 -2
- package/dist/structures/audit-log.d.ts +1 -1
- package/dist/structures/base.d.ts +6 -6
- package/dist/structures/channels.d.ts +1 -1
- package/dist/structures/embed.d.ts +1 -1
- package/dist/structures/index.d.ts +14 -14
- package/dist/structures/index.js +109 -2382
- package/dist/structures/index.js.map +3 -16
- package/dist/structures/interactions.d.ts +13 -9
- package/dist/structures/options.d.ts +1 -1
- package/dist/structures/permissions.d.ts +2 -2
- package/dist/structures/resources.d.ts +10 -10
- package/dist/structures/sticker.d.ts +1 -1
- package/dist/types/gateway.d.ts +2 -79
- package/dist/types/index.d.ts +0 -6
- package/dist/types/index.js +41 -272
- package/dist/types/index.js.map +3 -6
- package/dist/utils/index.js +23 -209
- package/dist/utils/index.js.map +3 -5
- package/dist/voice/connection.d.ts +200 -0
- package/dist/voice/crypto.d.ts +50 -0
- package/dist/voice/dave.d.ts +85 -0
- package/dist/voice/effects.d.ts +31 -0
- package/dist/voice/emitter.d.ts +14 -0
- package/dist/voice/gateway.d.ts +59 -0
- package/dist/voice/index.d.ts +25 -228
- package/dist/voice/index.js +111 -442
- package/dist/voice/index.js.map +3 -4
- package/dist/voice/libopus.d.ts +88 -0
- package/dist/voice/networking.d.ts +80 -0
- package/dist/voice/ogg.d.ts +24 -0
- package/dist/voice/opus.d.ts +18 -0
- package/dist/voice/player.d.ts +79 -0
- package/dist/voice/protocol.d.ts +76 -0
- package/dist/voice/receiver.d.ts +59 -0
- package/dist/voice/resource.d.ts +102 -0
- package/dist/voice/udp.d.ts +40 -0
- package/dist/ws/close-codes.d.ts +1 -1
- package/dist/ws/index.d.ts +25 -4
- package/dist/ws/index.js +47 -1336
- package/dist/ws/index.js.map +3 -17
- package/dist/ws/protocol.d.ts +1 -1
- package/dist/ws/send-budget.d.ts +0 -2
- package/dist/ws/state.d.ts +0 -10
- package/package.json +19 -16
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../packages/voice/src/crypto.ts", "../node_modules/.bun/@noble+ciphers@1.3.0/node_modules/@noble/ciphers/esm/utils.js", "../node_modules/.bun/@noble+ciphers@1.3.0/node_modules/@noble/ciphers/esm/_arx.js", "../node_modules/.bun/@noble+ciphers@1.3.0/node_modules/@noble/ciphers/esm/_poly1305.js", "../node_modules/.bun/@noble+ciphers@1.3.0/node_modules/@noble/ciphers/esm/chacha.js", "../packages/voice/src/protocol.ts", "../packages/voice/src/dave.ts", "../packages/voice/src/gateway.ts", "../packages/voice/src/udp.ts", "../packages/voice/src/networking.ts", "../packages/voice/src/emitter.ts", "../packages/voice/src/ogg.ts", "../packages/voice/src/receiver.ts", "../packages/voice/src/connection.ts", "../packages/voice/src/libopus.ts", "../packages/voice/src/opus.ts", "../packages/voice/src/effects.ts", "../packages/voice/src/resource.ts", "../packages/voice/src/player.ts", "../packages/voice/src/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { createCipheriv, createDecipheriv, getCiphers } from \"node:crypto\";\nimport { xchacha20poly1305 } from \"@noble/ciphers/chacha.js\";\nimport { RTP_OPUS_PAYLOAD_TYPE, VoiceError } from \"./protocol.js\";\n\n/** Transport encryption modes this package implements. */\nexport type VoiceEncryptionMode =\n \"aead_aes256_gcm_rtpsize\" | \"aead_xchacha20_poly1305_rtpsize\";\n\nconst TAG_BYTES = 16;\nconst NONCE_SUFFIX_BYTES = 4;\n\n/** Modes in order of preference: AES-GCM when the runtime has it, XChaCha20-Poly1305 always. */\nexport const SUPPORTED_ENCRYPTION_MODES: readonly VoiceEncryptionMode[] =\n getCiphers().includes(\"aes-256-gcm\")\n ? [\"aead_aes256_gcm_rtpsize\", \"aead_xchacha20_poly1305_rtpsize\"]\n : [\"aead_xchacha20_poly1305_rtpsize\"];\n\n/** Picks the first mode in our preference order that the voice server offers. @throws {VoiceError} If none is offered. */\nexport function chooseEncryptionMode(\n offered: readonly string[],\n): VoiceEncryptionMode {\n const mode = SUPPORTED_ENCRYPTION_MODES.find((m) => offered.includes(m));\n if (!mode)\n throw new VoiceError(\n `No supported voice encryption mode offered (got: ${offered.join(\", \") || \"none\"}).`,\n );\n return mode;\n}\n\n/** A parsed RTP packet header. */\nexport interface RtpHeader {\n version: number;\n padding: boolean;\n extension: boolean;\n payloadType: number;\n sequence: number;\n timestamp: number;\n ssrc: number;\n /** Bytes authenticated but not encrypted: the fixed header, CSRCs and the extension header. */\n headerSize: number;\n /** 32-bit words of extension data, encrypted with the payload. */\n extensionWords: number;\n}\n\n/** Writes the 12-byte RTP header Discord expects for an outgoing Opus packet. */\nexport function rtpHeader(\n sequence: number,\n timestamp: number,\n ssrc: number,\n): Uint8Array {\n const header = new Uint8Array(12);\n const view = new DataView(header.buffer);\n header[0] = 0x80;\n header[1] = RTP_OPUS_PAYLOAD_TYPE;\n view.setUint16(2, sequence & 0xffff);\n view.setUint32(4, timestamp >>> 0);\n view.setUint32(8, ssrc >>> 0);\n return header;\n}\n\n/** Parses an RTP header, or returns `undefined` for anything that is not a complete RTP v2 header. */\nexport function parseRtpHeader(packet: Uint8Array): RtpHeader | undefined {\n if (packet.length < 12) return undefined;\n const view = new DataView(\n packet.buffer,\n packet.byteOffset,\n packet.byteLength,\n );\n const first = packet[0]!;\n const version = first >> 6;\n if (version !== 2) return undefined;\n const extension = (first & 0x10) !== 0;\n let headerSize = 12 + (first & 0x0f) * 4;\n let extensionWords = 0;\n if (extension) {\n if (packet.length < headerSize + 4) return undefined;\n extensionWords = view.getUint16(headerSize + 2);\n headerSize += 4;\n }\n if (packet.length < headerSize) return undefined;\n return {\n version,\n padding: (first & 0x20) !== 0,\n extension,\n payloadType: packet[1]! & 0x7f,\n sequence: view.getUint16(2),\n timestamp: view.getUint32(4),\n ssrc: view.getUint32(8),\n headerSize,\n extensionWords,\n };\n}\n\n/**\n * Seals and opens RTP packets for one voice session (\"rtpsize\" AEAD modes):\n * the RTP header (and extension header) is authenticated, the rest is\n * encrypted, and a 32-bit nonce counter is appended to the packet. The full\n * nonce is that counter followed by zeros (12 bytes for AES-GCM, 24 for\n * XChaCha20-Poly1305).\n */\nexport class PacketCipher {\n public readonly mode: VoiceEncryptionMode;\n readonly #key: Uint8Array;\n #counter = 0;\n\n /** @param counter First nonce counter (default 0). */\n public constructor(\n mode: VoiceEncryptionMode,\n key: Uint8Array,\n counter = 0,\n ) {\n if (key.length !== 32)\n throw new VoiceError(\"The voice secret key must be 32 bytes.\");\n if (!SUPPORTED_ENCRYPTION_MODES.includes(mode))\n throw new VoiceError(`Unsupported voice encryption mode: ${mode}`);\n this.mode = mode;\n this.#key = Uint8Array.from(key);\n this.#counter = counter >>> 0;\n }\n\n /** The nonce counter of the next sealed packet (wraps at 2^32). */\n public get counter(): number {\n return this.#counter;\n }\n\n #nonce(suffix: Uint8Array): Uint8Array {\n const nonce = new Uint8Array(\n this.mode === \"aead_aes256_gcm_rtpsize\" ? 12 : 24,\n );\n nonce.set(suffix, 0);\n return nonce;\n }\n\n /** Encrypts `payload` under `header`. @returns The datagram: header, ciphertext, tag, nonce suffix. */\n public seal(header: Uint8Array, payload: Uint8Array): Uint8Array {\n const suffix = new Uint8Array(NONCE_SUFFIX_BYTES);\n new DataView(suffix.buffer).setUint32(0, this.#counter);\n this.#counter = (this.#counter + 1) >>> 0;\n const nonce = this.#nonce(suffix);\n let sealed: Uint8Array;\n if (this.mode === \"aead_aes256_gcm_rtpsize\") {\n const cipher = createCipheriv(\"aes-256-gcm\", this.#key, nonce);\n cipher.setAAD(header);\n const body = Buffer.concat([\n cipher.update(payload),\n cipher.final(),\n ]);\n sealed = Buffer.concat([body, cipher.getAuthTag()]);\n } else\n sealed = xchacha20poly1305(this.#key, nonce, header).encrypt(\n payload,\n );\n const out = new Uint8Array(\n header.length + sealed.length + NONCE_SUFFIX_BYTES,\n );\n out.set(header, 0);\n out.set(sealed, header.length);\n out.set(suffix, header.length + sealed.length);\n return out;\n }\n\n /**\n * Decrypts a received datagram. Removes the encrypted extension data and\n * RTP padding. @returns The header and the plaintext payload, or\n * `undefined` when the packet is malformed or fails authentication.\n */\n public open(\n packet: Uint8Array,\n ): { header: RtpHeader; payload: Uint8Array } | undefined {\n const header = parseRtpHeader(packet);\n if (!header) return undefined;\n const bodyEnd = packet.length - NONCE_SUFFIX_BYTES;\n const tagStart = bodyEnd - TAG_BYTES;\n if (tagStart < header.headerSize) return undefined;\n const aad = packet.subarray(0, header.headerSize);\n const nonce = this.#nonce(packet.subarray(bodyEnd));\n let plain: Uint8Array;\n try {\n if (this.mode === \"aead_aes256_gcm_rtpsize\") {\n const decipher = createDecipheriv(\n \"aes-256-gcm\",\n this.#key,\n nonce,\n );\n decipher.setAAD(aad);\n decipher.setAuthTag(packet.subarray(tagStart, bodyEnd));\n plain = Buffer.concat([\n decipher.update(\n packet.subarray(header.headerSize, tagStart),\n ),\n decipher.final(),\n ]);\n } else\n plain = xchacha20poly1305(this.#key, nonce, aad).decrypt(\n packet.subarray(header.headerSize, bodyEnd),\n );\n } catch {\n return undefined;\n }\n if (header.padding && plain.length > 0) {\n const pad = plain[plain.length - 1]!;\n if (pad > plain.length) return undefined;\n plain = plain.subarray(0, plain.length - pad);\n }\n const skip = header.extensionWords * 4;\n if (skip > plain.length) return undefined;\n return { header, payload: plain.subarray(skip) };\n }\n}\n",
|
|
6
|
+
"/**\n * Utilities for hex, bytes, CSPRNG.\n * @module\n */\n/*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */\n/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */\nexport function isBytes(a) {\n return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n}\n/** Asserts something is boolean. */\nexport function abool(b) {\n if (typeof b !== 'boolean')\n throw new Error(`boolean expected, not ${b}`);\n}\n/** Asserts something is positive integer. */\nexport function anumber(n) {\n if (!Number.isSafeInteger(n) || n < 0)\n throw new Error('positive integer expected, got ' + n);\n}\n/** Asserts something is Uint8Array. */\nexport function abytes(b, ...lengths) {\n if (!isBytes(b))\n throw new Error('Uint8Array expected');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);\n}\n/**\n * Asserts something is hash\n * TODO: remove\n * @deprecated\n */\nexport function ahash(h) {\n if (typeof h !== 'function' || typeof h.create !== 'function')\n throw new Error('Hash should be wrapped by utils.createHasher');\n anumber(h.outputLen);\n anumber(h.blockLen);\n}\n/** Asserts a hash instance has not been destroyed / finished */\nexport function aexists(instance, checkFinished = true) {\n if (instance.destroyed)\n throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished)\n throw new Error('Hash#digest() has already been called');\n}\n/** Asserts output is properly-sized byte array */\nexport function aoutput(out, instance) {\n abytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error('digestInto() expects output buffer of length at least ' + min);\n }\n}\n/** Cast u8 / u16 / u32 to u8. */\nexport function u8(arr) {\n return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/** Cast u8 / u16 / u32 to u32. */\nexport function u32(arr) {\n return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n}\n/** Zeroize a byte array. Warning: JS provides no guarantees. */\nexport function clean(...arrays) {\n for (let i = 0; i < arrays.length; i++) {\n arrays[i].fill(0);\n }\n}\n/** Create DataView of an array for easy byte-level manipulation. */\nexport function createView(arr) {\n return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/** Is current platform little-endian? Most are. Big-Endian platform: IBM */\nexport const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();\n// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex\nconst hasHexBuiltin = /* @__PURE__ */ (() => \n// @ts-ignore\ntypeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\n/**\n * Convert byte array to hex string. Uses built-in function, when available.\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes) {\n abytes(bytes);\n // @ts-ignore\n if (hasHexBuiltin)\n return bytes.toHex();\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };\nfunction asciiToBase16(ch) {\n if (ch >= asciis._0 && ch <= asciis._9)\n return ch - asciis._0; // '2' => 50-48\n if (ch >= asciis.A && ch <= asciis.F)\n return ch - (asciis.A - 10); // 'B' => 66-(65-10)\n if (ch >= asciis.a && ch <= asciis.f)\n return ch - (asciis.a - 10); // 'b' => 98-(97-10)\n return;\n}\n/**\n * Convert hex string to byte array. Uses built-in function, when available.\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n // @ts-ignore\n if (hasHexBuiltin)\n return Uint8Array.fromHex(hex);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n throw new Error('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163\n }\n return array;\n}\n// Used in micro\nexport function hexToNumber(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n return BigInt(hex === '' ? '0' : '0x' + hex); // Big Endian\n}\n// Used in ff1\n// BE: Big Endian, LE: Little Endian\nexport function bytesToNumberBE(bytes) {\n return hexToNumber(bytesToHex(bytes));\n}\n// Used in micro, ff1\nexport function numberToBytesBE(n, len) {\n return hexToBytes(n.toString(16).padStart(len * 2, '0'));\n}\n// TODO: remove\n// There is no setImmediate in browser and setTimeout is slow.\n// call of async fn will return Promise, which will be fullfiled only on\n// next scheduler queue processing step and this is exactly what we need.\nexport const nextTick = async () => { };\n/**\n * Converts string to bytes using UTF8 encoding.\n * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new Error('string expected');\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n/**\n * Converts bytes to string using UTF8 encoding.\n * @example bytesToUtf8(new Uint8Array([97, 98, 99])) // 'abc'\n */\nexport function bytesToUtf8(bytes) {\n return new TextDecoder().decode(bytes);\n}\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data) {\n if (typeof data === 'string')\n data = utf8ToBytes(data);\n else if (isBytes(data))\n data = copyBytes(data);\n else\n throw new Error('Uint8Array expected, got ' + typeof data);\n return data;\n}\n/**\n * Checks if two U8A use same underlying buffer and overlaps.\n * This is invalid and can corrupt data.\n */\nexport function overlapBytes(a, b) {\n return (a.buffer === b.buffer && // best we can do, may fail with an obscure Proxy\n a.byteOffset < b.byteOffset + b.byteLength && // a starts before b end\n b.byteOffset < a.byteOffset + a.byteLength // b starts before a end\n );\n}\n/**\n * If input and output overlap and input starts before output, we will overwrite end of input before\n * we start processing it, so this is not supported for most ciphers (except chacha/salse, which designed with this)\n */\nexport function complexOverlapBytes(input, output) {\n // This is very cursed. It works somehow, but I'm completely unsure,\n // reasoning about overlapping aligned windows is very hard.\n if (overlapBytes(input, output) && input.byteOffset < output.byteOffset)\n throw new Error('complex overlap of input and output is not supported');\n}\n/**\n * Copies several Uint8Arrays into one.\n */\nexport function concatBytes(...arrays) {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\nexport function checkOpts(defaults, opts) {\n if (opts == null || typeof opts !== 'object')\n throw new Error('options must be defined');\n const merged = Object.assign(defaults, opts);\n return merged;\n}\n/** Compares 2 uint8array-s in kinda constant time. */\nexport function equalBytes(a, b) {\n if (a.length !== b.length)\n return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++)\n diff |= a[i] ^ b[i];\n return diff === 0;\n}\n// TODO: remove\n/** For runtime check if class implements interface. */\nexport class Hash {\n}\n/**\n * Wraps a cipher: validates args, ensures encrypt() can only be called once.\n * @__NO_SIDE_EFFECTS__\n */\nexport const wrapCipher = (params, constructor) => {\n function wrappedCipher(key, ...args) {\n // Validate key\n abytes(key);\n // Big-Endian hardware is rare. Just in case someone still decides to run ciphers:\n if (!isLE)\n throw new Error('Non little-endian hardware is not yet supported');\n // Validate nonce if nonceLength is present\n if (params.nonceLength !== undefined) {\n const nonce = args[0];\n if (!nonce)\n throw new Error('nonce / iv required');\n if (params.varSizeNonce)\n abytes(nonce);\n else\n abytes(nonce, params.nonceLength);\n }\n // Validate AAD if tagLength present\n const tagl = params.tagLength;\n if (tagl && args[1] !== undefined) {\n abytes(args[1]);\n }\n const cipher = constructor(key, ...args);\n const checkOutput = (fnLength, output) => {\n if (output !== undefined) {\n if (fnLength !== 2)\n throw new Error('cipher output not supported');\n abytes(output);\n }\n };\n // Create wrapped cipher with validation and single-use encryption\n let called = false;\n const wrCipher = {\n encrypt(data, output) {\n if (called)\n throw new Error('cannot encrypt() twice with same key + nonce');\n called = true;\n abytes(data);\n checkOutput(cipher.encrypt.length, output);\n return cipher.encrypt(data, output);\n },\n decrypt(data, output) {\n abytes(data);\n if (tagl && data.length < tagl)\n throw new Error('invalid ciphertext length: smaller than tagLength=' + tagl);\n checkOutput(cipher.decrypt.length, output);\n return cipher.decrypt(data, output);\n },\n };\n return wrCipher;\n }\n Object.assign(wrappedCipher, params);\n return wrappedCipher;\n};\n/**\n * By default, returns u8a of length.\n * When out is available, it checks it for validity and uses it.\n */\nexport function getOutput(expectedLength, out, onlyAligned = true) {\n if (out === undefined)\n return new Uint8Array(expectedLength);\n if (out.length !== expectedLength)\n throw new Error('invalid output length, expected ' + expectedLength + ', got: ' + out.length);\n if (onlyAligned && !isAligned32(out))\n throw new Error('invalid output, must be aligned');\n return out;\n}\n/** Polyfill for Safari 14. */\nexport function setBigUint64(view, byteOffset, value, isLE) {\n if (typeof view.setBigUint64 === 'function')\n return view.setBigUint64(byteOffset, value, isLE);\n const _32n = BigInt(32);\n const _u32_max = BigInt(0xffffffff);\n const wh = Number((value >> _32n) & _u32_max);\n const wl = Number(value & _u32_max);\n const h = isLE ? 4 : 0;\n const l = isLE ? 0 : 4;\n view.setUint32(byteOffset + h, wh, isLE);\n view.setUint32(byteOffset + l, wl, isLE);\n}\nexport function u64Lengths(dataLength, aadLength, isLE) {\n abool(isLE);\n const num = new Uint8Array(16);\n const view = createView(num);\n setBigUint64(view, 0, BigInt(aadLength), isLE);\n setBigUint64(view, 8, BigInt(dataLength), isLE);\n return num;\n}\n// Is byte array aligned to 4 byte offset (u32)?\nexport function isAligned32(bytes) {\n return bytes.byteOffset % 4 === 0;\n}\n// copy bytes to new u8a (aligned). Because Buffer.slice is broken.\nexport function copyBytes(bytes) {\n return Uint8Array.from(bytes);\n}\n//# sourceMappingURL=utils.js.map",
|
|
7
|
+
"/**\n * Basic utils for ARX (add-rotate-xor) salsa and chacha ciphers.\n\nRFC8439 requires multi-step cipher stream, where\nauthKey starts with counter: 0, actual msg with counter: 1.\n\nFor this, we need a way to re-use nonce / counter:\n\n const counter = new Uint8Array(4);\n chacha(..., counter, ...); // counter is now 1\n chacha(..., counter, ...); // counter is now 2\n\nThis is complicated:\n\n- 32-bit counters are enough, no need for 64-bit: max ArrayBuffer size in JS is 4GB\n- Original papers don't allow mutating counters\n- Counter overflow is undefined [^1]\n- Idea A: allow providing (nonce | counter) instead of just nonce, re-use it\n- Caveat: Cannot be re-used through all cases:\n- * chacha has (counter | nonce)\n- * xchacha has (nonce16 | counter | nonce16)\n- Idea B: separate nonce / counter and provide separate API for counter re-use\n- Caveat: there are different counter sizes depending on an algorithm.\n- salsa & chacha also differ in structures of key & sigma:\n salsa20: s[0] | k(4) | s[1] | nonce(2) | ctr(2) | s[2] | k(4) | s[3]\n chacha: s(4) | k(8) | ctr(1) | nonce(3)\n chacha20orig: s(4) | k(8) | ctr(2) | nonce(2)\n- Idea C: helper method such as `setSalsaState(key, nonce, sigma, data)`\n- Caveat: we can't re-use counter array\n\nxchacha [^2] uses the subkey and remaining 8 byte nonce with ChaCha20 as normal\n(prefixed by 4 NUL bytes, since [RFC8439] specifies a 12-byte nonce).\n\n[^1]: https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU/\n[^2]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#appendix-A.2\n\n * @module\n */\n// prettier-ignore\nimport { abool, abytes, anumber, checkOpts, clean, copyBytes, u32 } from \"./utils.js\";\n// We can't make top-level var depend on utils.utf8ToBytes\n// because it's not present in all envs. Creating a similar fn here\nconst _utf8ToBytes = (str) => Uint8Array.from(str.split('').map((c) => c.charCodeAt(0)));\nconst sigma16 = _utf8ToBytes('expand 16-byte k');\nconst sigma32 = _utf8ToBytes('expand 32-byte k');\nconst sigma16_32 = u32(sigma16);\nconst sigma32_32 = u32(sigma32);\nexport function rotl(a, b) {\n return (a << b) | (a >>> (32 - b));\n}\n// Is byte array aligned to 4 byte offset (u32)?\nfunction isAligned32(b) {\n return b.byteOffset % 4 === 0;\n}\n// Salsa and Chacha block length is always 512-bit\nconst BLOCK_LEN = 64;\nconst BLOCK_LEN32 = 16;\n// new Uint32Array([2**32]) // => Uint32Array(1) [ 0 ]\n// new Uint32Array([2**32-1]) // => Uint32Array(1) [ 4294967295 ]\nconst MAX_COUNTER = 2 ** 32 - 1;\nconst U32_EMPTY = new Uint32Array();\nfunction runCipher(core, sigma, key, nonce, data, output, counter, rounds) {\n const len = data.length;\n const block = new Uint8Array(BLOCK_LEN);\n const b32 = u32(block);\n // Make sure that buffers aligned to 4 bytes\n const isAligned = isAligned32(data) && isAligned32(output);\n const d32 = isAligned ? u32(data) : U32_EMPTY;\n const o32 = isAligned ? u32(output) : U32_EMPTY;\n for (let pos = 0; pos < len; counter++) {\n core(sigma, key, nonce, b32, counter, rounds);\n if (counter >= MAX_COUNTER)\n throw new Error('arx: counter overflow');\n const take = Math.min(BLOCK_LEN, len - pos);\n // aligned to 4 bytes\n if (isAligned && take === BLOCK_LEN) {\n const pos32 = pos / 4;\n if (pos % 4 !== 0)\n throw new Error('arx: invalid block position');\n for (let j = 0, posj; j < BLOCK_LEN32; j++) {\n posj = pos32 + j;\n o32[posj] = d32[posj] ^ b32[j];\n }\n pos += BLOCK_LEN;\n continue;\n }\n for (let j = 0, posj; j < take; j++) {\n posj = pos + j;\n output[posj] = data[posj] ^ block[j];\n }\n pos += take;\n }\n}\n/** Creates ARX-like (ChaCha, Salsa) cipher stream from core function. */\nexport function createCipher(core, opts) {\n const { allowShortKeys, extendNonceFn, counterLength, counterRight, rounds } = checkOpts({ allowShortKeys: false, counterLength: 8, counterRight: false, rounds: 20 }, opts);\n if (typeof core !== 'function')\n throw new Error('core must be a function');\n anumber(counterLength);\n anumber(rounds);\n abool(counterRight);\n abool(allowShortKeys);\n return (key, nonce, data, output, counter = 0) => {\n abytes(key);\n abytes(nonce);\n abytes(data);\n const len = data.length;\n if (output === undefined)\n output = new Uint8Array(len);\n abytes(output);\n anumber(counter);\n if (counter < 0 || counter >= MAX_COUNTER)\n throw new Error('arx: counter overflow');\n if (output.length < len)\n throw new Error(`arx: output (${output.length}) is shorter than data (${len})`);\n const toClean = [];\n // Key & sigma\n // key=16 -> sigma16, k=key|key\n // key=32 -> sigma32, k=key\n let l = key.length;\n let k;\n let sigma;\n if (l === 32) {\n toClean.push((k = copyBytes(key)));\n sigma = sigma32_32;\n }\n else if (l === 16 && allowShortKeys) {\n k = new Uint8Array(32);\n k.set(key);\n k.set(key, 16);\n sigma = sigma16_32;\n toClean.push(k);\n }\n else {\n throw new Error(`arx: invalid 32-byte key, got length=${l}`);\n }\n // Nonce\n // salsa20: 8 (8-byte counter)\n // chacha20orig: 8 (8-byte counter)\n // chacha20: 12 (4-byte counter)\n // xsalsa20: 24 (16 -> hsalsa, 8 -> old nonce)\n // xchacha20: 24 (16 -> hchacha, 8 -> old nonce)\n // Align nonce to 4 bytes\n if (!isAligned32(nonce))\n toClean.push((nonce = copyBytes(nonce)));\n const k32 = u32(k);\n // hsalsa & hchacha: handle extended nonce\n if (extendNonceFn) {\n if (nonce.length !== 24)\n throw new Error(`arx: extended nonce must be 24 bytes`);\n extendNonceFn(sigma, k32, u32(nonce.subarray(0, 16)), k32);\n nonce = nonce.subarray(16);\n }\n // Handle nonce counter\n const nonceNcLen = 16 - counterLength;\n if (nonceNcLen !== nonce.length)\n throw new Error(`arx: nonce must be ${nonceNcLen} or 16 bytes`);\n // Pad counter when nonce is 64 bit\n if (nonceNcLen !== 12) {\n const nc = new Uint8Array(12);\n nc.set(nonce, counterRight ? 0 : 12 - nonce.length);\n nonce = nc;\n toClean.push(nonce);\n }\n const n32 = u32(nonce);\n runCipher(core, sigma, k32, n32, data, output, counter, rounds);\n clean(...toClean);\n return output;\n };\n}\n//# sourceMappingURL=_arx.js.map",
|
|
8
|
+
"/**\n * Poly1305 ([PDF](https://cr.yp.to/mac/poly1305-20050329.pdf),\n * [wiki](https://en.wikipedia.org/wiki/Poly1305))\n * is a fast and parallel secret-key message-authentication code suitable for\n * a wide variety of applications. It was standardized in\n * [RFC 8439](https://datatracker.ietf.org/doc/html/rfc8439) and is now used in TLS 1.3.\n *\n * Polynomial MACs are not perfect for every situation:\n * they lack Random Key Robustness: the MAC can be forged, and can't be used in PAKE schemes.\n * See [invisible salamanders attack](https://keymaterial.net/2020/09/07/invisible-salamanders-in-aes-gcm-siv/).\n * To combat invisible salamanders, `hash(key)` can be included in ciphertext,\n * however, this would violate ciphertext indistinguishability:\n * an attacker would know which key was used - so `HKDF(key, i)`\n * could be used instead.\n *\n * Check out [original website](https://cr.yp.to/mac.html).\n * @module\n */\nimport { Hash, abytes, aexists, aoutput, clean, toBytes } from \"./utils.js\";\n// Based on Public Domain poly1305-donna https://github.com/floodyberry/poly1305-donna\nconst u8to16 = (a, i) => (a[i++] & 0xff) | ((a[i++] & 0xff) << 8);\nclass Poly1305 {\n constructor(key) {\n this.blockLen = 16;\n this.outputLen = 16;\n this.buffer = new Uint8Array(16);\n this.r = new Uint16Array(10);\n this.h = new Uint16Array(10);\n this.pad = new Uint16Array(8);\n this.pos = 0;\n this.finished = false;\n key = toBytes(key);\n abytes(key, 32);\n const t0 = u8to16(key, 0);\n const t1 = u8to16(key, 2);\n const t2 = u8to16(key, 4);\n const t3 = u8to16(key, 6);\n const t4 = u8to16(key, 8);\n const t5 = u8to16(key, 10);\n const t6 = u8to16(key, 12);\n const t7 = u8to16(key, 14);\n // https://github.com/floodyberry/poly1305-donna/blob/e6ad6e091d30d7f4ec2d4f978be1fcfcbce72781/poly1305-donna-16.h#L47\n this.r[0] = t0 & 0x1fff;\n this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff;\n this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03;\n this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff;\n this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff;\n this.r[5] = (t4 >>> 1) & 0x1ffe;\n this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff;\n this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81;\n this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff;\n this.r[9] = (t7 >>> 5) & 0x007f;\n for (let i = 0; i < 8; i++)\n this.pad[i] = u8to16(key, 16 + 2 * i);\n }\n process(data, offset, isLast = false) {\n const hibit = isLast ? 0 : 1 << 11;\n const { h, r } = this;\n const r0 = r[0];\n const r1 = r[1];\n const r2 = r[2];\n const r3 = r[3];\n const r4 = r[4];\n const r5 = r[5];\n const r6 = r[6];\n const r7 = r[7];\n const r8 = r[8];\n const r9 = r[9];\n const t0 = u8to16(data, offset + 0);\n const t1 = u8to16(data, offset + 2);\n const t2 = u8to16(data, offset + 4);\n const t3 = u8to16(data, offset + 6);\n const t4 = u8to16(data, offset + 8);\n const t5 = u8to16(data, offset + 10);\n const t6 = u8to16(data, offset + 12);\n const t7 = u8to16(data, offset + 14);\n let h0 = h[0] + (t0 & 0x1fff);\n let h1 = h[1] + (((t0 >>> 13) | (t1 << 3)) & 0x1fff);\n let h2 = h[2] + (((t1 >>> 10) | (t2 << 6)) & 0x1fff);\n let h3 = h[3] + (((t2 >>> 7) | (t3 << 9)) & 0x1fff);\n let h4 = h[4] + (((t3 >>> 4) | (t4 << 12)) & 0x1fff);\n let h5 = h[5] + ((t4 >>> 1) & 0x1fff);\n let h6 = h[6] + (((t4 >>> 14) | (t5 << 2)) & 0x1fff);\n let h7 = h[7] + (((t5 >>> 11) | (t6 << 5)) & 0x1fff);\n let h8 = h[8] + (((t6 >>> 8) | (t7 << 8)) & 0x1fff);\n let h9 = h[9] + ((t7 >>> 5) | hibit);\n let c = 0;\n let d0 = c + h0 * r0 + h1 * (5 * r9) + h2 * (5 * r8) + h3 * (5 * r7) + h4 * (5 * r6);\n c = d0 >>> 13;\n d0 &= 0x1fff;\n d0 += h5 * (5 * r5) + h6 * (5 * r4) + h7 * (5 * r3) + h8 * (5 * r2) + h9 * (5 * r1);\n c += d0 >>> 13;\n d0 &= 0x1fff;\n let d1 = c + h0 * r1 + h1 * r0 + h2 * (5 * r9) + h3 * (5 * r8) + h4 * (5 * r7);\n c = d1 >>> 13;\n d1 &= 0x1fff;\n d1 += h5 * (5 * r6) + h6 * (5 * r5) + h7 * (5 * r4) + h8 * (5 * r3) + h9 * (5 * r2);\n c += d1 >>> 13;\n d1 &= 0x1fff;\n let d2 = c + h0 * r2 + h1 * r1 + h2 * r0 + h3 * (5 * r9) + h4 * (5 * r8);\n c = d2 >>> 13;\n d2 &= 0x1fff;\n d2 += h5 * (5 * r7) + h6 * (5 * r6) + h7 * (5 * r5) + h8 * (5 * r4) + h9 * (5 * r3);\n c += d2 >>> 13;\n d2 &= 0x1fff;\n let d3 = c + h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * (5 * r9);\n c = d3 >>> 13;\n d3 &= 0x1fff;\n d3 += h5 * (5 * r8) + h6 * (5 * r7) + h7 * (5 * r6) + h8 * (5 * r5) + h9 * (5 * r4);\n c += d3 >>> 13;\n d3 &= 0x1fff;\n let d4 = c + h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0;\n c = d4 >>> 13;\n d4 &= 0x1fff;\n d4 += h5 * (5 * r9) + h6 * (5 * r8) + h7 * (5 * r7) + h8 * (5 * r6) + h9 * (5 * r5);\n c += d4 >>> 13;\n d4 &= 0x1fff;\n let d5 = c + h0 * r5 + h1 * r4 + h2 * r3 + h3 * r2 + h4 * r1;\n c = d5 >>> 13;\n d5 &= 0x1fff;\n d5 += h5 * r0 + h6 * (5 * r9) + h7 * (5 * r8) + h8 * (5 * r7) + h9 * (5 * r6);\n c += d5 >>> 13;\n d5 &= 0x1fff;\n let d6 = c + h0 * r6 + h1 * r5 + h2 * r4 + h3 * r3 + h4 * r2;\n c = d6 >>> 13;\n d6 &= 0x1fff;\n d6 += h5 * r1 + h6 * r0 + h7 * (5 * r9) + h8 * (5 * r8) + h9 * (5 * r7);\n c += d6 >>> 13;\n d6 &= 0x1fff;\n let d7 = c + h0 * r7 + h1 * r6 + h2 * r5 + h3 * r4 + h4 * r3;\n c = d7 >>> 13;\n d7 &= 0x1fff;\n d7 += h5 * r2 + h6 * r1 + h7 * r0 + h8 * (5 * r9) + h9 * (5 * r8);\n c += d7 >>> 13;\n d7 &= 0x1fff;\n let d8 = c + h0 * r8 + h1 * r7 + h2 * r6 + h3 * r5 + h4 * r4;\n c = d8 >>> 13;\n d8 &= 0x1fff;\n d8 += h5 * r3 + h6 * r2 + h7 * r1 + h8 * r0 + h9 * (5 * r9);\n c += d8 >>> 13;\n d8 &= 0x1fff;\n let d9 = c + h0 * r9 + h1 * r8 + h2 * r7 + h3 * r6 + h4 * r5;\n c = d9 >>> 13;\n d9 &= 0x1fff;\n d9 += h5 * r4 + h6 * r3 + h7 * r2 + h8 * r1 + h9 * r0;\n c += d9 >>> 13;\n d9 &= 0x1fff;\n c = ((c << 2) + c) | 0;\n c = (c + d0) | 0;\n d0 = c & 0x1fff;\n c = c >>> 13;\n d1 += c;\n h[0] = d0;\n h[1] = d1;\n h[2] = d2;\n h[3] = d3;\n h[4] = d4;\n h[5] = d5;\n h[6] = d6;\n h[7] = d7;\n h[8] = d8;\n h[9] = d9;\n }\n finalize() {\n const { h, pad } = this;\n const g = new Uint16Array(10);\n let c = h[1] >>> 13;\n h[1] &= 0x1fff;\n for (let i = 2; i < 10; i++) {\n h[i] += c;\n c = h[i] >>> 13;\n h[i] &= 0x1fff;\n }\n h[0] += c * 5;\n c = h[0] >>> 13;\n h[0] &= 0x1fff;\n h[1] += c;\n c = h[1] >>> 13;\n h[1] &= 0x1fff;\n h[2] += c;\n g[0] = h[0] + 5;\n c = g[0] >>> 13;\n g[0] &= 0x1fff;\n for (let i = 1; i < 10; i++) {\n g[i] = h[i] + c;\n c = g[i] >>> 13;\n g[i] &= 0x1fff;\n }\n g[9] -= 1 << 13;\n let mask = (c ^ 1) - 1;\n for (let i = 0; i < 10; i++)\n g[i] &= mask;\n mask = ~mask;\n for (let i = 0; i < 10; i++)\n h[i] = (h[i] & mask) | g[i];\n h[0] = (h[0] | (h[1] << 13)) & 0xffff;\n h[1] = ((h[1] >>> 3) | (h[2] << 10)) & 0xffff;\n h[2] = ((h[2] >>> 6) | (h[3] << 7)) & 0xffff;\n h[3] = ((h[3] >>> 9) | (h[4] << 4)) & 0xffff;\n h[4] = ((h[4] >>> 12) | (h[5] << 1) | (h[6] << 14)) & 0xffff;\n h[5] = ((h[6] >>> 2) | (h[7] << 11)) & 0xffff;\n h[6] = ((h[7] >>> 5) | (h[8] << 8)) & 0xffff;\n h[7] = ((h[8] >>> 8) | (h[9] << 5)) & 0xffff;\n let f = h[0] + pad[0];\n h[0] = f & 0xffff;\n for (let i = 1; i < 8; i++) {\n f = (((h[i] + pad[i]) | 0) + (f >>> 16)) | 0;\n h[i] = f & 0xffff;\n }\n clean(g);\n }\n update(data) {\n aexists(this);\n data = toBytes(data);\n abytes(data);\n const { buffer, blockLen } = this;\n const len = data.length;\n for (let pos = 0; pos < len;) {\n const take = Math.min(blockLen - this.pos, len - pos);\n // Fast path: we have at least one block in input\n if (take === blockLen) {\n for (; blockLen <= len - pos; pos += blockLen)\n this.process(data, pos);\n continue;\n }\n buffer.set(data.subarray(pos, pos + take), this.pos);\n this.pos += take;\n pos += take;\n if (this.pos === blockLen) {\n this.process(buffer, 0, false);\n this.pos = 0;\n }\n }\n return this;\n }\n destroy() {\n clean(this.h, this.r, this.buffer, this.pad);\n }\n digestInto(out) {\n aexists(this);\n aoutput(out, this);\n this.finished = true;\n const { buffer, h } = this;\n let { pos } = this;\n if (pos) {\n buffer[pos++] = 1;\n for (; pos < 16; pos++)\n buffer[pos] = 0;\n this.process(buffer, 0, true);\n }\n this.finalize();\n let opos = 0;\n for (let i = 0; i < 8; i++) {\n out[opos++] = h[i] >>> 0;\n out[opos++] = h[i] >>> 8;\n }\n return out;\n }\n digest() {\n const { buffer, outputLen } = this;\n this.digestInto(buffer);\n const res = buffer.slice(0, outputLen);\n this.destroy();\n return res;\n }\n}\nexport function wrapConstructorWithKey(hashCons) {\n const hashC = (msg, key) => hashCons(key).update(toBytes(msg)).digest();\n const tmp = hashCons(new Uint8Array(32));\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (key) => hashCons(key);\n return hashC;\n}\n/** Poly1305 MAC from RFC 8439. */\nexport const poly1305 = wrapConstructorWithKey((key) => new Poly1305(key));\n//# sourceMappingURL=_poly1305.js.map",
|
|
9
|
+
"/**\n * [ChaCha20](https://cr.yp.to/chacha.html) stream cipher, released\n * in 2008. Developed after Salsa20, ChaCha aims to increase diffusion per round.\n * It was standardized in [RFC 8439](https://datatracker.ietf.org/doc/html/rfc8439) and\n * is now used in TLS 1.3.\n *\n * [XChaCha20](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha)\n * extended-nonce variant is also provided. Similar to XSalsa, it's safe to use with\n * randomly-generated nonces.\n *\n * Check out [PDF](http://cr.yp.to/chacha/chacha-20080128.pdf) and\n * [wiki](https://en.wikipedia.org/wiki/Salsa20).\n * @module\n */\nimport { createCipher, rotl } from \"./_arx.js\";\nimport { poly1305 } from \"./_poly1305.js\";\nimport { clean, equalBytes, getOutput, u64Lengths, wrapCipher, } from \"./utils.js\";\n/**\n * ChaCha core function.\n */\n// prettier-ignore\nfunction chachaCore(s, k, n, out, cnt, rounds = 20) {\n let y00 = s[0], y01 = s[1], y02 = s[2], y03 = s[3], // \"expa\" \"nd 3\" \"2-by\" \"te k\"\n y04 = k[0], y05 = k[1], y06 = k[2], y07 = k[3], // Key Key Key Key\n y08 = k[4], y09 = k[5], y10 = k[6], y11 = k[7], // Key Key Key Key\n y12 = cnt, y13 = n[0], y14 = n[1], y15 = n[2]; // Counter Counter\tNonce Nonce\n // Save state to temporary variables\n let x00 = y00, x01 = y01, x02 = y02, x03 = y03, x04 = y04, x05 = y05, x06 = y06, x07 = y07, x08 = y08, x09 = y09, x10 = y10, x11 = y11, x12 = y12, x13 = y13, x14 = y14, x15 = y15;\n for (let r = 0; r < rounds; r += 2) {\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 16);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 12);\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 8);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 7);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 16);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 12);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 8);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 7);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 16);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 12);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 8);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 7);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 16);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 12);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 8);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 7);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 16);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 12);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 8);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 7);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 16);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 12);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 8);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 7);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 16);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 12);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 8);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 7);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 16);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 12);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 8);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 7);\n }\n // Write output\n let oi = 0;\n out[oi++] = (y00 + x00) | 0;\n out[oi++] = (y01 + x01) | 0;\n out[oi++] = (y02 + x02) | 0;\n out[oi++] = (y03 + x03) | 0;\n out[oi++] = (y04 + x04) | 0;\n out[oi++] = (y05 + x05) | 0;\n out[oi++] = (y06 + x06) | 0;\n out[oi++] = (y07 + x07) | 0;\n out[oi++] = (y08 + x08) | 0;\n out[oi++] = (y09 + x09) | 0;\n out[oi++] = (y10 + x10) | 0;\n out[oi++] = (y11 + x11) | 0;\n out[oi++] = (y12 + x12) | 0;\n out[oi++] = (y13 + x13) | 0;\n out[oi++] = (y14 + x14) | 0;\n out[oi++] = (y15 + x15) | 0;\n}\n/**\n * hchacha helper method, used primarily in xchacha, to hash\n * key and nonce into key' and nonce'.\n * Same as chachaCore, but there doesn't seem to be a way to move the block\n * out without 25% performance hit.\n */\n// prettier-ignore\nexport function hchacha(s, k, i, o32) {\n let x00 = s[0], x01 = s[1], x02 = s[2], x03 = s[3], x04 = k[0], x05 = k[1], x06 = k[2], x07 = k[3], x08 = k[4], x09 = k[5], x10 = k[6], x11 = k[7], x12 = i[0], x13 = i[1], x14 = i[2], x15 = i[3];\n for (let r = 0; r < 20; r += 2) {\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 16);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 12);\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 8);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 7);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 16);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 12);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 8);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 7);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 16);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 12);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 8);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 7);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 16);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 12);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 8);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 7);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 16);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 12);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 8);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 7);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 16);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 12);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 8);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 7);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 16);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 12);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 8);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 7);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 16);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 12);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 8);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 7);\n }\n let oi = 0;\n o32[oi++] = x00;\n o32[oi++] = x01;\n o32[oi++] = x02;\n o32[oi++] = x03;\n o32[oi++] = x12;\n o32[oi++] = x13;\n o32[oi++] = x14;\n o32[oi++] = x15;\n}\n/**\n * Original, non-RFC chacha20 from DJB. 8-byte nonce, 8-byte counter.\n */\nexport const chacha20orig = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 8,\n allowShortKeys: true,\n});\n/**\n * ChaCha stream cipher. Conforms to RFC 8439 (IETF, TLS). 12-byte nonce, 4-byte counter.\n * With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance.\n */\nexport const chacha20 = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 4,\n allowShortKeys: false,\n});\n/**\n * XChaCha eXtended-nonce ChaCha. 24-byte nonce.\n * With 24-byte nonce, it's safe to use fill it with random (CSPRNG).\n * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha\n */\nexport const xchacha20 = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 8,\n extendNonceFn: hchacha,\n allowShortKeys: false,\n});\n/**\n * Reduced 8-round chacha, described in original paper.\n */\nexport const chacha8 = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 4,\n rounds: 8,\n});\n/**\n * Reduced 12-round chacha, described in original paper.\n */\nexport const chacha12 = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 4,\n rounds: 12,\n});\nconst ZEROS16 = /* @__PURE__ */ new Uint8Array(16);\n// Pad to digest size with zeros\nconst updatePadded = (h, msg) => {\n h.update(msg);\n const left = msg.length % 16;\n if (left)\n h.update(ZEROS16.subarray(left));\n};\nconst ZEROS32 = /* @__PURE__ */ new Uint8Array(32);\nfunction computeTag(fn, key, nonce, data, AAD) {\n const authKey = fn(key, nonce, ZEROS32);\n const h = poly1305.create(authKey);\n if (AAD)\n updatePadded(h, AAD);\n updatePadded(h, data);\n const num = u64Lengths(data.length, AAD ? AAD.length : 0, true);\n h.update(num);\n const res = h.digest();\n clean(authKey, num);\n return res;\n}\n/**\n * AEAD algorithm from RFC 8439.\n * Salsa20 and chacha (RFC 8439) use poly1305 differently.\n * We could have composed them similar to:\n * https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250\n * But it's hard because of authKey:\n * In salsa20, authKey changes position in salsa stream.\n * In chacha, authKey can't be computed inside computeTag, it modifies the counter.\n */\nexport const _poly1305_aead = (xorStream) => (key, nonce, AAD) => {\n const tagLength = 16;\n return {\n encrypt(plaintext, output) {\n const plength = plaintext.length;\n output = getOutput(plength + tagLength, output, false);\n output.set(plaintext);\n const oPlain = output.subarray(0, -tagLength);\n xorStream(key, nonce, oPlain, oPlain, 1);\n const tag = computeTag(xorStream, key, nonce, oPlain, AAD);\n output.set(tag, plength); // append tag\n clean(tag);\n return output;\n },\n decrypt(ciphertext, output) {\n output = getOutput(ciphertext.length - tagLength, output, false);\n const data = ciphertext.subarray(0, -tagLength);\n const passedTag = ciphertext.subarray(-tagLength);\n const tag = computeTag(xorStream, key, nonce, data, AAD);\n if (!equalBytes(passedTag, tag))\n throw new Error('invalid tag');\n output.set(ciphertext.subarray(0, -tagLength));\n xorStream(key, nonce, output, output, 1); // start stream with i=1\n clean(tag);\n return output;\n },\n };\n};\n/**\n * ChaCha20-Poly1305 from RFC 8439.\n *\n * Unsafe to use random nonces under the same key, due to collision chance.\n * Prefer XChaCha instead.\n */\nexport const chacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 12, tagLength: 16 }, _poly1305_aead(chacha20));\n/**\n * XChaCha20-Poly1305 extended-nonce chacha.\n *\n * Can be safely used with random nonces (CSPRNG).\n * See [IRTF draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha).\n */\nexport const xchacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 24, tagLength: 16 }, _poly1305_aead(xchacha20));\n//# sourceMappingURL=chacha.js.map",
|
|
10
|
+
"/** Voice gateway version this package speaks. */\nexport const VOICE_GATEWAY_VERSION = 8;\n\n/** Voice gateway opcodes (v8, with the DAVE opcodes 21-31). */\nexport const VoiceOpcodes = {\n Identify: 0,\n SelectProtocol: 1,\n Ready: 2,\n Heartbeat: 3,\n SessionDescription: 4,\n Speaking: 5,\n HeartbeatAck: 6,\n Resume: 7,\n Hello: 8,\n Resumed: 9,\n ClientsConnect: 11,\n ClientDisconnect: 13,\n DavePrepareTransition: 21,\n DaveExecuteTransition: 22,\n DaveTransitionReady: 23,\n DavePrepareEpoch: 24,\n DaveMlsExternalSender: 25,\n DaveMlsKeyPackage: 26,\n DaveMlsProposals: 27,\n DaveMlsCommitWelcome: 28,\n DaveMlsAnnounceCommitTransition: 29,\n DaveMlsWelcome: 30,\n DaveMlsInvalidCommitWelcome: 31,\n} as const;\nexport type VoiceOpcodes = (typeof VoiceOpcodes)[keyof typeof VoiceOpcodes];\n\n/** Voice gateway close codes. */\nexport const VoiceCloseCodes = {\n UnknownOpcode: 4001,\n FailedToDecode: 4002,\n NotAuthenticated: 4003,\n AuthenticationFailed: 4004,\n AlreadyAuthenticated: 4005,\n SessionNoLongerValid: 4006,\n SessionTimeout: 4009,\n ServerNotFound: 4011,\n UnknownProtocol: 4012,\n Disconnected: 4014,\n VoiceServerCrashed: 4015,\n UnknownEncryptionMode: 4016,\n DaveProtocolRequired: 4017,\n BadRequest: 4020,\n RateLimited: 4021,\n CallTerminated: 4022,\n} as const;\nexport type VoiceCloseCodes =\n (typeof VoiceCloseCodes)[keyof typeof VoiceCloseCodes];\n\n/**\n * Whether a voice gateway close can be resumed (op 7). Codes below 4000\n * (network or server-side closes) and 4015 (voice server crashed) can; 4006\n * (session invalid), 4014 (removed from the channel) and every other 4xxx\n * cannot.\n */\nexport function canResumeVoice(code: number): boolean {\n return code < 4000 || code === VoiceCloseCodes.VoiceServerCrashed;\n}\n\n/** RTP payload type Discord uses for Opus. */\nexport const RTP_OPUS_PAYLOAD_TYPE = 0x78;\n\n/** Opus frames are 20 ms of 48 kHz audio. */\nexport const FRAME_DURATION_MS = 20;\n/** Samples per channel in one 20 ms frame at 48 kHz. */\nexport const FRAME_SAMPLES = 960;\n/** Bytes of one 20 ms frame of 48 kHz stereo s16le PCM. */\nexport const PCM_FRAME_BYTES = FRAME_SAMPLES * 2 * 2;\n\n/** The Opus frame Discord treats as silence. Five of them end a transmission. */\nexport const SILENCE_FRAME: Uint8Array = Uint8Array.of(0xf8, 0xff, 0xfe);\n\n/** Speaking flags for op 5. */\nexport const SpeakingFlags = {\n Microphone: 1,\n Soundshare: 2,\n Priority: 4,\n} as const;\n\n/** Voice protocol errors. */\nexport class VoiceError extends Error {\n public constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"VoiceError\";\n }\n}\n",
|
|
11
|
+
"import { SILENCE_FRAME, VoiceError } from \"./protocol.js\";\n\n/** The parts of `@snazzah/davey`'s session this package uses. */\ninterface DaveyNativeSession {\n readonly ready: boolean;\n readonly voicePrivacyCode: string;\n reinit(protocolVersion: number, userId: string, channelId: string): void;\n reset(): void;\n setExternalSender(data: Buffer): void;\n getSerializedKeyPackage(): Buffer;\n processProposals(\n operationType: number,\n proposals: Buffer,\n recognizedUserIds?: string[],\n ): { commit?: Buffer; welcome?: Buffer };\n processWelcome(welcome: Buffer): void;\n processCommit(commit: Buffer): void;\n encryptOpus(packet: Buffer): Buffer;\n decrypt(userId: string, mediaType: number, packet: Buffer): Buffer;\n canPassthrough(userId: string): boolean;\n setPassthroughMode(passthrough: boolean, expirySeconds?: number): void;\n}\n\n/** The parts of `@snazzah/davey` this package uses. */\nexport interface DaveyModule {\n DAVE_PROTOCOL_VERSION: number;\n DAVESession: new (\n protocolVersion: number,\n userId: string,\n channelId: string,\n ) => DaveyNativeSession;\n}\n\nlet davey: DaveyModule | null | undefined;\n\n/**\n * Loads `@snazzah/davey` (the DAVE protocol: MLS group keys and frame\n * encryption), an optional peer dependency. @returns The module, or `null`\n * when it is not installed.\n */\nexport async function loadDave(): Promise<DaveyModule | null> {\n if (davey !== undefined) return davey;\n try {\n // Optional peer: a variable keeps bundlers from inlining its native binaries.\n const name = \"@snazzah/davey\";\n const mod = (await import(name)) as unknown as {\n default?: DaveyModule;\n } & DaveyModule;\n davey = mod.default?.DAVESession ? mod.default : mod;\n } catch {\n davey = null;\n }\n return davey;\n}\n\n/** Highest DAVE protocol version available here: 0 when `@snazzah/davey` is not installed. */\nexport async function maxDaveProtocolVersion(): Promise<number> {\n return (await loadDave())?.DAVE_PROTOCOL_VERSION ?? 0;\n}\n\nconst TRANSITION_EXPIRY_S = 10;\nconst TRANSITION_EXPIRY_DOWNGRADE_S = 24;\nconst DECRYPTION_FAILURE_TOLERANCE = 36;\nconst AUDIO = 0;\n\nfunction equalBytes(a: Uint8Array, b: Uint8Array): boolean {\n return a.length === b.length && a.every((byte, i) => byte === b[i]);\n}\n\n/** What a {@link DaveSession} asks its connection to send. */\nexport interface DaveSessionHooks {\n /** Send op 26 with this key package. */\n keyPackage(payload: Uint8Array): void;\n /** Send op 31: this transition could not be applied. */\n invalidTransition(transitionId: number): void;\n debug?(message: string): void;\n}\n\n/**\n * One end-to-end encrypted (DAVE) media session: the MLS group of a voice\n * channel, its protocol transitions, and Opus frame encryption. Follows the\n * DAVE protocol's client flow (key package → proposals → commit/welcome →\n * transition ready → execute).\n */\nexport class DaveSession {\n public protocolVersion: number;\n readonly #module: DaveyModule;\n readonly #userId: string;\n readonly #channelId: string;\n readonly #hooks: DaveSessionHooks;\n #session?: DaveyNativeSession;\n readonly #pending = new Map<number, number>();\n #lastTransition?: number;\n #downgraded = false;\n #reinitializing = false;\n /** An upgrade from transport-only (op 24, epoch 1) is pending: media stays unencrypted until it executes. */\n #upgrading = false;\n #failures = 0;\n\n public constructor(\n module: DaveyModule,\n protocolVersion: number,\n userId: string,\n channelId: string,\n hooks: DaveSessionHooks,\n ) {\n this.#module = module;\n this.protocolVersion = protocolVersion;\n this.#userId = userId;\n this.#channelId = channelId;\n this.#hooks = hooks;\n }\n\n /** Whether frames are currently end-to-end encrypted. */\n public get active(): boolean {\n return this.protocolVersion > 0 && Boolean(this.#session?.ready);\n }\n\n /** The voice privacy code users can compare, or `null` without DAVE. */\n public get voicePrivacyCode(): string | null {\n return this.protocolVersion > 0 && this.#session?.voicePrivacyCode\n ? this.#session.voicePrivacyCode\n : null;\n }\n\n /** (Re)creates the MLS state and announces a fresh key package. */\n public reinit(): void {\n if (this.protocolVersion > 0) {\n if (this.#session)\n this.#session.reinit(\n this.protocolVersion,\n this.#userId,\n this.#channelId,\n );\n else\n this.#session = new this.#module.DAVESession(\n this.protocolVersion,\n this.#userId,\n this.#channelId,\n );\n this.#hooks.keyPackage(this.#session.getSerializedKeyPackage());\n } else if (this.#session) {\n this.#session.reset();\n this.#session.setPassthroughMode(true, TRANSITION_EXPIRY_S);\n }\n }\n\n /** Op 25. */\n public setExternalSender(payload: Uint8Array): void {\n this.#native().setExternalSender(Buffer.from(payload));\n }\n\n /** Op 21. @returns Whether to answer with op 23 (transition ready). */\n public prepareTransition(\n transitionId: number,\n protocolVersion: number,\n ): boolean {\n this.#pending.set(transitionId, protocolVersion);\n if (transitionId === 0) {\n this.executeTransition(0);\n return false;\n }\n if (protocolVersion === 0)\n this.#session?.setPassthroughMode(\n true,\n TRANSITION_EXPIRY_DOWNGRADE_S,\n );\n return true;\n }\n\n /** Op 22. @returns Whether a pending transition was executed. */\n public executeTransition(transitionId: number): boolean {\n const next = this.#pending.get(transitionId);\n if (next === undefined) return false;\n const previous = this.protocolVersion;\n this.protocolVersion = next;\n if (previous !== next && next === 0) this.#downgraded = true;\n else if (transitionId > 0 && this.#downgraded) {\n this.#downgraded = false;\n this.#session?.setPassthroughMode(true, TRANSITION_EXPIRY_S);\n }\n this.#reinitializing = false;\n this.#upgrading = false;\n this.#lastTransition = transitionId;\n this.#pending.delete(transitionId);\n this.#hooks.debug?.(\n `DAVE transition ${transitionId}: v${previous} -> v${next}`,\n );\n return true;\n }\n\n /** Op 24. */\n public prepareEpoch(epoch: number, protocolVersion: number): void {\n if (epoch === 1) {\n if (this.protocolVersion === 0 && protocolVersion > 0)\n this.#upgrading = true;\n this.protocolVersion = protocolVersion;\n this.reinit();\n }\n }\n\n /** Op 27. @returns The op 28 payload (commit, then welcome) to send, if any. */\n public processProposals(\n payload: Uint8Array,\n connectedUserIds: Iterable<string>,\n ): Uint8Array | undefined {\n if (payload.length < 1) return undefined;\n const { commit, welcome } = this.#native().processProposals(\n payload[0]!,\n Buffer.from(payload.subarray(1)),\n [...connectedUserIds],\n );\n if (!commit) return undefined;\n return welcome ? Buffer.concat([commit, welcome]) : commit;\n }\n\n /** Op 29 (commit) or op 30 (welcome). @returns The transition and whether it applied; a failure re-initializes. */\n public process(\n kind: \"commit\" | \"welcome\",\n payload: Uint8Array,\n ): { transitionId: number; ok: boolean } {\n const transitionId =\n payload.length >= 2 ? (payload[0]! << 8) | payload[1]! : 0;\n try {\n const body = Buffer.from(payload.subarray(2));\n if (kind === \"commit\") this.#native().processCommit(body);\n else this.#native().processWelcome(body);\n if (transitionId === 0) {\n this.#reinitializing = false;\n this.#lastTransition = 0;\n } else this.#pending.set(transitionId, this.protocolVersion);\n return { transitionId, ok: true };\n } catch (error) {\n this.#hooks.debug?.(`DAVE ${kind} failed: ${String(error)}`);\n this.#recover(transitionId);\n return { transitionId, ok: false };\n }\n }\n\n #recover(transitionId: number): void {\n if (this.#reinitializing) return;\n this.#reinitializing = true;\n this.#failures = 0;\n this.#hooks.invalidTransition(transitionId);\n this.reinit();\n }\n\n /**\n * End-to-end encrypts an outgoing Opus frame. Silence frames, frames\n * without DAVE (protocol version 0) and frames during an upgrade from\n * transport-only stay as they are. @returns The frame to send, or `null`\n * to drop it: DAVE is required but the MLS group is not ready (joining, or\n * recovering from an invalid commit), so it must not leave unencrypted.\n */\n public encrypt(frame: Uint8Array): Uint8Array | null {\n if (this.protocolVersion === 0 || equalBytes(frame, SILENCE_FRAME))\n return frame;\n if (!this.#session?.ready) return this.#upgrading ? frame : null;\n return this.#session.encryptOpus(Buffer.from(frame));\n }\n\n /** Decrypts a frame from `userId`. @returns The Opus frame, or `null` to drop it. */\n public decrypt(frame: Uint8Array, userId: string): Uint8Array | null {\n const session = this.#session;\n const canDecrypt =\n session?.ready &&\n (this.protocolVersion !== 0 || session.canPassthrough(userId));\n if (!session || !canDecrypt || equalBytes(frame, SILENCE_FRAME))\n return frame;\n try {\n const out = session.decrypt(userId, AUDIO, Buffer.from(frame));\n this.#failures = 0;\n return out;\n } catch {\n if (!this.#reinitializing && this.#pending.size === 0) {\n this.#failures++;\n if (\n this.#failures > DECRYPTION_FAILURE_TOLERANCE &&\n this.#lastTransition !== undefined\n )\n this.#recover(this.#lastTransition);\n }\n return null;\n }\n }\n\n #native(): DaveyNativeSession {\n if (!this.#session) throw new VoiceError(\"No DAVE session.\");\n return this.#session;\n }\n\n /** Drops the MLS state. */\n public destroy(): void {\n try {\n this.#session?.reset();\n } catch {\n // Already reset.\n }\n this.#session = undefined;\n }\n}\n",
|
|
12
|
+
"import { GatewayHeartbeat } from \"@lunibee/ws\";\nimport { VOICE_GATEWAY_VERSION, VoiceOpcodes } from \"./protocol.js\";\n\n/** A JSON voice gateway frame. */\nexport interface VoicePacket {\n op: number;\n d?: unknown;\n seq?: number;\n}\n\n/** A binary voice gateway frame (DAVE): sequence, opcode and payload. */\nexport interface VoiceBinaryPacket {\n seq: number;\n op: number;\n payload: Uint8Array;\n}\n\n/** The parts of a WebSocket {@link VoiceGateway} uses; the global `WebSocket` provides them. */\nexport interface VoiceSocketLike {\n binaryType: string;\n readonly readyState: number;\n send(data: string | Uint8Array): void;\n close(code?: number, reason?: string): void;\n addEventListener(type: string, listener: (event: never) => void): void;\n}\n\n/** Opens a WebSocket. Replace it in tests. */\nexport type VoiceSocketFactory = (url: string) => VoiceSocketLike;\n\n/** The default factory: the runtime's global `WebSocket`. */\nexport const globalVoiceSocket: VoiceSocketFactory = (url) =>\n new WebSocket(url) as unknown as VoiceSocketLike;\n\n/** What a {@link VoiceGateway} reports to its owner. */\nexport interface VoiceGatewayHandlers {\n open(): void;\n packet(packet: VoicePacket): void;\n binary(packet: VoiceBinaryPacket): void;\n close(code: number, reason: string): void;\n error(error: Error): void;\n}\n\n/** Client close code for missed heartbeat ACKs: below 4000, so the session resumes. */\nexport const HEARTBEAT_TIMEOUT_CLOSE = 3001;\n\n/** Builds the voice gateway URL for an endpoint from VOICE_SERVER_UPDATE. */\nexport function voiceGatewayURL(endpoint: string): string {\n const host = endpoint.replace(/^wss?:\\/\\//, \"\").replace(/\\/.*$/, \"\");\n return `wss://${host}/?v=${VOICE_GATEWAY_VERSION}`;\n}\n\n/**\n * One voice gateway WebSocket (v8). Parses JSON and binary frames, tracks the\n * last sequence for `seq_ack`, and heartbeats with `@lunibee/ws`'s\n * {@link GatewayHeartbeat} (an unanswered heartbeat closes with\n * {@link HEARTBEAT_TIMEOUT_CLOSE}, which the owner resumes).\n */\nexport class VoiceGateway {\n /** The last sequence number received, `-1` before any. Sent back as `seq_ack`. */\n public sequence: number;\n readonly #socket: VoiceSocketLike;\n readonly #handlers: VoiceGatewayHandlers;\n readonly #heartbeat: GatewayHeartbeat;\n #closed = false;\n\n public constructor(\n url: string,\n handlers: VoiceGatewayHandlers,\n options: { factory?: VoiceSocketFactory; sequence?: number } = {},\n ) {\n this.sequence = options.sequence ?? -1;\n this.#handlers = handlers;\n this.#socket = (options.factory ?? globalVoiceSocket)(url);\n this.#socket.binaryType = \"arraybuffer\";\n this.#heartbeat = new GatewayHeartbeat({\n ackTimeout: 15_000,\n zombieTimeout: 60_000,\n sequence: () => this.sequence,\n isConnected: () => this.#socket.readyState === 1,\n send: () =>\n this.sendJSON({\n op: VoiceOpcodes.Heartbeat,\n d: { t: Date.now(), seq_ack: this.sequence },\n }),\n onTimeout: () =>\n this.close(HEARTBEAT_TIMEOUT_CLOSE, \"Heartbeat timed out.\"),\n onError: (error) => this.#handlers.error(error),\n });\n this.#socket.addEventListener(\"open\", () => {\n this.#heartbeat.watch();\n this.#handlers.open();\n });\n this.#socket.addEventListener(\"message\", (event: { data: unknown }) =>\n this.#message(event.data),\n );\n this.#socket.addEventListener(\"error\", () => {\n // The close event that follows carries the outcome.\n });\n this.#socket.addEventListener(\n \"close\",\n (event: { code: number; reason: string }) => {\n this.#heartbeat.stop();\n // A close we started was already reported (or was a normal one).\n if (this.#closed) return;\n this.#closed = true;\n this.#handlers.close(event.code, event.reason ?? \"\");\n },\n );\n }\n\n /** Round trip of the last heartbeat, or -1. */\n public get ping(): number {\n return this.#heartbeat.latency;\n }\n\n #message(data: unknown): void {\n this.#heartbeat.receivedMessage();\n if (data instanceof ArrayBuffer || data instanceof Uint8Array) {\n const bytes =\n data instanceof Uint8Array ? data : new Uint8Array(data);\n if (bytes.length < 3) return;\n const seq = (bytes[0]! << 8) | bytes[1]!;\n this.sequence = seq;\n this.#handlers.binary({\n seq,\n op: bytes[2]!,\n payload: bytes.subarray(3),\n });\n return;\n }\n if (typeof data !== \"string\") return;\n let packet: VoicePacket;\n try {\n packet = JSON.parse(data) as VoicePacket;\n } catch {\n this.#handlers.error(\n new Error(\"The voice gateway sent invalid JSON.\"),\n );\n return;\n }\n if (!packet || typeof packet.op !== \"number\") return;\n if (typeof packet.seq === \"number\") this.sequence = packet.seq;\n if (packet.op === VoiceOpcodes.Hello) {\n const interval = (packet.d as { heartbeat_interval?: number })\n ?.heartbeat_interval;\n if (typeof interval === \"number\" && interval > 0)\n this.#heartbeat.start(interval);\n } else if (packet.op === VoiceOpcodes.HeartbeatAck)\n this.#heartbeat.acknowledge();\n this.#handlers.packet(packet);\n }\n\n /** Sends a JSON frame. @returns Whether the socket was open. */\n public sendJSON(packet: VoicePacket): boolean {\n if (this.#socket.readyState !== 1) return false;\n try {\n this.#socket.send(JSON.stringify(packet));\n return true;\n } catch {\n return false;\n }\n }\n\n /** Sends a binary frame: the opcode byte followed by the payload. */\n public sendBinary(op: number, payload: Uint8Array): boolean {\n if (this.#socket.readyState !== 1) return false;\n const frame = new Uint8Array(payload.length + 1);\n frame[0] = op;\n frame.set(payload, 1);\n try {\n this.#socket.send(frame);\n return true;\n } catch {\n return false;\n }\n }\n\n /** Closes the socket and stops heartbeating. A `1000` close is not reported back. */\n public close(code = 1000, reason = \"\"): void {\n this.#heartbeat.stop();\n const reported = this.#closed;\n this.#closed = true;\n try {\n this.#socket.close(code, reason);\n } catch {\n // Already closing.\n }\n // A non-normal close we initiate is reported as such, so the owner can resume.\n if (!reported && code !== 1000) this.#handlers.close(code, reason);\n }\n}\n",
|
|
13
|
+
"import { VoiceError } from \"./protocol.js\";\n\n/** The parts of a UDP socket {@link VoiceUdp} uses; `Bun.udpSocket` provides them. */\nexport interface UdpSocketLike {\n send(data: Uint8Array, port: number, address: string): boolean;\n close(): void;\n}\n\n/** Opens a UDP socket that calls `onData` for each datagram. Replace it in tests. */\nexport type UdpSocketFactory = (\n onData: (data: Uint8Array) => void,\n) => Promise<UdpSocketLike>;\n\n/** The default factory: an IPv4 `Bun.udpSocket` on an ephemeral port. */\nexport const bunUdpSocket: UdpSocketFactory = async (onData) =>\n (await Bun.udpSocket({\n socket: {\n data: (_socket, data) => onData(new Uint8Array(data)),\n // An ICMP \"port unreachable\" surfaces as ECONNREFUSED: the voice\n // server is gone or not there yet. Datagrams are best effort;\n // the gateway's heartbeat decides whether the session is alive.\n error: () => undefined,\n },\n })) as unknown as UdpSocketLike;\n\nconst KEEPALIVE_MS = 5_000;\nconst DISCOVERY_TIMEOUT_MS = 5_000;\n\n/** Builds an IP discovery request (type 0x1, length 70) for `ssrc`. */\nexport function discoveryRequest(ssrc: number): Uint8Array {\n const packet = new Uint8Array(74);\n const view = new DataView(packet.buffer);\n view.setUint16(0, 1);\n view.setUint16(2, 70);\n view.setUint32(4, ssrc >>> 0);\n return packet;\n}\n\n/** Reads an IP discovery response (type 0x2): our external address and port. */\nexport function parseDiscoveryResponse(\n packet: Uint8Array,\n): { ip: string; port: number } | undefined {\n if (packet.length !== 74) return undefined;\n const view = new DataView(\n packet.buffer,\n packet.byteOffset,\n packet.byteLength,\n );\n if (view.getUint16(0) !== 2 || view.getUint16(2) !== 70) return undefined;\n const end = packet.indexOf(0, 8);\n const ip = new TextDecoder().decode(\n packet.subarray(8, end === -1 || end > 72 ? 72 : end),\n );\n if (!/^\\d{1,3}(?:\\.\\d{1,3}){3}$/.test(ip)) return undefined;\n return { ip, port: view.getUint16(72) };\n}\n\n/**\n * The voice UDP socket: sends audio to the voice server, receives other\n * users' audio, runs IP discovery and a keepalive every 5 s. `close()` ends\n * the socket and its timer; nothing is left open.\n */\nexport class VoiceUdp {\n readonly #socket: UdpSocketLike;\n readonly #ip: string;\n readonly #port: number;\n readonly #keepalive: ReturnType<typeof setInterval>;\n readonly #listeners = new Set<(packet: Uint8Array) => void>();\n /** Pending `discover()` calls, ended by `close()`. */\n readonly #discoveries = new Set<() => void>();\n #counter = 0;\n #closed = false;\n\n private constructor(socket: UdpSocketLike, ip: string, port: number) {\n this.#socket = socket;\n this.#ip = ip;\n this.#port = port;\n this.#keepalive = setInterval(\n () => this.#sendKeepalive(),\n KEEPALIVE_MS,\n );\n (this.#keepalive as { unref?: () => void }).unref?.();\n }\n\n /** Opens a socket towards the voice server at `ip:port`. */\n public static async open(\n ip: string,\n port: number,\n factory: UdpSocketFactory = bunUdpSocket,\n ): Promise<VoiceUdp> {\n let udp: VoiceUdp | undefined;\n const socket = await factory((data) => {\n if (udp) udp.#receive(data);\n });\n udp = new VoiceUdp(socket, ip, port);\n return udp;\n }\n\n /** Whether `close()` was called. */\n public get closed(): boolean {\n return this.#closed;\n }\n\n /** Listens for datagrams. @returns A function that removes the listener. */\n public onPacket(listener: (packet: Uint8Array) => void): () => void {\n this.#listeners.add(listener);\n return () => this.#listeners.delete(listener);\n }\n\n /** Sends one datagram to the voice server. @returns Whether it was handed to the socket. */\n public send(packet: Uint8Array): boolean {\n if (this.#closed) return false;\n try {\n return this.#socket.send(packet, this.#port, this.#ip);\n } catch {\n return false;\n }\n }\n\n /** Asks the voice server for our external address. @throws {VoiceError} On timeout or when closed. */\n public discover(\n ssrc: number,\n timeoutMs = DISCOVERY_TIMEOUT_MS,\n ): Promise<{ ip: string; port: number }> {\n return new Promise((resolve, reject) => {\n const settle = (\n error?: Error,\n found?: { ip: string; port: number },\n ): void => {\n clearTimeout(timer);\n remove();\n this.#discoveries.delete(abort);\n if (error) reject(error);\n else resolve(found!);\n };\n const abort = (): void =>\n settle(new VoiceError(\"The voice UDP socket is closed.\"));\n const timer = setTimeout(\n () => settle(new VoiceError(\"IP discovery timed out.\")),\n timeoutMs,\n );\n const remove = this.onPacket((packet) => {\n const found = parseDiscoveryResponse(packet);\n if (found) settle(undefined, found);\n });\n this.#discoveries.add(abort);\n if (!this.send(discoveryRequest(ssrc))) abort();\n });\n }\n\n #sendKeepalive(): void {\n const packet = new Uint8Array(8);\n new DataView(packet.buffer).setUint32(0, this.#counter, true);\n this.#counter = (this.#counter + 1) >>> 0;\n this.send(packet);\n }\n\n #receive(data: Uint8Array): void {\n if (this.#closed) return;\n for (const listener of [...this.#listeners])\n try {\n listener(data);\n } catch {\n // A listener's failure must not stop the others.\n }\n }\n\n /** Closes the socket and stops the keepalive. Safe to call twice. */\n public close(): void {\n if (this.#closed) return;\n this.#closed = true;\n clearInterval(this.#keepalive);\n // A pending discovery ends now, not when its timer fires.\n for (const abort of [...this.#discoveries]) abort();\n this.#listeners.clear();\n try {\n this.#socket.close();\n } catch {\n // Already closed.\n }\n }\n}\n",
|
|
14
|
+
"import {\n PacketCipher,\n chooseEncryptionMode,\n rtpHeader,\n parseRtpHeader,\n type VoiceEncryptionMode,\n} from \"./crypto.js\";\nimport { DaveSession, loadDave } from \"./dave.js\";\nimport {\n VoiceGateway,\n voiceGatewayURL,\n type VoiceBinaryPacket,\n type VoicePacket,\n type VoiceSocketFactory,\n} from \"./gateway.js\";\nimport {\n FRAME_SAMPLES,\n RTP_OPUS_PAYLOAD_TYPE,\n VoiceCloseCodes,\n VoiceError,\n VoiceOpcodes,\n canResumeVoice,\n} from \"./protocol.js\";\nimport { VoiceUdp, type UdpSocketFactory } from \"./udp.js\";\n\n/** What Discord sent for one voice session (VOICE_STATE_UPDATE + VOICE_SERVER_UPDATE). */\nexport interface VoiceServerInfo {\n guildId: string;\n channelId: string;\n userId: string;\n sessionId: string;\n token: string;\n endpoint: string;\n}\n\n/** Where a {@link VoiceNetworking} is in its handshake. */\nexport type NetworkingState =\n | \"opening\"\n | \"identifying\"\n | \"discovering\"\n | \"selecting\"\n | \"ready\"\n | \"resuming\"\n | \"closed\";\n\n/** Options for {@link VoiceNetworking}. */\nexport interface VoiceNetworkingOptions {\n /** Offer DAVE (end-to-end encryption) when `@snazzah/davey` is installed. Default true. Discord requires it outside stage channels. */\n dave?: boolean;\n /** Opens the voice WebSocket (tests). */\n socketFactory?: VoiceSocketFactory;\n /** Opens the UDP socket (tests). */\n udpFactory?: UdpSocketFactory;\n /** Overrides the voice gateway URL built from the endpoint (tests): a URL, or a function of the endpoint. */\n url?: string | ((endpoint: string) => string);\n debug?: (message: string) => void;\n /** @internal A DAVE implementation in place of `@snazzah/davey` (tests). */\n daveModule?: Awaited<ReturnType<typeof loadDave>>;\n /** @internal Resume backoff (tests): attempts before giving up, first delay and cap in ms. */\n resume?: { attempts?: number; delay?: number; maxDelay?: number };\n}\n\n/** Resume attempts after a recoverable close before the session is closed for good. */\nconst RESUME_ATTEMPTS = 5;\n/** First resume delay; it doubles per attempt (with jitter) up to {@link RESUME_MAX_DELAY_MS}. */\nconst RESUME_DELAY_MS = 250;\nconst RESUME_MAX_DELAY_MS = 10_000;\n\n/** What a {@link VoiceNetworking} reports. */\nexport interface VoiceNetworkingHandlers {\n state?(state: NetworkingState, previous: NetworkingState): void;\n /** The session closed for good (not resumable). */\n close?(code: number, reason: string): void;\n error?(error: Error): void;\n /** An Opus frame from another user, decrypted. */\n audio?(userId: string, frame: Uint8Array): void;\n /** Op 5 from another user: their SSRC. */\n speaking?(userId: string, ssrc: number): void;\n /** Op 13. */\n clientDisconnect?(userId: string): void;\n}\n\n/**\n * One voice server session: the voice gateway handshake (v8), IP discovery,\n * transport encryption, DAVE, and sending and receiving RTP packets. A new\n * server (VOICE_SERVER_UPDATE) needs a new instance; a recoverable close\n * (network loss, voice server crash) resumes on its own.\n */\nexport class VoiceNetworking {\n public state: NetworkingState = \"opening\";\n /** Our SSRC, from READY. */\n public ssrc = 0;\n /** The negotiated encryption mode, once ready. */\n public mode?: VoiceEncryptionMode;\n readonly #info: VoiceServerInfo;\n readonly #options: VoiceNetworkingOptions;\n readonly #handlers: VoiceNetworkingHandlers;\n #gateway: VoiceGateway;\n #udp?: VoiceUdp;\n #cipher?: PacketCipher;\n #dave?: DaveSession;\n #maxDave = 0;\n #daveModule: Awaited<ReturnType<typeof loadDave>> = null;\n #sequence = Math.floor(Math.random() * 0x10000);\n #timestamp = Math.floor(Math.random() * 0x100000000);\n #speaking = false;\n #resumeAttempts = 0;\n #resumeTimer?: ReturnType<typeof setTimeout>;\n /** An outgoing frame failed to encrypt; reported once until one succeeds. */\n #encryptFailing = false;\n readonly #users = new Map<number, string>();\n readonly #connected = new Set<string>();\n\n public constructor(\n info: VoiceServerInfo,\n handlers: VoiceNetworkingHandlers = {},\n options: VoiceNetworkingOptions = {},\n ) {\n this.#info = info;\n this.#handlers = handlers;\n this.#options = options;\n this.#gateway = this.#openGateway();\n }\n\n /** Heartbeat round trip in ms, or -1. */\n public get ping(): number {\n return this.#gateway.ping;\n }\n\n /** The DAVE session, when Discord negotiated one. */\n public get dave(): DaveSession | undefined {\n return this.#dave;\n }\n\n /** User IDs in the channel, from ops 11 and 13. */\n public get connectedUsers(): ReadonlySet<string> {\n return this.#connected;\n }\n\n #debug(message: string): void {\n this.#options.debug?.(message);\n }\n\n #setState(next: NetworkingState): void {\n if (this.state === next) return;\n const previous = this.state;\n this.state = next;\n this.#handlers.state?.(next, previous);\n }\n\n #error(error: unknown): void {\n this.#handlers.error?.(\n error instanceof Error ? error : new VoiceError(String(error)),\n );\n }\n\n #openGateway(sequence?: number): VoiceGateway {\n return new VoiceGateway(\n typeof this.#options.url === \"function\"\n ? this.#options.url(this.#info.endpoint)\n : (this.#options.url ?? voiceGatewayURL(this.#info.endpoint)),\n {\n open: () => void this.#onOpen(),\n packet: (packet) => this.#onPacket(packet),\n binary: (packet) => this.#onBinary(packet),\n close: (code, reason) => this.#onClose(code, reason),\n error: (error) => this.#error(error),\n },\n { factory: this.#options.socketFactory, sequence },\n );\n }\n\n async #onOpen(): Promise<void> {\n const { guildId, userId, sessionId, token } = this.#info;\n if (this.state === \"resuming\") {\n this.#gateway.sendJSON({\n op: VoiceOpcodes.Resume,\n d: {\n server_id: guildId,\n session_id: sessionId,\n token,\n seq_ack: this.#gateway.sequence,\n },\n });\n return;\n }\n if (this.state !== \"opening\") return;\n this.#daveModule =\n this.#options.dave === false\n ? null\n : (this.#options.daveModule ?? (await loadDave()));\n this.#maxDave = this.#daveModule?.DAVE_PROTOCOL_VERSION ?? 0;\n if (this.state !== \"opening\") return;\n this.#gateway.sendJSON({\n op: VoiceOpcodes.Identify,\n d: {\n server_id: guildId,\n user_id: userId,\n session_id: sessionId,\n token,\n max_dave_protocol_version: this.#maxDave,\n },\n });\n this.#setState(\"identifying\");\n }\n\n #onPacket(packet: VoicePacket): void {\n const d = (packet.d ?? {}) as Record<string, unknown>;\n switch (packet.op) {\n case VoiceOpcodes.Ready:\n if (this.state === \"identifying\") void this.#onReady(d);\n return;\n case VoiceOpcodes.SessionDescription:\n if (this.state === \"selecting\") this.#onSession(d);\n return;\n case VoiceOpcodes.Resumed:\n if (this.state === \"resuming\") {\n this.#speaking = false;\n this.#resumeAttempts = 0;\n this.#setState(\"ready\");\n }\n return;\n case VoiceOpcodes.Speaking:\n if (\n typeof d.user_id === \"string\" &&\n typeof d.ssrc === \"number\"\n ) {\n this.#users.set(d.ssrc, d.user_id);\n this.#handlers.speaking?.(d.user_id, d.ssrc);\n }\n return;\n case VoiceOpcodes.ClientsConnect:\n if (Array.isArray(d.user_ids))\n for (const id of d.user_ids)\n if (typeof id === \"string\") this.#connected.add(id);\n return;\n case VoiceOpcodes.ClientDisconnect:\n if (typeof d.user_id === \"string\") {\n this.#connected.delete(d.user_id);\n for (const [ssrc, user] of this.#users)\n if (user === d.user_id) this.#users.delete(ssrc);\n this.#handlers.clientDisconnect?.(d.user_id);\n }\n return;\n }\n const dave = this.#dave;\n if (!dave || (this.state !== \"ready\" && this.state !== \"resuming\"))\n return;\n const transitionId = Number(d.transition_id ?? 0);\n if (packet.op === VoiceOpcodes.DavePrepareTransition) {\n if (\n dave.prepareTransition(\n transitionId,\n Number(d.protocol_version ?? 0),\n )\n )\n this.#gateway.sendJSON({\n op: VoiceOpcodes.DaveTransitionReady,\n d: { transition_id: transitionId },\n });\n } else if (packet.op === VoiceOpcodes.DaveExecuteTransition)\n dave.executeTransition(transitionId);\n else if (packet.op === VoiceOpcodes.DavePrepareEpoch)\n dave.prepareEpoch(\n Number(d.epoch ?? 0),\n Number(d.protocol_version ?? 0),\n );\n }\n\n #onBinary(packet: VoiceBinaryPacket): void {\n const dave = this.#dave;\n if (!dave || this.state !== \"ready\") return;\n try {\n switch (packet.op) {\n case VoiceOpcodes.DaveMlsExternalSender:\n dave.setExternalSender(packet.payload);\n return;\n case VoiceOpcodes.DaveMlsProposals: {\n const reply = dave.processProposals(\n packet.payload,\n this.#connected,\n );\n if (reply)\n this.#gateway.sendBinary(\n VoiceOpcodes.DaveMlsCommitWelcome,\n reply,\n );\n return;\n }\n case VoiceOpcodes.DaveMlsAnnounceCommitTransition:\n case VoiceOpcodes.DaveMlsWelcome: {\n const { transitionId, ok } = dave.process(\n packet.op === VoiceOpcodes.DaveMlsWelcome\n ? \"welcome\"\n : \"commit\",\n packet.payload,\n );\n if (ok && transitionId !== 0)\n this.#gateway.sendJSON({\n op: VoiceOpcodes.DaveTransitionReady,\n d: { transition_id: transitionId },\n });\n return;\n }\n }\n } catch (error) {\n this.#error(error);\n }\n }\n\n async #onReady(d: Record<string, unknown>): Promise<void> {\n const { ssrc, ip, port, modes } = d as {\n ssrc: number;\n ip: string;\n port: number;\n modes: string[];\n };\n this.ssrc = ssrc;\n this.#setState(\"discovering\");\n try {\n const mode = chooseEncryptionMode(\n Array.isArray(modes) ? modes : [],\n );\n const udp = await VoiceUdp.open(ip, port, this.#options.udpFactory);\n if (this.state !== \"discovering\") return void udp.close();\n this.#udp = udp;\n udp.onPacket((packet) => this.#receive(packet));\n const local = await udp.discover(ssrc);\n if (this.state !== \"discovering\") return;\n this.#gateway.sendJSON({\n op: VoiceOpcodes.SelectProtocol,\n d: {\n protocol: \"udp\",\n data: { address: local.ip, port: local.port, mode },\n },\n });\n this.#setState(\"selecting\");\n } catch (error) {\n // destroy() during the handshake: the failure is ours, not news.\n if (this.state === \"closed\") return;\n this.#error(error);\n this.destroy();\n this.#handlers.close?.(\n 4000,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n\n #onSession(d: Record<string, unknown>): void {\n const key = d.secret_key;\n if (!Array.isArray(key) || typeof d.mode !== \"string\") return;\n try {\n this.#cipher = new PacketCipher(\n d.mode as VoiceEncryptionMode,\n Uint8Array.from(key as number[]),\n );\n } catch (error) {\n this.#error(error);\n return;\n }\n this.mode = this.#cipher.mode;\n const daveVersion = Number(d.dave_protocol_version ?? 0);\n const module = this.#daveModule;\n if (module && this.#maxDave > 0) {\n this.#dave = new DaveSession(\n module,\n daveVersion,\n this.#info.userId,\n this.#info.channelId,\n {\n keyPackage: (payload) =>\n this.#gateway.sendBinary(\n VoiceOpcodes.DaveMlsKeyPackage,\n payload,\n ),\n invalidTransition: (transitionId) =>\n this.#gateway.sendJSON({\n op: VoiceOpcodes.DaveMlsInvalidCommitWelcome,\n d: { transition_id: transitionId },\n }),\n debug: (message) => this.#debug(message),\n },\n );\n }\n this.#setState(\"ready\");\n this.#dave?.reinit();\n }\n\n #onClose(code: number, reason: string): void {\n if (this.state === \"closed\") return;\n if (\n canResumeVoice(code) &&\n (this.state === \"ready\" || this.state === \"resuming\")\n ) {\n const resume = this.#options.resume ?? {};\n if (this.#resumeAttempts < (resume.attempts ?? RESUME_ATTEMPTS)) {\n // Exponential backoff with jitter: a voice server that is gone\n // (every socket closes at once with 1006) must not become a busy loop.\n const base = Math.min(\n (resume.delay ?? RESUME_DELAY_MS) *\n 2 ** this.#resumeAttempts,\n resume.maxDelay ?? RESUME_MAX_DELAY_MS,\n );\n const delay = Math.round(base / 2 + (Math.random() * base) / 2);\n this.#resumeAttempts++;\n this.#debug(\n `Voice gateway closed (${code}); resuming in ${delay} ms (attempt ${this.#resumeAttempts}).`,\n );\n this.#setState(\"resuming\");\n const sequence = this.#gateway.sequence;\n this.#resumeTimer = setTimeout(() => {\n this.#resumeTimer = undefined;\n if (this.state === \"resuming\")\n this.#gateway = this.#openGateway(sequence);\n }, delay);\n (this.#resumeTimer as { unref?: () => void }).unref?.();\n return;\n }\n this.destroy();\n this.#handlers.close?.(\n code,\n `${reason ? `${reason} ` : \"\"}Could not resume the voice session after ${this.#resumeAttempts} attempts.`,\n );\n return;\n }\n this.destroy();\n const hint =\n code === VoiceCloseCodes.DaveProtocolRequired && this.#maxDave === 0\n ? \" Discord requires end-to-end encryption (DAVE): install @snazzah/davey.\"\n : \"\";\n this.#handlers.close?.(code, `${reason}${hint}`.trim());\n }\n\n #receive(packet: Uint8Array): void {\n const cipher = this.#cipher;\n if (!cipher) return;\n const header = parseRtpHeader(packet);\n if (!header || header.payloadType !== RTP_OPUS_PAYLOAD_TYPE) return;\n const userId = this.#users.get(header.ssrc);\n if (!userId) return;\n const opened = cipher.open(packet);\n if (!opened) return;\n const frame = this.#dave\n ? this.#dave.decrypt(opened.payload, userId)\n : opened.payload;\n if (frame) this.#handlers.audio?.(userId, frame);\n }\n\n /** Sends op 5. Only sends when the flag changes. */\n public setSpeaking(speaking: boolean, flags = 1): void {\n if (this.state !== \"ready\" || this.#speaking === speaking) return;\n this.#speaking = speaking;\n this.#gateway.sendJSON({\n op: VoiceOpcodes.Speaking,\n d: { speaking: speaking ? flags : 0, delay: 0, ssrc: this.ssrc },\n });\n }\n\n /**\n * Encrypts one 20 ms Opus frame (DAVE, then transport) and sends it.\n * Sequence and timestamp advance by one frame either way. A frame DAVE\n * cannot end-to-end encrypt yet (the MLS group is not ready) is dropped.\n * @returns Whether it was sent.\n */\n public sendFrame(frame: Uint8Array): boolean {\n const cipher = this.#cipher;\n const udp = this.#udp;\n if (this.state !== \"ready\" || !cipher || !udp) return false;\n this.setSpeaking(true);\n const header = rtpHeader(this.#sequence, this.#timestamp, this.ssrc);\n this.#sequence = (this.#sequence + 1) & 0xffff;\n this.#timestamp = (this.#timestamp + FRAME_SAMPLES) >>> 0;\n let payload: Uint8Array | null = frame;\n if (this.#dave)\n try {\n payload = this.#dave.encrypt(frame);\n this.#encryptFailing = false;\n } catch (error) {\n if (!this.#encryptFailing)\n this.#error(\n new VoiceError(\n `DAVE could not encrypt a frame; frames are dropped until it can: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n ),\n );\n this.#encryptFailing = true;\n return false;\n }\n // Never sent unencrypted while end-to-end encryption is required.\n if (!payload) return false;\n return udp.send(cipher.seal(header, payload));\n }\n\n /** Ends the session: gateway, UDP socket, DAVE state. Safe to call twice. */\n public destroy(): void {\n if (this.state === \"closed\") return;\n this.#setState(\"closed\");\n if (this.#resumeTimer) clearTimeout(this.#resumeTimer);\n this.#resumeTimer = undefined;\n this.#gateway.close(1000, \"Voice session ended.\");\n this.#udp?.close();\n this.#udp = undefined;\n this.#dave?.destroy();\n this.#dave = undefined;\n this.#cipher = undefined;\n this.#users.clear();\n this.#connected.clear();\n }\n}\n",
|
|
15
|
+
"type AnyListener = (...args: never[]) => unknown;\n\n/** A small typed event emitter: listener failures are isolated, nothing is async. */\nexport class Emitter<E extends { [K in keyof E]: unknown[] }> {\n readonly #listeners = new Map<keyof E, Set<AnyListener>>();\n\n /** Adds a listener. @throws {TypeError} If it is not a function. */\n public on<K extends keyof E>(\n event: K,\n listener: (...args: E[K]) => unknown,\n ): this {\n if (typeof listener !== \"function\")\n throw new TypeError(\"Listener must be a function.\");\n let set = this.#listeners.get(event);\n if (!set) this.#listeners.set(event, (set = new Set()));\n set.add(listener as AnyListener);\n return this;\n }\n\n /** Removes a listener. */\n public off<K extends keyof E>(\n event: K,\n listener: (...args: E[K]) => unknown,\n ): this {\n this.#listeners.get(event)?.delete(listener as AnyListener);\n return this;\n }\n\n /** Calls the listeners of `event`; one that throws does not stop the others. */\n protected emit<K extends keyof E>(event: K, ...args: E[K]): void {\n const set = this.#listeners.get(event);\n if (!set) return;\n for (const listener of [...set])\n try {\n void (listener as (...a: E[K]) => unknown)(...args);\n } catch {\n // Listener failures are isolated.\n }\n }\n\n /** Drops every listener. */\n protected removeAllListeners(): void {\n this.#listeners.clear();\n }\n}\n",
|
|
16
|
+
"import { VoiceError } from \"./protocol.js\";\n\nconst CAPTURE = [0x4f, 0x67, 0x67, 0x53]; // \"OggS\"\nconst OPUS_HEAD = \"OpusHead\";\nconst OPUS_TAGS = \"OpusTags\";\n/** Largest Ogg page: 27-byte header, 255 segment sizes, 255 segments of 255 bytes. */\nconst MAX_PAGE = 27 + 255 + 255 * 255;\n/** Largest packet kept while it spans pages; an Opus packet is far smaller. */\nconst MAX_PACKET = 64 * 1024;\n\nfunction startsWith(bytes: Uint8Array, text: string): boolean {\n if (bytes.length < text.length) return false;\n for (let i = 0; i < text.length; i++)\n if (bytes[i] !== text.charCodeAt(i)) return false;\n return true;\n}\n\nfunction findCapture(buffer: Uint8Array, from: number): number {\n for (let i = from; i + 4 <= buffer.length; i++)\n if (\n buffer[i] === CAPTURE[0] &&\n buffer[i + 1] === CAPTURE[1] &&\n buffer[i + 2] === CAPTURE[2] &&\n buffer[i + 3] === CAPTURE[3]\n )\n return i;\n return -1;\n}\n\n/**\n * Reads Opus packets out of an Ogg/Opus stream without decoding them (the\n * passthrough path: no Opus library, no re-encoding). Skips the OpusHead and\n * OpusTags headers. Memory is bounded by one page and one packet.\n * @throws {VoiceError} For an Ogg stream that is not 48 kHz Opus with at most two channels.\n */\nexport async function* demuxOggOpus(\n chunks: AsyncIterable<Uint8Array>,\n): AsyncGenerator<Uint8Array> {\n let buffer: Uint8Array = new Uint8Array(0);\n let partial: Uint8Array[] = [];\n let partialSize = 0;\n let sawHead = false;\n /** Bytes read without finding any Ogg page. */\n let skipped = 0;\n\n const take = (bytes: Uint8Array): Uint8Array | undefined => {\n // A segment shorter than 255 bytes ends the packet.\n if (partial.length === 0) return bytes;\n partial.push(bytes);\n const out = new Uint8Array(partialSize + bytes.length);\n let offset = 0;\n for (const part of partial) {\n out.set(part, offset);\n offset += part.length;\n }\n partial = [];\n partialSize = 0;\n return out;\n };\n\n for await (const chunk of chunks) {\n const merged = new Uint8Array(buffer.length + chunk.length);\n merged.set(buffer, 0);\n merged.set(chunk, buffer.length);\n buffer = merged;\n let offset = 0;\n for (;;) {\n const start = findCapture(buffer, offset);\n if (start === -1) {\n // Keep a possible partial capture pattern for the next chunk.\n offset = Math.max(offset, buffer.length - 3);\n break;\n }\n if (buffer.length < start + 27) {\n offset = start;\n break;\n }\n const segments = buffer[start + 26]!;\n const dataStart = start + 27 + segments;\n if (buffer.length < dataStart) {\n offset = start;\n break;\n }\n let size = 0;\n for (let i = 0; i < segments; i++) size += buffer[start + 27 + i]!;\n if (buffer.length < dataStart + size) {\n offset = start;\n break;\n }\n let cursor = dataStart;\n for (let i = 0; i < segments; i++) {\n const length = buffer[start + 27 + i]!;\n const segment = buffer.slice(cursor, cursor + length);\n cursor += length;\n if (length === 255) {\n partial.push(segment);\n partialSize += length;\n if (partialSize > MAX_PACKET)\n throw new VoiceError(\n \"An Ogg packet is too large to be Opus audio.\",\n );\n continue;\n }\n const packet = take(segment);\n if (!packet || packet.length === 0) continue;\n if (startsWith(packet, OPUS_HEAD)) {\n const channels = packet[9] ?? 0;\n if (channels < 1 || channels > 2)\n throw new VoiceError(\n `Unsupported Opus channel count: ${channels}.`,\n );\n sawHead = true;\n continue;\n }\n if (startsWith(packet, OPUS_TAGS)) continue;\n if (!sawHead)\n throw new VoiceError(\n \"The Ogg stream does not carry Opus audio.\",\n );\n yield packet;\n }\n offset = cursor;\n }\n if (!sawHead && findCapture(buffer, 0) === -1) skipped += offset;\n buffer = buffer.slice(offset);\n if (buffer.length > MAX_PAGE || skipped > MAX_PAGE)\n throw new VoiceError(\"The input is not an Ogg stream.\");\n }\n if (!sawHead && (skipped > 0 || buffer.length > 0))\n throw new VoiceError(\"The input is not an Ogg/Opus stream.\");\n}\n\nconst CRC_TABLE = (() => {\n const table = new Uint32Array(256);\n for (let i = 0; i < 256; i++) {\n let r = i << 24;\n for (let j = 0; j < 8; j++)\n r = r & 0x80000000 ? (r << 1) ^ 0x04c11db7 : r << 1;\n table[i] = r >>> 0;\n }\n return table;\n})();\n\nfunction oggCrc(bytes: Uint8Array): number {\n let crc = 0;\n for (const byte of bytes)\n crc = ((crc << 8) ^ CRC_TABLE[((crc >>> 24) ^ byte) & 0xff]!) >>> 0;\n return crc;\n}\n\n/**\n * Writes Opus packets as an Ogg/Opus stream (48 kHz, stereo), which players\n * and FFmpeg read. Each packet counts as 20 ms (960 samples), as Discord sends.\n * Pages hold up to 50 packets (one second).\n */\nexport class OggOpusWriter {\n readonly #serial: number;\n #sequence = 0;\n #granule = 0n;\n #packets: Uint8Array[] = [];\n #lacing = 0;\n #ended = false;\n\n public constructor(serial = (Math.random() * 0x100000000) >>> 0) {\n this.#serial = serial;\n }\n\n /** The two header pages (OpusHead, OpusTags). Write them first. */\n public header(vendor = \"lunibee\"): Uint8Array {\n const head = new Uint8Array(19);\n head.set(new TextEncoder().encode(OPUS_HEAD));\n const view = new DataView(head.buffer);\n head[8] = 1; // version\n head[9] = 2; // channels\n view.setUint16(10, 0, true); // pre-skip\n view.setUint32(12, 48_000, true);\n const vendorBytes = new TextEncoder().encode(vendor);\n const tags = new Uint8Array(8 + 4 + vendorBytes.length + 4);\n tags.set(new TextEncoder().encode(OPUS_TAGS));\n const tagsView = new DataView(tags.buffer);\n tagsView.setUint32(8, vendorBytes.length, true);\n tags.set(vendorBytes, 12);\n return concat([\n this.#page([head], 0x02, 0n),\n this.#page([tags], 0, 0n),\n ]);\n }\n\n /** Adds one packet. @returns A page once 50 packets are buffered, else an empty array. */\n public write(packet: Uint8Array): Uint8Array {\n if (this.#ended) throw new VoiceError(\"The Ogg stream has ended.\");\n const lacing = Math.floor(packet.length / 255) + 1;\n if (lacing > 255)\n throw new VoiceError(\"An Opus packet is too large for one page.\");\n // A page has at most 255 segments: flush first when this one would not fit.\n const before = this.#lacing + lacing > 255 ? this.flush() : undefined;\n this.#packets.push(packet);\n this.#lacing += lacing;\n this.#granule += 960n;\n const after =\n this.#packets.length >= 50 ? this.flush() : new Uint8Array(0);\n return before ? concat([before, after]) : after;\n }\n\n /** Writes the buffered packets as a page (empty array when there are none). */\n public flush(): Uint8Array {\n if (this.#packets.length === 0) return new Uint8Array(0);\n const packets = this.#packets;\n this.#packets = [];\n this.#lacing = 0;\n return this.#page(packets, 0, this.#granule);\n }\n\n /** Writes the last page (end-of-stream flag). Further writes throw. */\n public end(): Uint8Array {\n if (this.#ended) return new Uint8Array(0);\n this.#ended = true;\n const packets = this.#packets;\n this.#packets = [];\n this.#lacing = 0;\n return this.#page(packets, 0x04, this.#granule);\n }\n\n #page(packets: Uint8Array[], flags: number, granule: bigint): Uint8Array {\n const lacing: number[] = [];\n for (const packet of packets) {\n let left = packet.length;\n while (left >= 255) {\n lacing.push(255);\n left -= 255;\n }\n lacing.push(left);\n }\n const body = concat(packets);\n const page = new Uint8Array(27 + lacing.length + body.length);\n const view = new DataView(page.buffer);\n page.set(CAPTURE);\n page[5] = flags;\n view.setBigUint64(6, granule, true);\n view.setUint32(14, this.#serial, true);\n view.setUint32(18, this.#sequence++, true);\n page[26] = lacing.length;\n page.set(lacing, 27);\n page.set(body, 27 + lacing.length);\n view.setUint32(22, oggCrc(page), true);\n return page;\n }\n}\n\nfunction concat(parts: Uint8Array[]): Uint8Array {\n let length = 0;\n for (const part of parts) length += part.length;\n const out = new Uint8Array(length);\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n return out;\n}\n",
|
|
17
|
+
"import { OggOpusWriter } from \"./ogg.js\";\nimport { FRAME_DURATION_MS, SILENCE_FRAME } from \"./protocol.js\";\n\n/** When a {@link VoiceReceiver.subscribe} stream ends. */\nexport type ReceiveEnd =\n | { behavior: \"manual\" }\n /** After `duration` ms with no audio (silence frames count as none). Default, 1,000 ms. */\n | { behavior: \"silence\"; duration?: number };\n\n/** Options for {@link VoiceReceiver.subscribe}. */\nexport interface ReceiveOptions {\n end?: ReceiveEnd;\n /** Frames kept for a slow reader; newer frames are dropped beyond it. Default 50 (1 s). */\n highWaterMark?: number;\n}\n\n/** Options for {@link VoiceReceiver.record}. */\nexport interface RecordOptions {\n /** When the recording ends. Default `{ behavior: \"manual\" }`: on `unsubscribe()`, cancel, or when the connection ends. */\n end?: ReceiveEnd;\n /** Bytes kept for a slow reader; audio beyond it is replaced by silence. Default 1 MiB. */\n highWaterMark?: number;\n}\n\ninterface Subscription {\n end: ReceiveEnd;\n timer?: ReturnType<typeof setTimeout>;\n deliver(frame: Uint8Array): void;\n close(): void;\n}\n\n/** Gaps longer than this are filled with silence; shorter ones are network jitter. */\nconst GAP_MS = 60;\n/** The longest gap one packet fills: an hour of silence frames (about 720 KB). */\nconst MAX_GAP_FRAMES = 3_600_000 / FRAME_DURATION_MS;\n\nfunction isSilence(frame: Uint8Array): boolean {\n return (\n frame.length === SILENCE_FRAME.length &&\n frame.every((byte, i) => byte === SILENCE_FRAME[i])\n );\n}\n\n/**\n * Receives other users' audio (low level): decrypted Opus packets per user.\n * SSRCs are mapped to users from op 5; decoding is up to you (`createOpusCodec`).\n */\nexport class VoiceReceiver {\n readonly #subscriptions = new Map<string, Set<Subscription>>();\n readonly #ssrcs = new Map<string, number>();\n readonly #speaking = new Map<string, ReturnType<typeof setTimeout>>();\n readonly #listeners = new Map<\n \"start\" | \"end\",\n Set<(userId: string) => void>\n >();\n\n /** The SSRC Discord assigned to a user, once they spoke. */\n public ssrcOf(userId: string): number | undefined {\n return this.#ssrcs.get(userId);\n }\n\n /** Users who sent audio in the last 100 ms. */\n public get speaking(): ReadonlySet<string> {\n return new Set(this.#speaking.keys());\n }\n\n /** Listens for a user starting or stopping to send audio. */\n public on(\n event: \"start\" | \"end\",\n listener: (userId: string) => void,\n ): this {\n let set = this.#listeners.get(event);\n if (!set) this.#listeners.set(event, (set = new Set()));\n set.add(listener);\n return this;\n }\n\n public off(\n event: \"start\" | \"end\",\n listener: (userId: string) => void,\n ): this {\n this.#listeners.get(event)?.delete(listener);\n return this;\n }\n\n #emit(event: \"start\" | \"end\", userId: string): void {\n for (const listener of this.#listeners.get(event) ?? [])\n try {\n listener(userId);\n } catch {\n // Listener failures are isolated.\n }\n }\n\n /**\n * A stream of `userId`'s Opus packets. It ends after a second without\n * audio unless `end.behavior` is `\"manual\"`; cancelling it unsubscribes.\n */\n public subscribe(\n userId: string,\n options: ReceiveOptions = {},\n ): ReadableStream<Uint8Array> {\n const end = options.end ?? { behavior: \"silence\" };\n let subscription: Subscription | undefined;\n return new ReadableStream<Uint8Array>(\n {\n start: (controller) => {\n subscription = {\n end,\n deliver: (frame) => {\n // A reader that falls behind loses the newest frames, not memory.\n if ((controller.desiredSize ?? 1) > 0)\n controller.enqueue(frame);\n },\n close: () => controller.close(),\n };\n this.#add(userId, subscription);\n },\n cancel: () => {\n if (subscription) this.#remove(userId, subscription);\n },\n },\n { highWaterMark: options.highWaterMark ?? 50 },\n );\n }\n\n /**\n * Records `userId` as an Ogg/Opus stream (48 kHz stereo) that players and\n * FFmpeg read: write it to a file with `Bun.write(path, new Response(stream))`.\n * The audio is not re-encoded. Time the user is silent is kept as silence,\n * counted from the start of the recording, so recordings of several users\n * started together line up.\n */\n public record(\n userId: string,\n options: RecordOptions = {},\n ): ReadableStream<Uint8Array> {\n const end = options.end ?? { behavior: \"manual\" };\n const writer = new OggOpusWriter();\n let subscription: Subscription | undefined;\n return new ReadableStream<Uint8Array>(\n {\n start: (controller) => {\n const emit = (bytes: Uint8Array): void => {\n if (bytes.length > 0) controller.enqueue(bytes);\n };\n emit(writer.header());\n let last = performance.now();\n subscription = {\n end,\n deliver: (frame) => {\n // Full: drop the frame; the gap becomes silence once there is room.\n if ((controller.desiredSize ?? 1) <= 0) return;\n const now = performance.now();\n const gap = now - last;\n if (gap > GAP_MS) {\n const missing = Math.min(\n Math.round(gap / FRAME_DURATION_MS) - 1,\n MAX_GAP_FRAMES,\n );\n // Bounded by highWaterMark like audio: a long\n // gap is cut short rather than queued whole.\n for (\n let i = 0;\n i < missing &&\n (controller.desiredSize ?? 1) > 0;\n i++\n )\n emit(writer.write(SILENCE_FRAME));\n }\n last = now;\n emit(writer.write(frame));\n },\n close: () => {\n emit(writer.end());\n controller.close();\n },\n };\n this.#add(userId, subscription);\n },\n cancel: () => {\n if (subscription) this.#remove(userId, subscription);\n },\n },\n new ByteLengthQueuingStrategy({\n highWaterMark: options.highWaterMark ?? 1024 * 1024,\n }),\n );\n }\n\n #add(userId: string, subscription: Subscription): void {\n let set = this.#subscriptions.get(userId);\n if (!set) this.#subscriptions.set(userId, (set = new Set()));\n set.add(subscription);\n this.#arm(userId, subscription);\n }\n\n /** Ends every stream of `userId`. @returns Whether there was one. */\n public unsubscribe(userId: string): boolean {\n const set = this.#subscriptions.get(userId);\n if (!set) return false;\n for (const subscription of [...set]) this.#close(userId, subscription);\n return true;\n }\n\n #arm(userId: string, subscription: Subscription): void {\n if (subscription.end.behavior !== \"silence\") return;\n if (subscription.timer) clearTimeout(subscription.timer);\n subscription.timer = setTimeout(\n () => this.#close(userId, subscription),\n subscription.end.duration ?? 1_000,\n );\n }\n\n #remove(userId: string, subscription: Subscription): void {\n if (subscription.timer) clearTimeout(subscription.timer);\n const set = this.#subscriptions.get(userId);\n set?.delete(subscription);\n if (set?.size === 0) this.#subscriptions.delete(userId);\n }\n\n #close(userId: string, subscription: Subscription): void {\n this.#remove(userId, subscription);\n try {\n subscription.close();\n } catch {\n // Already closed or cancelled.\n }\n }\n\n /** @internal Op 5 told us a user's SSRC. */\n public mapUser(userId: string, ssrc: number): void {\n this.#ssrcs.set(userId, ssrc);\n }\n\n /** @internal Op 13: a user left. */\n public forgetUser(userId: string): void {\n this.#ssrcs.delete(userId);\n this.unsubscribe(userId);\n }\n\n /** @internal A decrypted frame arrived from `userId`. */\n public push(userId: string, frame: Uint8Array): void {\n const silent = isSilence(frame);\n if (!silent) this.#markSpeaking(userId);\n const set = this.#subscriptions.get(userId);\n if (!set) return;\n for (const subscription of set) {\n if (!silent) this.#arm(userId, subscription);\n try {\n subscription.deliver(frame);\n } catch {\n // Closed by the consumer.\n }\n }\n }\n\n #markSpeaking(userId: string): void {\n const timer = this.#speaking.get(userId);\n if (timer) clearTimeout(timer);\n else this.#emit(\"start\", userId);\n this.#speaking.set(\n userId,\n setTimeout(() => {\n this.#speaking.delete(userId);\n this.#emit(\"end\", userId);\n }, 100),\n );\n }\n\n /** @internal Ends every stream and forgets every user (the connection left). */\n public close(): void {\n for (const [userId, set] of [...this.#subscriptions])\n for (const subscription of [...set])\n this.#close(userId, subscription);\n for (const timer of this.#speaking.values()) clearTimeout(timer);\n this.#speaking.clear();\n this.#ssrcs.clear();\n }\n}\n",
|
|
18
|
+
"import {\n VoiceNetworking,\n type NetworkingState,\n type VoiceNetworkingOptions,\n} from \"./networking.js\";\nimport type { AudioPlayer, AudioSink } from \"./player.js\";\nimport { Emitter } from \"./emitter.js\";\nimport { VoiceError } from \"./protocol.js\";\nimport { VoiceReceiver } from \"./receiver.js\";\n\n/** Where a {@link VoiceConnection} is. */\nexport const VoiceConnectionStatus = {\n /** Asked Discord to join (op 4); waiting for the voice state and server. */\n Signalling: \"signalling\",\n /** Connecting to the voice server. */\n Connecting: \"connecting\",\n /** Can send and receive audio. */\n Ready: \"ready\",\n /** Not in a channel (left, removed, timed out or failed). `rejoin()` brings it back. */\n Disconnected: \"disconnected\",\n /** Gone for good. */\n Destroyed: \"destroyed\",\n} as const;\nexport type VoiceConnectionStatus =\n (typeof VoiceConnectionStatus)[keyof typeof VoiceConnectionStatus];\n\n/** The bot's own VOICE_STATE_UPDATE, as the adapter forwards it. */\nexport interface VoiceStateData {\n guild_id?: string;\n channel_id: string | null;\n user_id: string;\n session_id: string;\n}\n\n/** VOICE_SERVER_UPDATE. `endpoint` is null while Discord moves the guild to another server. */\nexport interface VoiceServerData {\n guild_id: string;\n token: string;\n endpoint: string | null;\n}\n\n/** What a connection gives its adapter. */\nexport interface VoiceAdapterMethods {\n onVoiceStateUpdate(data: VoiceStateData): void;\n onVoiceServerUpdate(data: VoiceServerData): void;\n /** The adapter is gone (its client was destroyed): destroy without sending anything. */\n destroy(): void;\n}\n\n/** An op 4 (Voice State Update) payload. */\nexport interface VoiceStatePayload {\n op: 4;\n d: {\n guild_id: string;\n channel_id: string | null;\n self_mute: boolean;\n self_deaf: boolean;\n };\n}\n\n/** How a connection reaches the main Gateway: send op 4, and be told about voice events. */\nexport interface VoiceAdapter {\n /** Sends op 4 through the shard that owns the guild. @returns Whether it was sent. */\n sendPayload(payload: VoiceStatePayload): boolean;\n destroy(): void;\n}\n\n/** Builds an adapter for a guild. */\nexport type VoiceAdapterCreator = (\n methods: VoiceAdapterMethods,\n) => VoiceAdapter;\n\n/** Options for {@link joinVoiceChannel}. */\nexport interface JoinVoiceChannelOptions {\n guildId: string;\n channelId: string;\n selfMute?: boolean;\n selfDeaf?: boolean;\n adapterCreator: VoiceAdapterCreator;\n /** Ms to wait for Discord's voice events and the voice server. Default 15,000. */\n timeout?: number;\n /** Offer DAVE end-to-end encryption (needs `@snazzah/davey`). Default true. */\n dave?: boolean;\n debug?: (message: string) => void;\n /** Socket factories and URL override, for tests. */\n networking?: Pick<\n VoiceNetworkingOptions,\n \"socketFactory\" | \"udpFactory\" | \"url\" | \"daveModule\" | \"resume\"\n >;\n}\n\n/** Why a connection is disconnected. */\nexport interface DisconnectReason {\n /**\n * `\"left\"` (disconnect()), `\"removed\"` (moved out or kicked), `\"timeout\"`,\n * `\"closed\"` (the voice server closed the session), `\"unsent\"` (op 4 could\n * not be sent: the client is not connected).\n */\n reason: \"left\" | \"removed\" | \"timeout\" | \"closed\" | \"unsent\";\n /** The voice gateway close code, for `\"closed\"`. */\n code?: number;\n message?: string;\n}\n\n/** What a {@link VoiceConnection} emits. */\nexport interface VoiceConnectionEvents {\n /** Note the order: the new status first. */\n stateChange: [next: VoiceConnectionStatus, previous: VoiceConnectionStatus];\n error: [error: Error];\n debug: [message: string];\n}\n\n/** A player subscribed to a connection. */\nexport interface PlayerSubscription {\n readonly connection: VoiceConnection;\n readonly player: AudioPlayer;\n unsubscribe(): void;\n}\n\n/**\n * The bot's voice session in one guild: it asks Discord to join (op 4),\n * connects to the voice server when the voice state and server arrive,\n * reconnects when the server or channel changes, and sends a subscribed\n * player's audio. Create it with `client.voice.join()` or\n * {@link joinVoiceChannel}.\n */\nexport class VoiceConnection extends Emitter<VoiceConnectionEvents> {\n public status: VoiceConnectionStatus = \"signalling\";\n public readonly guildId: string;\n public channelId: string;\n public selfMute: boolean;\n public selfDeaf: boolean;\n /** Why it is disconnected, while it is. */\n public disconnectReason?: DisconnectReason;\n /** Incoming audio. */\n public readonly receiver = new VoiceReceiver();\n readonly #options: JoinVoiceChannelOptions;\n readonly #adapter: VoiceAdapter;\n #networking?: VoiceNetworking;\n #sessionId?: string;\n /** The channel the current voice session (networking) was opened for. */\n #sessionChannel?: string;\n #userId?: string;\n #token?: string;\n #endpoint?: string;\n #timer?: ReturnType<typeof setTimeout>;\n #leaving = false;\n #subscription?: PlayerSubscription;\n readonly #sink: AudioSink;\n\n public constructor(options: JoinVoiceChannelOptions) {\n super();\n if (!options.guildId?.trim())\n throw new TypeError(\"A guild ID is required.\");\n if (!options.channelId?.trim())\n throw new TypeError(\"A voice channel ID is required.\");\n if (typeof options.adapterCreator !== \"function\")\n throw new TypeError(\"An adapterCreator is required.\");\n this.#options = { ...options };\n this.guildId = options.guildId;\n this.channelId = options.channelId;\n this.selfMute = options.selfMute ?? false;\n this.selfDeaf = options.selfDeaf ?? false;\n const self = this;\n this.#sink = {\n get ready() {\n return self.status === \"ready\";\n },\n sendFrame: (frame) => this.#networking?.sendFrame(frame) ?? false,\n setSpeaking: (speaking) => this.#networking?.setSpeaking(speaking),\n };\n this.#adapter = options.adapterCreator({\n onVoiceStateUpdate: (data) => this.#onState(data),\n onVoiceServerUpdate: (data) => this.#onServer(data),\n destroy: () => this.destroy(false),\n });\n this.#signal();\n }\n\n /** Heartbeat round trip of the voice gateway in ms, or -1. */\n public get ping(): number {\n return this.#networking?.ping ?? -1;\n }\n\n /** The voice privacy code (DAVE) users can compare, or `null`. */\n public get voicePrivacyCode(): string | null {\n return this.#networking?.dave?.voicePrivacyCode ?? null;\n }\n\n /** Whether audio is end-to-end encrypted (DAVE) right now. */\n public get endToEndEncrypted(): boolean {\n return this.#networking?.dave?.active ?? false;\n }\n\n /** The subscribed player's subscription, if any. */\n public get subscription(): PlayerSubscription | undefined {\n return this.#subscription;\n }\n\n #debug(message: string): void {\n this.#options.debug?.(message);\n this.emit(\"debug\", message);\n }\n\n #setStatus(next: VoiceConnectionStatus, reason?: DisconnectReason): void {\n if (this.status === \"destroyed\") return;\n this.disconnectReason = next === \"disconnected\" ? reason : undefined;\n if (next === \"ready\" || next === \"disconnected\" || next === \"destroyed\")\n this.#clearTimer();\n if (this.status === next) return;\n const previous = this.status;\n this.status = next;\n this.emit(\"stateChange\", next, previous);\n this.#subscription?.player.refresh();\n }\n\n #clearTimer(): void {\n if (this.#timer) clearTimeout(this.#timer);\n this.#timer = undefined;\n }\n\n /** Sends op 4 for the current channel and waits for Discord, with the timeout. */\n #signal(): boolean {\n this.#leaving = false;\n this.#setStatus(\"signalling\");\n this.#clearTimer();\n const timeout = this.#options.timeout ?? 15_000;\n this.#timer = setTimeout(() => {\n this.#timer = undefined;\n if (this.status !== \"signalling\" && this.status !== \"connecting\")\n return;\n this.#networking?.destroy();\n this.#networking = undefined;\n this.#setStatus(\"disconnected\", {\n reason: \"timeout\",\n message: `No voice connection within ${timeout} ms.`,\n });\n this.emit(\n \"error\",\n new VoiceError(\n `Joining the voice channel timed out after ${timeout} ms.`,\n ),\n );\n }, timeout);\n (this.#timer as { unref?: () => void }).unref?.();\n if (this.#send(this.channelId)) return true;\n this.#setStatus(\"disconnected\", {\n reason: \"unsent\",\n message:\n \"The voice state update could not be sent: the client is not connected, or the guild is on another shard.\",\n });\n return false;\n }\n\n #send(channelId: string | null): boolean {\n try {\n return this.#adapter.sendPayload({\n op: 4,\n d: {\n guild_id: this.guildId,\n channel_id: channelId,\n self_mute: this.selfMute,\n self_deaf: this.selfDeaf,\n },\n });\n } catch (error) {\n this.emit(\n \"error\",\n error instanceof Error ? error : new VoiceError(String(error)),\n );\n return false;\n }\n }\n\n #onState(data: VoiceStateData): void {\n if (this.status === \"destroyed\") return;\n if (data.channel_id === null) {\n this.#networking?.destroy();\n this.#networking = undefined;\n this.receiver.close();\n this.#sessionChannel = undefined;\n this.#setStatus(\"disconnected\", {\n reason: this.#leaving ? \"left\" : \"removed\",\n });\n return;\n }\n // Compare with the channel the current voice session was opened for:\n // rejoin() has already updated channelId when the move was ours.\n const moved = data.channel_id !== this.#sessionChannel;\n const newSession = data.session_id !== this.#sessionId;\n this.#sessionId = data.session_id;\n this.#userId = data.user_id;\n this.channelId = data.channel_id;\n // A move (by us or a moderator) changes the DAVE group: reconnect.\n if (moved || newSession || !this.#networking) this.#connect();\n // op 4 for the channel the live session is already in: nothing to reconnect.\n else if (\n this.status === \"signalling\" &&\n this.#networking.state === \"ready\"\n )\n this.#setStatus(\"ready\");\n }\n\n #onServer(data: VoiceServerData): void {\n if (this.status === \"destroyed\") return;\n if (data.endpoint === null) {\n // Discord is moving the guild to another voice server; a new update follows.\n this.#networking?.destroy();\n this.#networking = undefined;\n if (this.status === \"ready\") this.#setStatus(\"connecting\");\n // The new server may never come: the same time limit as a reconnect.\n if (this.status === \"connecting\" && !this.#timer)\n this.#armReconnectTimeout();\n return;\n }\n this.#token = data.token;\n this.#endpoint = data.endpoint;\n this.#connect();\n }\n\n #connect(): void {\n const { channelId } = this;\n const sessionId = this.#sessionId;\n const userId = this.#userId;\n const token = this.#token;\n const endpoint = this.#endpoint;\n if (!sessionId || !userId || !token || !endpoint) return;\n this.#sessionChannel = channelId;\n this.#networking?.destroy();\n this.#setStatus(\"connecting\");\n // The join's timer covers a first connect; a reconnect gets its own.\n if (!this.#timer) this.#armReconnectTimeout();\n this.#debug(`Connecting to voice server ${endpoint}.`);\n const networking: VoiceNetworking = new VoiceNetworking(\n {\n guildId: this.guildId,\n channelId,\n userId,\n sessionId,\n token,\n endpoint,\n },\n {\n state: (state: NetworkingState) => {\n if (this.#networking !== networking) return;\n if (state === \"ready\") this.#setStatus(\"ready\");\n else if (state === \"resuming\") {\n this.#setStatus(\"connecting\");\n if (!this.#timer) this.#armReconnectTimeout();\n }\n },\n close: (code, reason) => {\n if (this.#networking !== networking) return;\n this.#networking = undefined;\n this.#setStatus(\"disconnected\", {\n reason: \"closed\",\n code,\n message: reason,\n });\n if (reason)\n this.emit(\n \"error\",\n new VoiceError(\n `Voice server closed the session (${code}): ${reason}`,\n ),\n );\n },\n // A replaced or destroyed session's late failures are not this connection's.\n error: (error) => {\n if (this.#networking === networking)\n this.emit(\"error\", error);\n },\n audio: (user, frame) => this.receiver.push(user, frame),\n speaking: (user, ssrc) => this.receiver.mapUser(user, ssrc),\n clientDisconnect: (user) => this.receiver.forgetUser(user),\n },\n {\n dave: this.#options.dave,\n debug: (message) => this.#debug(message),\n ...this.#options.networking,\n },\n );\n this.#networking = networking;\n }\n\n /** A reconnect (new server or channel) gets the same time limit as the first join. */\n #armReconnectTimeout(): void {\n const timeout = this.#options.timeout ?? 15_000;\n this.#timer = setTimeout(() => {\n this.#timer = undefined;\n if (this.status !== \"connecting\") return;\n this.#networking?.destroy();\n this.#networking = undefined;\n this.#setStatus(\"disconnected\", {\n reason: \"timeout\",\n message: `No voice server connection within ${timeout} ms.`,\n });\n }, timeout);\n (this.#timer as { unref?: () => void }).unref?.();\n }\n\n /**\n * Joins again, or moves to another channel, or changes mute/deaf.\n * @returns Whether op 4 was sent. @throws {VoiceError} If destroyed.\n */\n public rejoin(\n options: {\n channelId?: string;\n selfMute?: boolean;\n selfDeaf?: boolean;\n } = {},\n ): boolean {\n if (this.status === \"destroyed\")\n throw new VoiceError(\"The voice connection was destroyed.\");\n if (options.channelId !== undefined) {\n if (!options.channelId.trim())\n throw new TypeError(\"A voice channel ID is required.\");\n this.channelId = options.channelId;\n }\n if (options.selfMute !== undefined) this.selfMute = options.selfMute;\n if (options.selfDeaf !== undefined) this.selfDeaf = options.selfDeaf;\n // Same channel (or only mute/deaf) on a live connection: no reconnect needed.\n if (\n this.status === \"ready\" &&\n (options.channelId === undefined ||\n options.channelId === this.#sessionChannel)\n )\n return this.#send(this.channelId);\n return this.#signal();\n }\n\n /** Leaves the channel (op 4 with no channel); `rejoin()` can bring it back. @returns Whether op 4 was sent. */\n public disconnect(): boolean {\n if (this.status === \"destroyed\") return false;\n this.#leaving = true;\n this.#clearTimer();\n const sent = this.#send(null);\n this.#networking?.destroy();\n this.#networking = undefined;\n this.receiver.close();\n this.#setStatus(\"disconnected\", { reason: \"left\" });\n return sent;\n }\n\n /**\n * Leaves and releases everything: voice gateway, UDP socket, DAVE state,\n * receiver streams, timers and the player subscription.\n * @param leave Send op 4 to leave the channel (default true).\n */\n public destroy(leave = true): void {\n if (this.status === \"destroyed\") return;\n this.#clearTimer();\n if (leave) {\n this.#leaving = true;\n this.#send(null);\n }\n this.#networking?.destroy();\n this.#networking = undefined;\n this.receiver.close();\n this.#subscription?.unsubscribe();\n const previous = this.status;\n this.status = \"destroyed\";\n this.disconnectReason = undefined;\n this.emit(\"stateChange\", \"destroyed\", previous);\n try {\n this.#adapter.destroy();\n } catch {\n // Best effort.\n }\n this.removeAllListeners();\n }\n\n /** Plays `player` on this connection, replacing any other player. */\n public subscribe(player: AudioPlayer): PlayerSubscription {\n if (this.status === \"destroyed\")\n throw new VoiceError(\"The voice connection was destroyed.\");\n this.#subscription?.unsubscribe();\n const subscription: PlayerSubscription = {\n connection: this,\n player,\n unsubscribe: () => {\n player.detach(this.#sink);\n if (this.#subscription === subscription)\n this.#subscription = undefined;\n },\n };\n this.#subscription = subscription;\n player.attach(this.#sink);\n return subscription;\n }\n\n /** Sends op 5 now. Players do this on their own; use it for custom audio. */\n public setSpeaking(speaking: boolean): void {\n this.#networking?.setSpeaking(speaking);\n }\n\n /** Sends one 20 ms Opus frame now (for custom audio pipelines). @returns Whether it was sent. */\n public playOpusPacket(frame: Uint8Array): boolean {\n return this.#networking?.sendFrame(frame) ?? false;\n }\n}\n\nconst tracked = new Map<string, VoiceConnection>();\n\n/**\n * Joins (or moves to) a voice channel with your own adapter, and tracks the\n * connection per guild. With a Lunibee `Client`, use `client.voice.join()`.\n */\nexport function joinVoiceChannel(\n options: JoinVoiceChannelOptions,\n): VoiceConnection {\n const existing = tracked.get(options.guildId);\n if (existing && existing.status !== \"destroyed\") {\n existing.rejoin(options);\n return existing;\n }\n const connection = new VoiceConnection(options);\n tracked.set(options.guildId, connection);\n connection.on(\"stateChange\", (next) => {\n if (\n next === \"destroyed\" &&\n tracked.get(connection.guildId) === connection\n )\n tracked.delete(connection.guildId);\n });\n return connection;\n}\n\n/** The connection {@link joinVoiceChannel} tracks for a guild. */\nexport function getVoiceConnection(\n guildId: string,\n): VoiceConnection | undefined {\n return tracked.get(guildId);\n}\n\n/** What a {@link VoiceManager} needs from its client. */\nexport interface VoiceManagerClient {\n /** The bot's user ID, once logged in. */\n readonly userId: string | undefined;\n /** Whether op 4 for this guild can be sent now (connected, and the guild is on this shard). */\n canSendVoiceState?(guildId: string): boolean;\n /** Sends op 4 through the owning shard. @returns Whether it was sent. */\n sendVoiceState(\n guildId: string,\n channelId: string | null,\n options: { selfMute?: boolean; selfDeaf?: boolean },\n ): boolean;\n}\n\n/** Options for {@link VoiceManager.join}. */\nexport type VoiceJoinOptions = Omit<JoinVoiceChannelOptions, \"adapterCreator\">;\n\n/**\n * `client.voice`: one {@link VoiceConnection} per guild, wired to the\n * client's Gateway. The client forwards its own voice events and guild\n * removals here, and destroys every connection when it is destroyed.\n */\nexport class VoiceManager {\n readonly #client: VoiceManagerClient;\n readonly #connections = new Map<string, VoiceConnection>();\n readonly #adapters = new Map<string, VoiceAdapterMethods>();\n readonly #defaults: Partial<VoiceJoinOptions>;\n\n public constructor(\n client: VoiceManagerClient,\n defaults: Partial<VoiceJoinOptions> = {},\n ) {\n this.#client = client;\n this.#defaults = defaults;\n }\n\n /** Live connections by guild. */\n public get connections(): ReadonlyMap<string, VoiceConnection> {\n return this.#connections;\n }\n\n /** The connection for a guild, if any. */\n public get(guildId: string): VoiceConnection | undefined {\n return this.#connections.get(guildId);\n }\n\n /**\n * Joins a voice channel (or moves the guild's connection) and resolves\n * once audio can flow. @throws {VoiceError} If the guild is not on this\n * client's shard, or it is not ready within `timeout` (the connection is\n * then left disconnected; `rejoin()` or `leave()` it).\n */\n public join(options: VoiceJoinOptions): Promise<VoiceConnection> {\n const merged = { ...this.#defaults, ...options };\n if (\n this.#client.canSendVoiceState &&\n !this.#client.canSendVoiceState(options.guildId)\n )\n return Promise.reject(\n new VoiceError(\n \"Cannot send the voice state update: the client is not connected, or the guild is on another shard.\",\n ),\n );\n let connection = this.#connections.get(options.guildId);\n if (connection && connection.status !== \"destroyed\")\n connection.rejoin(merged);\n else {\n connection = new VoiceConnection({\n ...merged,\n adapterCreator: (methods) => {\n this.#adapters.set(options.guildId, methods);\n return {\n sendPayload: (payload) =>\n this.#client.sendVoiceState(\n payload.d.guild_id,\n payload.d.channel_id,\n {\n selfMute: payload.d.self_mute,\n selfDeaf: payload.d.self_deaf,\n },\n ),\n destroy: () => {\n if (this.#adapters.get(options.guildId) === methods)\n this.#adapters.delete(options.guildId);\n },\n };\n },\n });\n const created = connection;\n this.#connections.set(options.guildId, created);\n created.on(\"stateChange\", (next) => {\n if (\n next === \"destroyed\" &&\n this.#connections.get(created.guildId) === created\n )\n this.#connections.delete(created.guildId);\n });\n }\n return waitReady(connection, merged.timeout ?? 15_000);\n }\n\n /** Leaves a guild's channel and destroys its connection. @returns Whether there was one. */\n public leave(guildId: string): boolean {\n const connection = this.#connections.get(guildId);\n if (!connection) return false;\n connection.destroy();\n return true;\n }\n\n /** @internal The client's own VOICE_STATE_UPDATE. */\n public handleVoiceState(\n data: VoiceStateData & { guild_id?: string },\n ): void {\n if (!data.guild_id || data.user_id !== this.#client.userId) return;\n this.#adapters.get(data.guild_id)?.onVoiceStateUpdate(data);\n }\n\n /** @internal VOICE_SERVER_UPDATE. */\n public handleVoiceServer(data: VoiceServerData): void {\n this.#adapters.get(data.guild_id)?.onVoiceServerUpdate(data);\n }\n\n /** @internal The bot left (or lost) a guild: drop its connection without sending anything. */\n public handleGuildRemove(guildId: string): void {\n this.#connections.get(guildId)?.destroy(false);\n }\n\n /** Destroys every connection. @param leave Send op 4 to leave each channel (default true). */\n public destroy(leave = true): void {\n for (const connection of [...this.#connections.values()])\n connection.destroy(leave);\n this.#connections.clear();\n this.#adapters.clear();\n }\n}\n\n/** Resolves when `connection` is ready; rejects when it disconnects, is destroyed, or `timeoutMs` passes. */\nfunction waitReady(\n connection: VoiceConnection,\n timeoutMs: number,\n): Promise<VoiceConnection> {\n if (connection.status === \"ready\") return Promise.resolve(connection);\n return new Promise((resolve, reject) => {\n const done = (error?: Error): void => {\n clearTimeout(timer);\n connection.off(\"stateChange\", onChange);\n if (error) reject(error);\n else resolve(connection);\n };\n const onChange = (next: VoiceConnectionStatus): void => {\n if (next === \"ready\") done();\n else if (next === \"destroyed\")\n done(new VoiceError(\"The voice connection was destroyed.\"));\n else if (next === \"disconnected\")\n done(\n new VoiceError(\n `Could not join the voice channel: ${connection.disconnectReason?.message ?? connection.disconnectReason?.reason ?? \"disconnected\"}.`,\n ),\n );\n };\n const timer = setTimeout(\n () =>\n done(\n new VoiceError(\n `Joining the voice channel timed out after ${timeoutMs} ms.`,\n ),\n ),\n Math.min(timeoutMs + 50, 2_147_483_647),\n );\n connection.on(\"stateChange\", onChange);\n });\n}\n",
|
|
19
|
+
"import { CString, dlopen, FFIType, ptr, type Pointer } from \"bun:ffi\";\nimport { FRAME_SAMPLES, PCM_FRAME_BYTES, VoiceError } from \"./protocol.js\";\n\n/** `OPUS_APPLICATION_*`: what the encoder tunes for. */\nexport const OpusApplication = {\n /** Speech: best for voice chat. */\n Voip: 2048,\n /** Music and mixed content (the default). */\n Audio: 2049,\n /** Lowest delay; disables the speech modes. */\n RestrictedLowDelay: 2051,\n} as const;\nexport type OpusApplication =\n (typeof OpusApplication)[keyof typeof OpusApplication];\n\nconst SYMBOLS = {\n opus_encoder_create: {\n args: [FFIType.i32, FFIType.i32, FFIType.i32, FFIType.ptr],\n returns: FFIType.ptr,\n },\n opus_encode: {\n args: [FFIType.ptr, FFIType.ptr, FFIType.i32, FFIType.ptr, FFIType.i32],\n returns: FFIType.i32,\n },\n opus_encoder_destroy: { args: [FFIType.ptr], returns: FFIType.void },\n opus_decoder_create: {\n args: [FFIType.i32, FFIType.i32, FFIType.ptr],\n returns: FFIType.ptr,\n },\n opus_decode: {\n args: [\n FFIType.ptr,\n FFIType.ptr,\n FFIType.i32,\n FFIType.ptr,\n FFIType.i32,\n FFIType.i32,\n ],\n returns: FFIType.i32,\n },\n opus_decoder_destroy: { args: [FFIType.ptr], returns: FFIType.void },\n opus_strerror: { args: [FFIType.i32], returns: FFIType.ptr },\n opus_get_version_string: { args: [], returns: FFIType.ptr },\n} as const;\n\ntype Library = ReturnType<typeof dlopen<typeof SYMBOLS>>[\"symbols\"];\n\n/**\n * Where libopus usually is, by platform. `LUNIBEE_OPUS_LIBRARY` is tried\n * first; `LUNIBEE_OPUS_LIBRARY=none` skips libopus (Lunibee then uses opusscript).\n */\nfunction candidates(): string[] {\n const own = process.env.LUNIBEE_OPUS_LIBRARY;\n if (own === \"none\") return [];\n const byPlatform =\n process.platform === \"darwin\"\n ? [\n \"libopus.0.dylib\",\n \"libopus.dylib\",\n \"/opt/homebrew/lib/libopus.dylib\",\n \"/usr/local/lib/libopus.dylib\",\n ]\n : process.platform === \"win32\"\n ? [\"opus.dll\", \"libopus-0.dll\", \"libopus.dll\"]\n : [\"libopus.so.0\", \"libopus.so\"];\n return own ? [own, ...byPlatform] : byPlatform;\n}\n\nlet loaded: { symbols: Library; path: string } | null | undefined;\n\n/**\n * Opens the system's libopus through `bun:ffi` (once). `null` when it is not\n * installed: `apt install libopus0`, `brew install opus`, or point\n * `LUNIBEE_OPUS_LIBRARY` at the library file.\n */\nexport function loadLibopus(\n paths: readonly string[] = candidates(),\n): { symbols: Library; path: string } | null {\n for (const path of paths)\n try {\n const library = dlopen(path, SYMBOLS);\n return { symbols: library.symbols, path };\n } catch {\n // Not here; try the next one.\n }\n return null;\n}\n\n/** Whether libopus can be loaded (looked up once). */\nexport function hasLibopus(): boolean {\n loaded ??= loadLibopus();\n return loaded !== null;\n}\n\n/** @internal Forget the lookup, so tests can change `LUNIBEE_OPUS_LIBRARY`. */\nexport function resetLibopus(): void {\n loaded = undefined;\n}\n\nfunction library(): { symbols: Library; path: string } {\n loaded ??= loadLibopus();\n if (!loaded)\n throw new VoiceError(\n \"libopus is not installed (apt install libopus0, brew install opus), or set LUNIBEE_OPUS_LIBRARY to its path.\",\n );\n return loaded;\n}\n\n/** The libopus version string, e.g. `\"libopus 1.5.2\"`, or `null` when it is not installed. */\nexport function libopusVersion(): string | null {\n loaded ??= loadLibopus();\n if (!loaded) return null;\n return new CString(loaded.symbols.opus_get_version_string()!).toString();\n}\n\nfunction check(code: number, what: string): number {\n if (code < 0)\n throw new VoiceError(\n `${what} failed: ${new CString(library().symbols.opus_strerror(code)!).toString()}`,\n );\n return code;\n}\n\n/** Largest Opus packet: 1275 bytes per frame (RFC 6716). */\nconst MAX_PACKET = 1275;\n\n/**\n * Lunibee's Opus encoder and decoder for 48 kHz stereo, on the system's\n * libopus through `bun:ffi`: native speed with nothing to compile. Frees its\n * native state on `destroy()` (and, as a safety net, when it is collected).\n */\nexport class Opus {\n readonly #symbols: Library;\n #encoder: Pointer | null;\n #decoder: Pointer | null;\n readonly #packet = new Uint8Array(MAX_PACKET);\n readonly #pcm = new Int16Array(FRAME_SAMPLES * 2);\n static readonly #registry = new FinalizationRegistry<{\n symbols: Library;\n encoder: Pointer;\n decoder: Pointer;\n }>(({ symbols, encoder, decoder }) => {\n symbols.opus_encoder_destroy(encoder);\n symbols.opus_decoder_destroy(decoder);\n });\n\n /** @throws {VoiceError} When libopus is not installed or refuses the settings. */\n public constructor(application: OpusApplication = OpusApplication.Audio) {\n this.#symbols = library().symbols;\n const error = new Int32Array(1);\n this.#encoder = this.#symbols.opus_encoder_create(\n 48_000,\n 2,\n application,\n ptr(error),\n ) as Pointer | null;\n check(error[0]!, \"Creating the Opus encoder\");\n this.#decoder = this.#symbols.opus_decoder_create(\n 48_000,\n 2,\n ptr(error),\n ) as Pointer | null;\n if (error[0]! < 0) {\n this.#symbols.opus_encoder_destroy(this.#encoder!);\n check(error[0]!, \"Creating the Opus decoder\");\n }\n Opus.#registry.register(\n this,\n {\n symbols: this.#symbols,\n encoder: this.#encoder!,\n decoder: this.#decoder!,\n },\n this,\n );\n }\n\n /** Where libopus was loaded from. */\n public static get libraryPath(): string {\n return library().path;\n }\n\n /**\n * Encodes one 20 ms frame: 960 stereo samples of s16le PCM (3,840 bytes).\n * @returns The Opus packet (a new array).\n * @throws {VoiceError} After `destroy()`, for a frame of the wrong size, or when libopus fails.\n */\n public encode(pcm: Uint8Array): Uint8Array {\n if (!this.#encoder)\n throw new VoiceError(\"The Opus codec was destroyed.\");\n if (pcm.byteLength !== PCM_FRAME_BYTES)\n throw new VoiceError(\n `Opus encodes one 20 ms frame of ${PCM_FRAME_BYTES} bytes, got ${pcm.byteLength}.`,\n );\n // libopus reads native-endian int16; copy into an aligned buffer.\n const samples = this.#pcm;\n const view = new DataView(pcm.buffer, pcm.byteOffset, pcm.byteLength);\n for (let i = 0; i < samples.length; i++)\n samples[i] = view.getInt16(i * 2, true);\n const length = check(\n this.#symbols.opus_encode(\n this.#encoder,\n ptr(samples),\n FRAME_SAMPLES,\n ptr(this.#packet),\n MAX_PACKET,\n ),\n \"Opus encoding\",\n );\n return this.#packet.slice(0, length);\n }\n\n /**\n * Decodes one Opus packet to s16le PCM (3,840 bytes for a 20 ms packet).\n * An empty packet stands for a lost one and is concealed.\n * @throws {VoiceError} After `destroy()`, or for a corrupt packet.\n */\n public decode(packet: Uint8Array): Uint8Array {\n if (!this.#decoder)\n throw new VoiceError(\"The Opus codec was destroyed.\");\n // Up to 120 ms per packet (5,760 samples per channel); a lost packet\n // is concealed as one 20 ms frame.\n const frame = packet.byteLength ? 5760 : FRAME_SAMPLES;\n const out = new Int16Array(frame * 2);\n const samples = check(\n this.#symbols.opus_decode(\n this.#decoder,\n packet.byteLength ? ptr(packet) : null,\n packet.byteLength,\n ptr(out),\n frame,\n 0,\n ),\n \"Opus decoding\",\n );\n const pcm = new Uint8Array(samples * 4);\n const view = new DataView(pcm.buffer);\n for (let i = 0; i < samples * 2; i++)\n view.setInt16(i * 2, out[i]!, true);\n return pcm;\n }\n\n /** Frees the native encoder and decoder. Safe to call twice. */\n public destroy(): void {\n if (!this.#encoder) return;\n Opus.#registry.unregister(this);\n this.#symbols.opus_encoder_destroy(this.#encoder);\n this.#symbols.opus_decoder_destroy(this.#decoder!);\n this.#encoder = null;\n this.#decoder = null;\n }\n}\n",
|
|
20
|
+
"import { hasLibopus, Opus } from \"./libopus.js\";\nimport { FRAME_SAMPLES, VoiceError } from \"./protocol.js\";\n\n/** One 48 kHz stereo Opus encoder and decoder. Call `destroy()` when done. */\nexport interface OpusCodec {\n /** The library behind it: `\"libopus\"` (the system's, through `bun:ffi`) or `\"opusscript\"` (WebAssembly). */\n readonly library: string;\n /** Encodes one 20 ms frame of s16le PCM (3,840 bytes). */\n encode(pcm: Uint8Array): Uint8Array;\n /** Decodes one Opus packet to s16le PCM. */\n decode(packet: Uint8Array): Uint8Array;\n destroy(): void;\n}\n\n/** Lunibee's own codec on the system libopus (`Opus`, through `bun:ffi`). */\nconst native = (): OpusCodec => {\n const codec = new Opus();\n return {\n library: \"libopus\",\n encode: (pcm) => codec.encode(pcm),\n decode: (packet) => codec.decode(packet),\n destroy: () => codec.destroy(),\n };\n};\n\n/** `opusscript`: libopus compiled to WebAssembly, for systems without libopus. */\nconst wasm = async (): Promise<OpusCodec> => {\n const name = \"opusscript\";\n const mod = (await import(name)) as unknown as {\n default: ScriptConstructor;\n };\n const OpusScript = mod.default;\n const codec = new OpusScript(48_000, 2, OpusScript.Application.AUDIO);\n let destroyed = false;\n return {\n library: \"opusscript\",\n encode: (pcm) => codec.encode(Buffer.from(pcm), FRAME_SAMPLES),\n decode: (packet) => codec.decode(Buffer.from(packet)),\n destroy: () => {\n if (destroyed) return;\n destroyed = true;\n codec.delete();\n },\n };\n};\ninterface ScriptConstructor {\n new (\n rate: number,\n channels: number,\n application: number,\n ): {\n encode(pcm: Buffer, frameSize: number): Buffer;\n decode(packet: Buffer): Buffer;\n delete(): void;\n };\n Application: { AUDIO: number };\n}\n\n/**\n * Creates an Opus codec: Lunibee's `Opus` on the system's libopus when it is\n * installed (native speed, nothing to compile), otherwise `opusscript`, an\n * optional peer dependency. Playing Ogg/Opus files, or anything through\n * FFmpeg without `inlineVolume` or effects, needs neither.\n * @throws {VoiceError} If neither is available.\n */\nexport async function createOpusCodec(): Promise<OpusCodec> {\n if (hasLibopus()) return native();\n try {\n return await wasm();\n } catch {\n throw new VoiceError(\n \"Encoding or decoding Opus needs an Opus library: install libopus (apt install libopus0, brew install opus) or opusscript.\",\n );\n }\n}\n",
|
|
21
|
+
"import { PCM_FRAME_BYTES } from \"./protocol.js\";\n\nconst RATE = 48_000;\nconst CHANNELS = 2;\n\n/**\n * A PCM effect: changes one 20 ms frame of 48 kHz stereo interleaved samples\n * in place. Effects keep state between frames, so use one instance per\n * resource.\n */\nexport interface AudioEffect {\n process(samples: Int16Array): void;\n}\n\nfunction check(name: string, value: number, min: number, max: number): void {\n if (!Number.isFinite(value) || value < min || value > max)\n throw new RangeError(`${name} must be between ${min} and ${max}.`);\n}\n\nconst clip = (value: number): number =>\n value > 32767 ? 32767 : value < -32768 ? -32768 : Math.round(value);\n\n/**\n * Shifts the pitch by `semitones` (-24 to 24) without changing the speed:\n * +12 is an octave up (a \"chipmunk\" voice), -7 a deeper one. A granular\n * delay-line shifter, so it adds about 40 ms of latency.\n */\nexport function pitchShift(semitones: number): AudioEffect {\n check(\"semitones\", semitones, -24, 24);\n const ratio = 2 ** (semitones / 12);\n const window = 2048;\n const size = 4096;\n const buffers = [new Float32Array(size), new Float32Array(size)];\n let write = 0;\n let phase = 0;\n const step = (1 - ratio) / window;\n const tap = (buffer: Float32Array, delay: number): number => {\n const position = write - delay;\n const base = Math.floor(position);\n const frac = position - base;\n const a = buffer[base & (size - 1)]!;\n const b = buffer[(base + 1) & (size - 1)]!;\n return a + (b - a) * frac;\n };\n return {\n process(samples) {\n if (semitones === 0) return;\n for (let i = 0; i < samples.length; i += CHANNELS) {\n const p2 = (phase + 0.5) % 1;\n const g1 = 1 - Math.abs(2 * phase - 1);\n const g2 = 1 - g1;\n for (let c = 0; c < CHANNELS; c++) {\n const buffer = buffers[c]!;\n buffer[write & (size - 1)] = samples[i + c]!;\n samples[i + c] = clip(\n g1 * tap(buffer, 1 + phase * window) +\n g2 * tap(buffer, 1 + p2 * window),\n );\n }\n write = (write + 1) & 0x3fffffff;\n phase = (((phase + step) % 1) + 1) % 1;\n }\n },\n };\n}\n\n/** A robot voice: ring modulation with a `frequency` Hz carrier (1 to 2,000, default 50). */\nexport function robot(frequency = 50): AudioEffect {\n check(\"frequency\", frequency, 1, 2_000);\n const increment = (2 * Math.PI * frequency) / RATE;\n let angle = 0;\n return {\n process(samples) {\n for (let i = 0; i < samples.length; i += CHANNELS) {\n const carrier = Math.sin(angle);\n for (let c = 0; c < CHANNELS; c++)\n samples[i + c] = clip(samples[i + c]! * carrier);\n angle += increment;\n if (angle > 2 * Math.PI) angle -= 2 * Math.PI;\n }\n },\n };\n}\n\n/** Options for {@link echo}. */\nexport interface EchoOptions {\n /** Delay in ms (1 to 2,000). Default 250. */\n delay?: number;\n /** How much of each echo is fed back (0 to 0.95). Default 0.4. */\n feedback?: number;\n /** Echo level in the output (0 to 1). Default 0.5. */\n mix?: number;\n}\n\n/** An echo. Its buffer is fixed by `delay` (at most 2 s, 750 KB). */\nexport function echo(options: EchoOptions = {}): AudioEffect {\n const { delay = 250, feedback = 0.4, mix = 0.5 } = options;\n check(\"delay\", delay, 1, 2_000);\n check(\"feedback\", feedback, 0, 0.95);\n check(\"mix\", mix, 0, 1);\n const buffer = new Float32Array(\n Math.round((delay * RATE) / 1000) * CHANNELS,\n );\n let index = 0;\n return {\n process(samples) {\n for (let i = 0; i < samples.length; i++) {\n const delayed = buffer[index]!;\n const input = samples[i]!;\n buffer[index] = input + delayed * feedback;\n samples[i] = clip(input + delayed * mix);\n if (++index === buffer.length) index = 0;\n }\n },\n };\n}\n\n/** Linear gain (0 to 16): 0.5 is half, 2 double (clipped). */\nexport function gain(factor: number): AudioEffect {\n check(\"factor\", factor, 0, 16);\n return {\n process(samples) {\n if (factor === 1) return;\n for (let i = 0; i < samples.length; i++)\n samples[i] = clip(samples[i]! * factor);\n },\n };\n}\n\n/** @internal Runs `effects` over one s16le PCM frame; returns a new full frame (3,840 bytes). */\nexport function applyEffects(\n effects: readonly AudioEffect[],\n pcm: Uint8Array,\n): Uint8Array {\n if (effects.length === 0) return pcm;\n const view = new DataView(pcm.buffer, pcm.byteOffset, pcm.byteLength);\n // Always one full 20 ms frame out, so the encoder gets what it expects.\n const samples = new Int16Array(PCM_FRAME_BYTES >> 1);\n const count = Math.min(pcm.byteLength, PCM_FRAME_BYTES) >> 1;\n for (let i = 0; i < count; i++) samples[i] = view.getInt16(i * 2, true);\n for (const effect of effects) effect.process(samples);\n const out = new Uint8Array(samples.length * 2);\n const outView = new DataView(out.buffer);\n for (let i = 0; i < samples.length; i++)\n outView.setInt16(i * 2, samples[i]!, true);\n return out;\n}\n",
|
|
22
|
+
"import { applyEffects, type AudioEffect } from \"./effects.js\";\nimport { demuxOggOpus } from \"./ogg.js\";\nimport { createOpusCodec, type OpusCodec } from \"./opus.js\";\nimport { PCM_FRAME_BYTES, VoiceError } from \"./protocol.js\";\n\n/**\n * What an input holds:\n * - `\"arbitrary\"`: any format FFmpeg reads (needs `ffmpeg` on the PATH);\n * - `\"ogg/opus\"`: an Ogg/Opus file or stream, played without re-encoding;\n * - `\"opus\"`: one Opus packet (20 ms) per chunk;\n * - `\"raw\"`: 48 kHz stereo s16le PCM (needs an Opus library).\n */\nexport type StreamType = \"arbitrary\" | \"ogg/opus\" | \"opus\" | \"raw\";\n\n/** What {@link createAudioResource} can play. A string is a file path, or an `http(s)` URL for FFmpeg. */\nexport type AudioInput =\n | string\n | Uint8Array\n | ReadableStream<Uint8Array>\n | AsyncIterable<Uint8Array>;\n\n/** Options for {@link createAudioResource}. */\nexport interface AudioResourceOptions<T = unknown> {\n /** What the input holds. Default: from the file extension (`.ogg`/`.opus`/`.pcm`), otherwise `\"arbitrary\"`. */\n inputType?: StreamType;\n /** Allow `resource.volume.set()`. Decodes and re-encodes Opus input, so it costs CPU. Default false. */\n inlineVolume?: boolean;\n /** Anything you want to keep with the resource (a title, who queued it). */\n metadata?: T;\n /** FFmpeg executable. Default `\"ffmpeg\"`. */\n ffmpegPath?: string;\n /** Frames read ahead of playback. Default 10 (200 ms); 1 when `live`. */\n prefetch?: number;\n /**\n * PCM effects (`pitchShift`, `robot`, `echo`, `gain`, or your own), run in\n * order on every frame. Like `inlineVolume`, they decode and re-encode.\n * `resource.effects` can be changed while it plays.\n */\n effects?: AudioEffect[];\n /**\n * A live source (a user's voice from `receiver.subscribe()`): the player\n * waits for it without counting missed frames, and frames that pile up\n * beyond 100 ms are dropped to keep the delay low. Default false.\n */\n live?: boolean;\n /** @internal Creates the Opus codec in place of {@link createOpusCodec} (tests). */\n codecFactory?: () => Promise<OpusCodec>;\n}\n\n/** Most frames a live resource keeps queued before it drops the oldest (100 ms). */\nconst LIVE_BACKLOG = 5;\n\n/** Inline volume of a resource created with `inlineVolume: true`. */\nexport class VolumeControl {\n /** Linear gain: 1 is unchanged, 0.5 half, 2 double (clipped). */\n public volume = 1;\n /** Sets a linear gain. @throws {RangeError} For a negative or non-finite value. */\n public set(volume: number): void {\n if (!Number.isFinite(volume) || volume < 0)\n throw new RangeError(\n \"Volume must be a finite number of at least 0.\",\n );\n this.volume = volume;\n }\n /** Sets a logarithmic gain in decibels (0 is unchanged). */\n public setDecibels(db: number): void {\n this.set(10 ** (db / 20));\n }\n /** Scales one s16le PCM frame in place. */\n public apply(pcm: Uint8Array): Uint8Array {\n if (this.volume === 1) return pcm;\n const view = new DataView(pcm.buffer, pcm.byteOffset, pcm.byteLength);\n for (let i = 0; i + 1 < pcm.length; i += 2) {\n const scaled = Math.round(view.getInt16(i, true) * this.volume);\n view.setInt16(i, Math.max(-32768, Math.min(32767, scaled)), true);\n }\n return pcm;\n }\n}\n\nasync function* chunksOf(\n input: Exclude<AudioInput, string>,\n): AsyncGenerator<Uint8Array> {\n if (input instanceof Uint8Array) {\n yield input;\n return;\n }\n if (input instanceof ReadableStream) {\n const reader = input.getReader();\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) return;\n yield value;\n }\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n }\n yield* input as AsyncIterable<Uint8Array>;\n}\n\n/** Cuts a byte stream into whole 20 ms PCM frames; a short last frame is padded with silence. */\nasync function* pcmFrames(\n chunks: AsyncIterable<Uint8Array>,\n): AsyncGenerator<Uint8Array> {\n let pending = new Uint8Array(0);\n for await (const chunk of chunks) {\n const merged = new Uint8Array(pending.length + chunk.length);\n merged.set(pending, 0);\n merged.set(chunk, pending.length);\n let offset = 0;\n while (merged.length - offset >= PCM_FRAME_BYTES) {\n yield merged.slice(offset, offset + PCM_FRAME_BYTES);\n offset += PCM_FRAME_BYTES;\n }\n pending = merged.slice(offset);\n }\n if (pending.length > 0) {\n const last = new Uint8Array(PCM_FRAME_BYTES);\n last.set(pending, 0);\n yield last;\n }\n}\n\nfunction inferType(path: string): StreamType {\n const lower = path.toLowerCase();\n if (lower.endsWith(\".ogg\") || lower.endsWith(\".opus\")) return \"ogg/opus\";\n if (lower.endsWith(\".pcm\") || lower.endsWith(\".raw\")) return \"raw\";\n return \"arbitrary\";\n}\n\n/**\n * An audio source for an {@link AudioPlayer}: a queue of 20 ms Opus frames\n * filled ahead of playback. One resource plays once; create another to play\n * the same input again.\n */\nexport class AudioResource<T = unknown> {\n /** What was passed as `metadata`. */\n public readonly metadata: T;\n /** Inline volume, when created with `inlineVolume: true`. */\n public readonly volume?: VolumeControl;\n /** The effects in use, when created with `effects`. Changes apply from the next frame. */\n public readonly effects?: AudioEffect[];\n /** Whether it is a live source (`live: true`). */\n public readonly live: boolean;\n /** Milliseconds of this resource the player has sent. */\n public playbackDuration = 0;\n /** Whether the player took its first frame. */\n public started = false;\n readonly #frames: AsyncGenerator<Uint8Array>;\n readonly #queue: Uint8Array[] = [];\n readonly #prefetch: number;\n readonly #cleanup: (() => void)[] = [];\n #filling = false;\n #done = false;\n #error?: Error;\n\n /** @internal Use {@link createAudioResource}. */\n public constructor(\n frames: AsyncGenerator<Uint8Array>,\n options: {\n metadata?: T;\n volume?: VolumeControl;\n effects?: AudioEffect[];\n live?: boolean;\n prefetch?: number;\n cleanup?: () => void;\n },\n ) {\n this.#frames = frames;\n this.metadata = options.metadata as T;\n this.volume = options.volume;\n this.effects = options.effects;\n this.live = options.live ?? false;\n this.#prefetch = this.live\n ? Math.max(1, options.prefetch ?? 1)\n : Math.max(1, options.prefetch ?? 10);\n if (options.cleanup) this.#cleanup.push(options.cleanup);\n this.#fill();\n }\n\n /** Whether every frame has been read (or it failed, or was destroyed). */\n public get ended(): boolean {\n return this.#done && this.#queue.length === 0;\n }\n\n /** Why it ended early, if it failed. */\n public get error(): Error | undefined {\n return this.#error;\n }\n\n /** Whether a frame is ready now. */\n public get readable(): boolean {\n return this.#queue.length > 0;\n }\n\n #fill(): void {\n if (this.#filling || this.#done) return;\n this.#filling = true;\n void (async () => {\n try {\n while (\n !this.#done &&\n (this.live || this.#queue.length < this.#prefetch)\n ) {\n const next = await this.#frames.next();\n if (next.done) {\n this.#finish();\n break;\n }\n if (this.#done) break;\n this.#queue.push(next.value);\n // Live: keep up with the source; old frames would only add delay.\n if (this.live && this.#queue.length > LIVE_BACKLOG)\n this.#queue.shift();\n }\n } catch (error) {\n this.#error =\n error instanceof Error\n ? error\n : new VoiceError(String(error));\n this.#finish();\n } finally {\n this.#filling = false;\n }\n })();\n }\n\n #finish(): void {\n if (this.#done) return;\n this.#done = true;\n for (const cleanup of this.#cleanup.splice(0))\n try {\n cleanup();\n } catch {\n // Cleanup is best effort.\n }\n }\n\n /**\n * Takes the next Opus frame. @returns A frame, `undefined` when none is\n * ready yet (buffering), or `null` when the resource has ended.\n */\n public read(): Uint8Array | null | undefined {\n const frame = this.#queue.shift();\n if (frame) {\n this.started = true;\n this.#fill();\n return frame;\n }\n if (this.#done) return null;\n this.#fill();\n return undefined;\n }\n\n /** Stops reading: ends FFmpeg and the input, frees the codec. Safe to call twice. */\n public destroy(): void {\n this.#queue.length = 0;\n this.#finish();\n void this.#frames.return(undefined).catch(() => undefined);\n }\n}\n\nfunction spawnFFmpeg(\n input: AudioInput,\n path: string,\n output: \"ogg/opus\" | \"raw\",\n): {\n stdout: ReadableStream<Uint8Array>;\n kill: () => void;\n /** Resolves when FFmpeg exited cleanly (or was killed); rejects with its error output otherwise. */\n exited: () => Promise<void>;\n} {\n const fromURL = typeof input === \"string\" && /^https?:\\/\\//i.test(input);\n const args = [\n path,\n \"-hide_banner\",\n \"-loglevel\",\n \"error\",\n \"-analyzeduration\",\n \"0\",\n // A URL is read by FFmpeg itself; everything else arrives on stdin, so\n // a file name is never parsed as an FFmpeg option or protocol.\n \"-i\",\n fromURL ? (input as string) : \"pipe:0\",\n \"-vn\",\n \"-ar\",\n \"48000\",\n \"-ac\",\n \"2\",\n ...(output === \"raw\"\n ? [\"-f\", \"s16le\"]\n : [\n \"-c:a\",\n \"libopus\",\n \"-b:a\",\n \"128k\",\n \"-frame_duration\",\n \"20\",\n \"-f\",\n \"opus\",\n ]),\n \"pipe:1\",\n ];\n const proc = Bun.spawn(args, {\n stdin: fromURL ? \"ignore\" : \"pipe\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n let killed = false;\n // The last 1,000 characters of FFmpeg's error output, for the error message.\n const stderr = (async () => {\n let tail = \"\";\n const decoder = new TextDecoder();\n try {\n for await (const chunk of proc.stderr as ReadableStream<Uint8Array>)\n tail = (tail + decoder.decode(chunk, { stream: true })).slice(\n -1000,\n );\n } catch {\n // Killed.\n }\n return tail.trim();\n })();\n if (!fromURL) {\n const sink = proc.stdin as unknown as {\n write(chunk: Uint8Array): unknown;\n end(): unknown;\n };\n const source =\n typeof input === \"string\"\n ? chunksOf(Bun.file(input).stream())\n : chunksOf(input);\n void (async () => {\n try {\n for await (const chunk of source) await sink.write(chunk);\n } catch {\n // FFmpeg exited (or was killed) before reading everything.\n } finally {\n try {\n await sink.end();\n } catch {\n // Already closed.\n }\n }\n })();\n }\n return {\n stdout: proc.stdout as ReadableStream<Uint8Array>,\n kill: () => {\n killed = true;\n try {\n proc.kill();\n } catch {\n // Already exited.\n }\n },\n exited: async () => {\n const code = await proc.exited;\n if (code === 0 || killed) return;\n const output = await stderr;\n throw new VoiceError(\n `FFmpeg exited with code ${code}${output ? `: ${output}` : \".\"}`,\n );\n },\n };\n}\n\n/**\n * Creates an {@link AudioResource} from a file path, a URL (FFmpeg), bytes, a\n * `ReadableStream` or an async iterable.\n *\n * Ogg/Opus input is played as it is (passthrough). PCM input, and anything\n * with `inlineVolume`, is encoded with Opus (`opusscript`, an optional\n * peer). Other formats go through FFmpeg, which is killed when\n * the resource ends or is destroyed.\n */\nexport function createAudioResource<T = unknown>(\n input: AudioInput,\n options: AudioResourceOptions<T> = {},\n): AudioResource<T> {\n let type =\n options.inputType ??\n (typeof input === \"string\" ? inferType(input) : \"arbitrary\");\n const volume = options.inlineVolume ? new VolumeControl() : undefined;\n const effects = options.effects ? [...options.effects] : undefined;\n const pcmOut = Boolean(volume || effects);\n const transform = (pcm: Uint8Array): Uint8Array => {\n const out = effects ? applyEffects(effects, pcm) : pcm;\n return volume ? volume.apply(out) : out;\n };\n const cleanups: (() => void)[] = [];\n let chunks: AsyncIterable<Uint8Array>;\n\n if (type === \"arbitrary\") {\n const ffmpeg = spawnFFmpeg(\n input,\n options.ffmpegPath ?? \"ffmpeg\",\n pcmOut ? \"raw\" : \"ogg/opus\",\n );\n cleanups.push(ffmpeg.kill);\n // An FFmpeg failure (bad input, unreachable URL) ends its output early:\n // report it as the resource's error, not as a normal end.\n chunks = (async function* () {\n yield* chunksOf(ffmpeg.stdout);\n await ffmpeg.exited();\n })();\n type = pcmOut ? \"raw\" : \"ogg/opus\";\n } else if (typeof input === \"string\") {\n if (/^https?:\\/\\//i.test(input))\n throw new VoiceError(`A URL needs inputType \"arbitrary\" (FFmpeg).`);\n chunks = chunksOf(Bun.file(input).stream());\n } else chunks = chunksOf(input);\n\n // The codec loads with the first frame that needs it, so this stays synchronous.\n let codec: OpusCodec | undefined;\n let destroyed = false;\n /** @returns The codec, or `undefined` once the resource is destroyed (nothing may be encoded then). */\n const getCodec = async (): Promise<OpusCodec | undefined> => {\n if (!codec) {\n const created = await (options.codecFactory ?? createOpusCodec)();\n // Destroyed while the library loaded: cleanup already ran, so free it here.\n if (destroyed) {\n created.destroy();\n return undefined;\n }\n codec = created;\n cleanups.push(() => created.destroy());\n }\n return destroyed ? undefined : codec;\n };\n\n let frames: AsyncGenerator<Uint8Array>;\n if (type === \"raw\") {\n const source = pcmFrames(chunks);\n frames = (async function* () {\n for await (const pcm of source) {\n const c = await getCodec();\n if (!c) return;\n yield c.encode(transform(pcm));\n }\n })();\n } else {\n const packets = type === \"ogg/opus\" ? demuxOggOpus(chunks) : chunks;\n frames = pcmOut\n ? (async function* () {\n for await (const packet of packets) {\n const c = await getCodec();\n if (!c) return;\n yield c.encode(transform(c.decode(packet)));\n }\n })()\n : (async function* () {\n yield* packets;\n })();\n }\n return new AudioResource<T>(frames, {\n metadata: options.metadata,\n volume,\n effects,\n live: options.live,\n prefetch: options.prefetch,\n cleanup: () => {\n destroyed = true;\n for (const cleanup of cleanups) cleanup();\n },\n });\n}\n",
|
|
23
|
+
"import { FRAME_DURATION_MS, SILENCE_FRAME, VoiceError } from \"./protocol.js\";\nimport { Emitter } from \"./emitter.js\";\nimport type { AudioResource } from \"./resource.js\";\n\n/** Where an {@link AudioPlayer} is. */\nexport const AudioPlayerStatus = {\n /** Nothing to play. */\n Idle: \"idle\",\n /** A resource is loaded but its next frame is not ready yet. */\n Buffering: \"buffering\",\n /** Sending a frame every 20 ms. */\n Playing: \"playing\",\n /** Paused by `pause()`. */\n Paused: \"paused\",\n /** Paused because no subscribed connection can send (`noSubscriber: \"pause\"`). */\n AutoPaused: \"autopaused\",\n} as const;\nexport type AudioPlayerStatus =\n (typeof AudioPlayerStatus)[keyof typeof AudioPlayerStatus];\n\n/** A destination for a player's frames: a voice connection. */\nexport interface AudioSink {\n /** Whether it can send now. */\n readonly ready: boolean;\n sendFrame(frame: Uint8Array): boolean;\n setSpeaking(speaking: boolean): void;\n}\n\n/** Options for {@link AudioPlayer}. */\nexport interface AudioPlayerOptions {\n /** With no ready subscriber: `\"pause\"` (default) waits, `\"play\"` keeps consuming, `\"stop\"` stops. */\n noSubscriber?: \"pause\" | \"play\" | \"stop\";\n /** Frames the resource may be late in a row before playback fails. Default 250 (5 s). */\n maxMissedFrames?: number;\n}\n\n/** What {@link AudioPlayer} emits. */\nexport interface AudioPlayerEvents {\n stateChange: [from: AudioPlayerStatus, to: AudioPlayerStatus];\n /** The resource failed (an FFmpeg error, a corrupt stream). The player goes idle. */\n error: [error: Error, resource: AudioResource<unknown>];\n /** The resource played to its end. */\n finish: [resource: AudioResource<unknown>];\n}\n\n/** Silence frames sent after audio stops, so the receiving decoder does not interpolate. */\nconst SILENCE_PADDING = 5;\n/** A tick this late (event loop blocked) restarts the clock instead of sending a burst. */\nconst MAX_LATENESS_MS = 100;\n\n/**\n * Plays {@link AudioResource}s to subscribed connections: one 20 ms Opus\n * frame per tick, on a self-correcting clock. The clock runs only while\n * there is something to send; an idle or paused player has no timer.\n */\nexport class AudioPlayer extends Emitter<AudioPlayerEvents> {\n #state: AudioPlayerStatus = \"idle\";\n #resource?: AudioResource<unknown>;\n readonly #sinks = new Set<AudioSink>();\n readonly #options: Required<AudioPlayerOptions>;\n #timer?: ReturnType<typeof setTimeout>;\n #next = 0;\n #silence = 0;\n #missed = 0;\n\n public constructor(options: AudioPlayerOptions = {}) {\n super();\n this.#options = {\n noSubscriber: options.noSubscriber ?? \"pause\",\n maxMissedFrames: options.maxMissedFrames ?? 250,\n };\n }\n\n /** Current status. */\n public get state(): AudioPlayerStatus {\n return this.#state;\n }\n\n /** The resource playing (or paused), if any. */\n public get resource(): AudioResource<unknown> | undefined {\n return this.#resource;\n }\n\n /** Subscribed connections. */\n public get subscribers(): ReadonlySet<AudioSink> {\n return this.#sinks;\n }\n\n /** Whether the clock is running (for tests and diagnostics). */\n public get ticking(): boolean {\n return this.#timer !== undefined;\n }\n\n #transition(next: AudioPlayerStatus): void {\n if (this.#state === next) return;\n const from = this.#state;\n this.#state = next;\n this.emit(\"stateChange\", from, next);\n }\n\n /**\n * Plays `resource`, replacing (and destroying) the current one.\n * @throws {VoiceError} If the resource already ended or was played before.\n */\n public play(resource: AudioResource<unknown>): void {\n if (resource.ended || resource.started)\n throw new VoiceError(\n \"This audio resource has already been played; create a new one.\",\n );\n if (this.#resource && this.#resource !== resource)\n this.#resource.destroy();\n this.#resource = resource;\n this.#missed = 0;\n this.#silence = 0;\n this.#transition(resource.readable ? \"playing\" : \"buffering\");\n this.#start();\n }\n\n /** Pauses. @param silence Send five silence frames first (default true). @returns Whether it paused. */\n public pause(silence = true): boolean {\n if (this.#state !== \"playing\" && this.#state !== \"buffering\")\n return false;\n this.#transition(\"paused\");\n this.#silence = silence ? SILENCE_PADDING : 0;\n if (silence) this.#start();\n else this.#quiet();\n return true;\n }\n\n /** Resumes after `pause()`. @returns Whether it resumed. */\n public unpause(): boolean {\n if (this.#state !== \"paused\") return false;\n this.#silence = 0;\n this.#transition(this.#resource?.readable ? \"playing\" : \"buffering\");\n this.#start();\n return true;\n }\n\n /** Alias of {@link unpause}. */\n public resume(): boolean {\n return this.unpause();\n }\n\n /**\n * Stops and destroys the resource. @param force Skip the five silence\n * frames. @returns Whether anything was playing.\n */\n public stop(force = false): boolean {\n if (this.#state === \"idle\") return false;\n this.#resource?.destroy();\n this.#resource = undefined;\n this.#transition(\"idle\");\n this.#silence = force ? 0 : SILENCE_PADDING;\n if (force) this.#quiet();\n else this.#start();\n return true;\n }\n\n /** @internal A connection subscribes. */\n public attach(sink: AudioSink): void {\n this.#sinks.add(sink);\n this.refresh();\n }\n\n /** @internal A connection unsubscribes. */\n public detach(sink: AudioSink): void {\n if (!this.#sinks.delete(sink)) return;\n try {\n sink.setSpeaking(false);\n } catch {\n // Its session is gone.\n }\n this.refresh();\n }\n\n /** @internal A subscriber's readiness changed: leave or enter `autopaused`. */\n public refresh(): void {\n if (this.#state === \"autopaused\" && this.#hasReadySink()) {\n this.#transition(\n this.#resource?.readable ? \"playing\" : \"buffering\",\n );\n this.#start();\n } else if (this.#state === \"playing\" || this.#state === \"buffering\")\n this.#start();\n }\n\n #hasReadySink(): boolean {\n for (const sink of this.#sinks) if (sink.ready) return true;\n return false;\n }\n\n #start(): void {\n if (this.#timer) return;\n this.#next = performance.now();\n this.#schedule();\n }\n\n #schedule(): void {\n this.#next += FRAME_DURATION_MS;\n const now = performance.now();\n if (now - this.#next > MAX_LATENESS_MS)\n this.#next = now + FRAME_DURATION_MS;\n this.#timer = setTimeout(\n () => {\n this.#timer = undefined;\n this.#tick();\n },\n Math.max(0, this.#next - now),\n );\n }\n\n /** Stops the clock and clears the speaking indicator. */\n #quiet(): void {\n if (this.#timer) clearTimeout(this.#timer);\n this.#timer = undefined;\n for (const sink of this.#sinks)\n try {\n sink.setSpeaking(false);\n } catch {\n // Its session is gone.\n }\n }\n\n #send(frame: Uint8Array): void {\n for (const sink of this.#sinks)\n if (sink.ready)\n try {\n sink.sendFrame(frame);\n } catch {\n // A failing connection must not stop the others.\n }\n }\n\n #tick(): void {\n // Silence padding after pause() or stop().\n if (this.#state === \"idle\" || this.#state === \"paused\") {\n if (this.#silence > 0) {\n this.#silence--;\n this.#send(SILENCE_FRAME);\n if (this.#silence > 0) return this.#schedule();\n }\n return this.#quiet();\n }\n if (this.#state === \"autopaused\") return this.#quiet();\n const resource = this.#resource;\n if (!resource) return this.#quiet();\n if (!this.#hasReadySink()) {\n if (this.#options.noSubscriber === \"pause\") {\n this.#transition(\"autopaused\");\n return this.#quiet();\n }\n if (this.#options.noSubscriber === \"stop\") {\n this.stop(true);\n return;\n }\n }\n const frame = resource.read();\n if (frame === null) return this.#end(resource);\n if (frame === undefined) {\n // A live source is quiet while its user is; that is not a failure.\n if (resource.live) {\n if (!resource.started) this.#transition(\"buffering\");\n return this.#schedule();\n }\n this.#transition(\"buffering\");\n if (++this.#missed > this.#options.maxMissedFrames) {\n this.#fail(\n resource,\n new VoiceError(\n \"The audio resource stopped producing frames.\",\n ),\n );\n return;\n }\n return this.#schedule();\n }\n this.#missed = 0;\n this.#transition(\"playing\");\n this.#send(frame);\n resource.playbackDuration += FRAME_DURATION_MS;\n this.#schedule();\n }\n\n #end(resource: AudioResource<unknown>): void {\n if (resource.error) return this.#fail(resource, resource.error);\n this.#resource = undefined;\n this.#transition(\"idle\");\n this.emit(\"finish\", resource);\n this.#silence = SILENCE_PADDING;\n this.#tick();\n }\n\n #fail(resource: AudioResource<unknown>, error: Error): void {\n resource.destroy();\n this.#resource = undefined;\n this.#transition(\"idle\");\n this.emit(\"error\", error, resource);\n this.#silence = SILENCE_PADDING;\n this.#tick();\n }\n}\n\n/** Creates an {@link AudioPlayer}. */\nexport function createAudioPlayer(options?: AudioPlayerOptions): AudioPlayer {\n return new AudioPlayer(options);\n}\n",
|
|
24
|
+
"import { VoiceConnection, type VoiceConnectionStatus } from \"./connection.js\";\nimport { loadDave } from \"./dave.js\";\nimport { createOpusCodec } from \"./opus.js\";\nimport { AudioPlayer, type AudioPlayerStatus } from \"./player.js\";\nimport { VoiceError } from \"./protocol.js\";\n\nexport {\n VOICE_GATEWAY_VERSION,\n VoiceOpcodes,\n VoiceCloseCodes,\n canResumeVoice,\n RTP_OPUS_PAYLOAD_TYPE,\n FRAME_DURATION_MS,\n FRAME_SAMPLES,\n PCM_FRAME_BYTES,\n SILENCE_FRAME,\n SpeakingFlags,\n VoiceError,\n} from \"./protocol.js\";\nexport {\n PacketCipher,\n SUPPORTED_ENCRYPTION_MODES,\n chooseEncryptionMode,\n parseRtpHeader,\n rtpHeader,\n type RtpHeader,\n type VoiceEncryptionMode,\n} from \"./crypto.js\";\nexport {\n VoiceGateway,\n voiceGatewayURL,\n HEARTBEAT_TIMEOUT_CLOSE,\n type VoiceBinaryPacket,\n type VoiceGatewayHandlers,\n type VoicePacket,\n type VoiceSocketFactory,\n type VoiceSocketLike,\n} from \"./gateway.js\";\nexport {\n VoiceUdp,\n bunUdpSocket,\n discoveryRequest,\n parseDiscoveryResponse,\n type UdpSocketFactory,\n type UdpSocketLike,\n} from \"./udp.js\";\nexport {\n DaveSession,\n loadDave,\n maxDaveProtocolVersion,\n type DaveSessionHooks,\n} from \"./dave.js\";\nexport {\n VoiceNetworking,\n type NetworkingState,\n type VoiceNetworkingHandlers,\n type VoiceNetworkingOptions,\n type VoiceServerInfo,\n} from \"./networking.js\";\nexport { createOpusCodec, type OpusCodec } from \"./opus.js\";\nexport {\n Opus,\n OpusApplication,\n hasLibopus,\n libopusVersion,\n loadLibopus,\n} from \"./libopus.js\";\nexport { demuxOggOpus, OggOpusWriter } from \"./ogg.js\";\nexport {\n pitchShift,\n robot,\n echo,\n gain,\n type AudioEffect,\n type EchoOptions,\n} from \"./effects.js\";\nexport {\n AudioResource,\n VolumeControl,\n createAudioResource,\n type AudioInput,\n type AudioResourceOptions,\n type StreamType,\n} from \"./resource.js\";\nexport {\n AudioPlayer,\n AudioPlayerStatus,\n createAudioPlayer,\n type AudioPlayerEvents,\n type AudioPlayerOptions,\n type AudioSink,\n} from \"./player.js\";\nexport {\n VoiceReceiver,\n type ReceiveEnd,\n type ReceiveOptions,\n type RecordOptions,\n} from \"./receiver.js\";\nexport {\n VoiceConnection,\n VoiceConnectionStatus,\n VoiceManager,\n getVoiceConnection,\n joinVoiceChannel,\n type DisconnectReason,\n type JoinVoiceChannelOptions,\n type PlayerSubscription,\n type VoiceAdapter,\n type VoiceAdapterCreator,\n type VoiceAdapterMethods,\n type VoiceConnectionEvents,\n type VoiceJoinOptions,\n type VoiceManagerClient,\n type VoiceServerData,\n type VoiceStateData,\n type VoiceStatePayload,\n} from \"./connection.js\";\n\n/**\n * Resolves once `target` reaches `status`, or rejects after `timeoutMs`.\n * @throws {VoiceError} If the status is not reached in time.\n */\nexport function entersState<T extends VoiceConnection | AudioPlayer>(\n target: T,\n status: T extends VoiceConnection\n ? VoiceConnectionStatus\n : AudioPlayerStatus,\n timeoutMs: number,\n): Promise<T> {\n const current =\n target instanceof VoiceConnection ? target.status : target.state;\n if (current === status) return Promise.resolve(target);\n const emitter = target as unknown as {\n on(event: \"stateChange\", fn: (a: string, b: string) => void): unknown;\n off(event: \"stateChange\", fn: (a: string, b: string) => void): unknown;\n };\n // A connection emits (next, previous); a player emits (from, to).\n const isConnection = target instanceof VoiceConnection;\n return new Promise<T>((resolve, reject) => {\n const onChange = (first: string, second: string): void => {\n if ((isConnection ? first : second) !== status) return;\n clearTimeout(timer);\n emitter.off(\"stateChange\", onChange);\n resolve(target);\n };\n const timer = setTimeout(\n () => {\n emitter.off(\"stateChange\", onChange);\n reject(\n new VoiceError(\n `Did not enter state \"${String(status)}\" within ${timeoutMs} ms.`,\n ),\n );\n },\n Math.min(timeoutMs, 2_147_483_647),\n );\n emitter.on(\"stateChange\", onChange);\n });\n}\n\n/** Which optional voice dependencies this runtime can load. */\nexport async function generateDependencyReport(): Promise<{\n dave: string | null;\n opus: string | null;\n ffmpeg: string | null;\n}> {\n const dave = await loadDave();\n let opus: string | null = null;\n try {\n const codec = await createOpusCodec();\n opus = codec.library;\n codec.destroy();\n } catch {\n opus = null;\n }\n let ffmpeg: string | null = null;\n try {\n const proc = Bun.spawnSync([\"ffmpeg\", \"-version\"], {\n stdout: \"pipe\",\n stderr: \"ignore\",\n });\n if (proc.exitCode === 0)\n ffmpeg =\n new TextDecoder().decode(proc.stdout).split(\"\\n\")[0] ??\n \"ffmpeg\";\n } catch {\n ffmpeg = null;\n }\n return {\n dave: dave\n ? `@snazzah/davey (DAVE v${dave.DAVE_PROTOCOL_VERSION})`\n : null,\n opus,\n ffmpeg,\n };\n}\n"
|
|
25
|
+
],
|
|
26
|
+
"mappings": ";;;;;;AAAA;;;ACMA;AAAO,SAAS,OAAO,CAAC,GAAG;AAAA,EACvB,OAAO,aAAa,cAAe,YAAY,OAAO,CAAC,KAAK,EAAE,YAAY,SAAS;AAAA;AAGhF,SAAS,KAAK,CAAC,GAAG;AAAA,EACrB,IAAI,OAAO,MAAM;AAAA,IACb,MAAM,IAAI,MAAM,yBAAyB,GAAG;AAAA;AAG7C,SAAS,OAAO,CAAC,GAAG;AAAA,EACvB,IAAI,CAAC,OAAO,cAAc,CAAC,KAAK,IAAI;AAAA,IAChC,MAAM,IAAI,MAAM,oCAAoC,CAAC;AAAA;AAGtD,SAAS,MAAM,CAAC,MAAM,SAAS;AAAA,EAClC,IAAI,CAAC,QAAQ,CAAC;AAAA,IACV,MAAM,IAAI,MAAM,qBAAqB;AAAA,EACzC,IAAI,QAAQ,SAAS,KAAK,CAAC,QAAQ,SAAS,EAAE,MAAM;AAAA,IAChD,MAAM,IAAI,MAAM,mCAAmC,UAAU,kBAAkB,EAAE,MAAM;AAAA;AAcxF,SAAS,OAAO,CAAC,UAAU,gBAAgB,MAAM;AAAA,EACpD,IAAI,SAAS;AAAA,IACT,MAAM,IAAI,MAAM,kCAAkC;AAAA,EACtD,IAAI,iBAAiB,SAAS;AAAA,IAC1B,MAAM,IAAI,MAAM,uCAAuC;AAAA;AAGxD,SAAS,OAAO,CAAC,KAAK,UAAU;AAAA,EACnC,OAAO,GAAG;AAAA,EACV,MAAM,MAAM,SAAS;AAAA,EACrB,IAAI,IAAI,SAAS,KAAK;AAAA,IAClB,MAAM,IAAI,MAAM,2DAA2D,GAAG;AAAA,EAClF;AAAA;AAOG,SAAS,GAAG,CAAC,KAAK;AAAA,EACrB,OAAO,IAAI,YAAY,IAAI,QAAQ,IAAI,YAAY,KAAK,MAAM,IAAI,aAAa,CAAC,CAAC;AAAA;AAG9E,SAAS,KAAK,IAAI,QAAQ;AAAA,EAC7B,SAAS,IAAI,EAAG,IAAI,OAAO,QAAQ,KAAK;AAAA,IACpC,OAAO,GAAG,KAAK,CAAC;AAAA,EACpB;AAAA;AAGG,SAAS,UAAU,CAAC,KAAK;AAAA,EAC5B,OAAO,IAAI,SAAS,IAAI,QAAQ,IAAI,YAAY,IAAI,UAAU;AAAA;AAG3D,IAAM,wBAAwB,MAAM,IAAI,WAAW,IAAI,YAAY,CAAC,SAAU,CAAC,EAAE,MAAM,EAAE,OAAO,IAAM;AAoFtG,SAAS,WAAW,CAAC,KAAK;AAAA,EAC7B,IAAI,OAAO,QAAQ;AAAA,IACf,MAAM,IAAI,MAAM,iBAAiB;AAAA,EACrC,OAAO,IAAI,WAAW,IAAI,YAAY,EAAE,OAAO,GAAG,CAAC;AAAA;AAchD,SAAS,OAAO,CAAC,MAAM;AAAA,EAC1B,IAAI,OAAO,SAAS;AAAA,IAChB,OAAO,YAAY,IAAI;AAAA,EACtB,SAAI,QAAQ,IAAI;AAAA,IACjB,OAAO,UAAU,IAAI;AAAA,EAErB;AAAA,UAAM,IAAI,MAAM,8BAA8B,OAAO,IAAI;AAAA,EAC7D,OAAO;AAAA;AAwCJ,SAAS,SAAS,CAAC,UAAU,MAAM;AAAA,EACtC,IAAI,QAAQ,QAAQ,OAAO,SAAS;AAAA,IAChC,MAAM,IAAI,MAAM,yBAAyB;AAAA,EAC7C,MAAM,SAAS,OAAO,OAAO,UAAU,IAAI;AAAA,EAC3C,OAAO;AAAA;AAGJ,SAAS,UAAU,CAAC,GAAG,GAAG;AAAA,EAC7B,IAAI,EAAE,WAAW,EAAE;AAAA,IACf,OAAO;AAAA,EACX,IAAI,OAAO;AAAA,EACX,SAAS,IAAI,EAAG,IAAI,EAAE,QAAQ;AAAA,IAC1B,QAAQ,EAAE,KAAK,EAAE;AAAA,EACrB,OAAO,SAAS;AAAA;AAUb,IAAM,aAAa,CAAC,QAAQ,gBAAgB;AAAA,EAC/C,SAAS,aAAa,CAAC,QAAQ,MAAM;AAAA,IAEjC,OAAO,GAAG;AAAA,IAEV,IAAI,CAAC;AAAA,MACD,MAAM,IAAI,MAAM,iDAAiD;AAAA,IAErE,IAAI,OAAO,gBAAgB,WAAW;AAAA,MAClC,MAAM,QAAQ,KAAK;AAAA,MACnB,IAAI,CAAC;AAAA,QACD,MAAM,IAAI,MAAM,qBAAqB;AAAA,MACzC,IAAI,OAAO;AAAA,QACP,OAAO,KAAK;AAAA,MAEZ;AAAA,eAAO,OAAO,OAAO,WAAW;AAAA,IACxC;AAAA,IAEA,MAAM,OAAO,OAAO;AAAA,IACpB,IAAI,QAAQ,KAAK,OAAO,WAAW;AAAA,MAC/B,OAAO,KAAK,EAAE;AAAA,IAClB;AAAA,IACA,MAAM,SAAS,YAAY,KAAK,GAAG,IAAI;AAAA,IACvC,MAAM,cAAc,CAAC,UAAU,WAAW;AAAA,MACtC,IAAI,WAAW,WAAW;AAAA,QACtB,IAAI,aAAa;AAAA,UACb,MAAM,IAAI,MAAM,6BAA6B;AAAA,QACjD,OAAO,MAAM;AAAA,MACjB;AAAA;AAAA,IAGJ,IAAI,SAAS;AAAA,IACb,MAAM,WAAW;AAAA,MACb,OAAO,CAAC,MAAM,QAAQ;AAAA,QAClB,IAAI;AAAA,UACA,MAAM,IAAI,MAAM,8CAA8C;AAAA,QAClE,SAAS;AAAA,QACT,OAAO,IAAI;AAAA,QACX,YAAY,OAAO,QAAQ,QAAQ,MAAM;AAAA,QACzC,OAAO,OAAO,QAAQ,MAAM,MAAM;AAAA;AAAA,MAEtC,OAAO,CAAC,MAAM,QAAQ;AAAA,QAClB,OAAO,IAAI;AAAA,QACX,IAAI,QAAQ,KAAK,SAAS;AAAA,UACtB,MAAM,IAAI,MAAM,uDAAuD,IAAI;AAAA,QAC/E,YAAY,OAAO,QAAQ,QAAQ,MAAM;AAAA,QACzC,OAAO,OAAO,QAAQ,MAAM,MAAM;AAAA;AAAA,IAE1C;AAAA,IACA,OAAO;AAAA;AAAA,EAEX,OAAO,OAAO,eAAe,MAAM;AAAA,EACnC,OAAO;AAAA;AAMJ,SAAS,SAAS,CAAC,gBAAgB,KAAK,cAAc,MAAM;AAAA,EAC/D,IAAI,QAAQ;AAAA,IACR,OAAO,IAAI,WAAW,cAAc;AAAA,EACxC,IAAI,IAAI,WAAW;AAAA,IACf,MAAM,IAAI,MAAM,qCAAqC,iBAAiB,YAAY,IAAI,MAAM;AAAA,EAChG,IAAI,eAAe,CAAC,YAAY,GAAG;AAAA,IAC/B,MAAM,IAAI,MAAM,iCAAiC;AAAA,EACrD,OAAO;AAAA;AAGJ,SAAS,YAAY,CAAC,MAAM,YAAY,OAAO,MAAM;AAAA,EACxD,IAAI,OAAO,KAAK,iBAAiB;AAAA,IAC7B,OAAO,KAAK,aAAa,YAAY,OAAO,IAAI;AAAA,EACpD,MAAM,OAAO,OAAO,EAAE;AAAA,EACtB,MAAM,WAAW,OAAO,UAAU;AAAA,EAClC,MAAM,KAAK,OAAQ,SAAS,OAAQ,QAAQ;AAAA,EAC5C,MAAM,KAAK,OAAO,QAAQ,QAAQ;AAAA,EAClC,MAAM,IAAI,OAAO,IAAI;AAAA,EACrB,MAAM,IAAI,OAAO,IAAI;AAAA,EACrB,KAAK,UAAU,aAAa,GAAG,IAAI,IAAI;AAAA,EACvC,KAAK,UAAU,aAAa,GAAG,IAAI,IAAI;AAAA;AAEpC,SAAS,UAAU,CAAC,YAAY,WAAW,MAAM;AAAA,EACpD,MAAM,IAAI;AAAA,EACV,MAAM,MAAM,IAAI,WAAW,EAAE;AAAA,EAC7B,MAAM,OAAO,WAAW,GAAG;AAAA,EAC3B,aAAa,MAAM,GAAG,OAAO,SAAS,GAAG,IAAI;AAAA,EAC7C,aAAa,MAAM,GAAG,OAAO,UAAU,GAAG,IAAI;AAAA,EAC9C,OAAO;AAAA;AAGJ,SAAS,WAAW,CAAC,OAAO;AAAA,EAC/B,OAAO,MAAM,aAAa,MAAM;AAAA;AAG7B,SAAS,SAAS,CAAC,OAAO;AAAA,EAC7B,OAAO,WAAW,KAAK,KAAK;AAAA;;;ACtShC,IAAM,eAAe,CAAC,QAAQ,WAAW,KAAK,IAAI,MAAM,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AACvF,IAAM,UAAU,aAAa,kBAAkB;AAC/C,IAAM,UAAU,aAAa,kBAAkB;AAC/C,IAAM,aAAa,IAAI,OAAO;AAC9B,IAAM,aAAa,IAAI,OAAO;AACvB,SAAS,IAAI,CAAC,GAAG,GAAG;AAAA,EACvB,OAAQ,KAAK,IAAM,MAAO,KAAK;AAAA;AAGnC,SAAS,YAAW,CAAC,GAAG;AAAA,EACpB,OAAO,EAAE,aAAa,MAAM;AAAA;AAGhC,IAAM,YAAY;AAClB,IAAM,cAAc;AAGpB,IAAM,cAAc,KAAK,KAAK;AAC9B,IAAM,YAAY,IAAI;AACtB,SAAS,SAAS,CAAC,MAAM,OAAO,KAAK,OAAO,MAAM,QAAQ,SAAS,QAAQ;AAAA,EACvE,MAAM,MAAM,KAAK;AAAA,EACjB,MAAM,QAAQ,IAAI,WAAW,SAAS;AAAA,EACtC,MAAM,MAAM,IAAI,KAAK;AAAA,EAErB,MAAM,YAAY,aAAY,IAAI,KAAK,aAAY,MAAM;AAAA,EACzD,MAAM,MAAM,YAAY,IAAI,IAAI,IAAI;AAAA,EACpC,MAAM,MAAM,YAAY,IAAI,MAAM,IAAI;AAAA,EACtC,SAAS,MAAM,EAAG,MAAM,KAAK,WAAW;AAAA,IACpC,KAAK,OAAO,KAAK,OAAO,KAAK,SAAS,MAAM;AAAA,IAC5C,IAAI,WAAW;AAAA,MACX,MAAM,IAAI,MAAM,uBAAuB;AAAA,IAC3C,MAAM,OAAO,KAAK,IAAI,WAAW,MAAM,GAAG;AAAA,IAE1C,IAAI,aAAa,SAAS,WAAW;AAAA,MACjC,MAAM,QAAQ,MAAM;AAAA,MACpB,IAAI,MAAM,MAAM;AAAA,QACZ,MAAM,IAAI,MAAM,6BAA6B;AAAA,MACjD,SAAS,IAAI,GAAG,KAAM,IAAI,aAAa,KAAK;AAAA,QACxC,OAAO,QAAQ;AAAA,QACf,IAAI,QAAQ,IAAI,QAAQ,IAAI;AAAA,MAChC;AAAA,MACA,OAAO;AAAA,MACP;AAAA,IACJ;AAAA,IACA,SAAS,IAAI,GAAG,KAAM,IAAI,MAAM,KAAK;AAAA,MACjC,OAAO,MAAM;AAAA,MACb,OAAO,QAAQ,KAAK,QAAQ,MAAM;AAAA,IACtC;AAAA,IACA,OAAO;AAAA,EACX;AAAA;AAGG,SAAS,YAAY,CAAC,MAAM,MAAM;AAAA,EACrC,QAAQ,gBAAgB,eAAe,eAAe,cAAc,WAAW,UAAU,EAAE,gBAAgB,OAAO,eAAe,GAAG,cAAc,OAAO,QAAQ,GAAG,GAAG,IAAI;AAAA,EAC3K,IAAI,OAAO,SAAS;AAAA,IAChB,MAAM,IAAI,MAAM,yBAAyB;AAAA,EAC7C,QAAQ,aAAa;AAAA,EACrB,QAAQ,MAAM;AAAA,EACd,MAAM,YAAY;AAAA,EAClB,MAAM,cAAc;AAAA,EACpB,OAAO,CAAC,KAAK,OAAO,MAAM,QAAQ,UAAU,MAAM;AAAA,IAC9C,OAAO,GAAG;AAAA,IACV,OAAO,KAAK;AAAA,IACZ,OAAO,IAAI;AAAA,IACX,MAAM,MAAM,KAAK;AAAA,IACjB,IAAI,WAAW;AAAA,MACX,SAAS,IAAI,WAAW,GAAG;AAAA,IAC/B,OAAO,MAAM;AAAA,IACb,QAAQ,OAAO;AAAA,IACf,IAAI,UAAU,KAAK,WAAW;AAAA,MAC1B,MAAM,IAAI,MAAM,uBAAuB;AAAA,IAC3C,IAAI,OAAO,SAAS;AAAA,MAChB,MAAM,IAAI,MAAM,gBAAgB,OAAO,iCAAiC,MAAM;AAAA,IAClF,MAAM,UAAU,CAAC;AAAA,IAIjB,IAAI,IAAI,IAAI;AAAA,IACZ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI,MAAM,IAAI;AAAA,MACV,QAAQ,KAAM,IAAI,UAAU,GAAG,CAAE;AAAA,MACjC,QAAQ;AAAA,IACZ,EACK,SAAI,MAAM,MAAM,gBAAgB;AAAA,MACjC,IAAI,IAAI,WAAW,EAAE;AAAA,MACrB,EAAE,IAAI,GAAG;AAAA,MACT,EAAE,IAAI,KAAK,EAAE;AAAA,MACb,QAAQ;AAAA,MACR,QAAQ,KAAK,CAAC;AAAA,IAClB,EACK;AAAA,MACD,MAAM,IAAI,MAAM,wCAAwC,GAAG;AAAA;AAAA,IAS/D,IAAI,CAAC,aAAY,KAAK;AAAA,MAClB,QAAQ,KAAM,QAAQ,UAAU,KAAK,CAAE;AAAA,IAC3C,MAAM,MAAM,IAAI,CAAC;AAAA,IAEjB,IAAI,eAAe;AAAA,MACf,IAAI,MAAM,WAAW;AAAA,QACjB,MAAM,IAAI,MAAM,sCAAsC;AAAA,MAC1D,cAAc,OAAO,KAAK,IAAI,MAAM,SAAS,GAAG,EAAE,CAAC,GAAG,GAAG;AAAA,MACzD,QAAQ,MAAM,SAAS,EAAE;AAAA,IAC7B;AAAA,IAEA,MAAM,aAAa,KAAK;AAAA,IACxB,IAAI,eAAe,MAAM;AAAA,MACrB,MAAM,IAAI,MAAM,sBAAsB,wBAAwB;AAAA,IAElE,IAAI,eAAe,IAAI;AAAA,MACnB,MAAM,KAAK,IAAI,WAAW,EAAE;AAAA,MAC5B,GAAG,IAAI,OAAO,eAAe,IAAI,KAAK,MAAM,MAAM;AAAA,MAClD,QAAQ;AAAA,MACR,QAAQ,KAAK,KAAK;AAAA,IACtB;AAAA,IACA,MAAM,MAAM,IAAI,KAAK;AAAA,IACrB,UAAU,MAAM,OAAO,KAAK,KAAK,MAAM,QAAQ,SAAS,MAAM;AAAA,IAC9D,MAAM,GAAG,OAAO;AAAA,IAChB,OAAO;AAAA;AAAA;;;ACnJf,IAAM,SAAS,CAAC,GAAG,MAAO,EAAE,OAAO,OAAU,EAAE,OAAO,QAAS;AAAA;AAC/D,MAAM,SAAS;AAAA,EACX,WAAW,CAAC,KAAK;AAAA,IACb,KAAK,WAAW;AAAA,IAChB,KAAK,YAAY;AAAA,IACjB,KAAK,SAAS,IAAI,WAAW,EAAE;AAAA,IAC/B,KAAK,IAAI,IAAI,YAAY,EAAE;AAAA,IAC3B,KAAK,IAAI,IAAI,YAAY,EAAE;AAAA,IAC3B,KAAK,MAAM,IAAI,YAAY,CAAC;AAAA,IAC5B,KAAK,MAAM;AAAA,IACX,KAAK,WAAW;AAAA,IAChB,MAAM,QAAQ,GAAG;AAAA,IACjB,OAAO,KAAK,EAAE;AAAA,IACd,MAAM,KAAK,OAAO,KAAK,CAAC;AAAA,IACxB,MAAM,KAAK,OAAO,KAAK,CAAC;AAAA,IACxB,MAAM,KAAK,OAAO,KAAK,CAAC;AAAA,IACxB,MAAM,KAAK,OAAO,KAAK,CAAC;AAAA,IACxB,MAAM,KAAK,OAAO,KAAK,CAAC;AAAA,IACxB,MAAM,KAAK,OAAO,KAAK,EAAE;AAAA,IACzB,MAAM,KAAK,OAAO,KAAK,EAAE;AAAA,IACzB,MAAM,KAAK,OAAO,KAAK,EAAE;AAAA,IAEzB,KAAK,EAAE,KAAK,KAAK;AAAA,IACjB,KAAK,EAAE,MAAO,OAAO,KAAO,MAAM,KAAM;AAAA,IACxC,KAAK,EAAE,MAAO,OAAO,KAAO,MAAM,KAAM;AAAA,IACxC,KAAK,EAAE,MAAO,OAAO,IAAM,MAAM,KAAM;AAAA,IACvC,KAAK,EAAE,MAAO,OAAO,IAAM,MAAM,MAAO;AAAA,IACxC,KAAK,EAAE,KAAM,OAAO,IAAK;AAAA,IACzB,KAAK,EAAE,MAAO,OAAO,KAAO,MAAM,KAAM;AAAA,IACxC,KAAK,EAAE,MAAO,OAAO,KAAO,MAAM,KAAM;AAAA,IACxC,KAAK,EAAE,MAAO,OAAO,IAAM,MAAM,KAAM;AAAA,IACvC,KAAK,EAAE,KAAM,OAAO,IAAK;AAAA,IACzB,SAAS,IAAI,EAAG,IAAI,GAAG;AAAA,MACnB,KAAK,IAAI,KAAK,OAAO,KAAK,KAAK,IAAI,CAAC;AAAA;AAAA,EAE5C,OAAO,CAAC,MAAM,QAAQ,SAAS,OAAO;AAAA,IAClC,MAAM,QAAQ,SAAS,IAAI,KAAK;AAAA,IAChC,QAAQ,GAAG,MAAM;AAAA,IACjB,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,EAAE;AAAA,IACb,MAAM,KAAK,OAAO,MAAM,SAAS,CAAC;AAAA,IAClC,MAAM,KAAK,OAAO,MAAM,SAAS,CAAC;AAAA,IAClC,MAAM,KAAK,OAAO,MAAM,SAAS,CAAC;AAAA,IAClC,MAAM,KAAK,OAAO,MAAM,SAAS,CAAC;AAAA,IAClC,MAAM,KAAK,OAAO,MAAM,SAAS,CAAC;AAAA,IAClC,MAAM,KAAK,OAAO,MAAM,SAAS,EAAE;AAAA,IACnC,MAAM,KAAK,OAAO,MAAM,SAAS,EAAE;AAAA,IACnC,MAAM,KAAK,OAAO,MAAM,SAAS,EAAE;AAAA,IACnC,IAAI,KAAK,EAAE,MAAM,KAAK;AAAA,IACtB,IAAI,KAAK,EAAE,OAAQ,OAAO,KAAO,MAAM,KAAM;AAAA,IAC7C,IAAI,KAAK,EAAE,OAAQ,OAAO,KAAO,MAAM,KAAM;AAAA,IAC7C,IAAI,KAAK,EAAE,OAAQ,OAAO,IAAM,MAAM,KAAM;AAAA,IAC5C,IAAI,KAAK,EAAE,OAAQ,OAAO,IAAM,MAAM,MAAO;AAAA,IAC7C,IAAI,KAAK,EAAE,MAAO,OAAO,IAAK;AAAA,IAC9B,IAAI,KAAK,EAAE,OAAQ,OAAO,KAAO,MAAM,KAAM;AAAA,IAC7C,IAAI,KAAK,EAAE,OAAQ,OAAO,KAAO,MAAM,KAAM;AAAA,IAC7C,IAAI,KAAK,EAAE,OAAQ,OAAO,IAAM,MAAM,KAAM;AAAA,IAC5C,IAAI,KAAK,EAAE,MAAO,OAAO,IAAK;AAAA,IAC9B,IAAI,IAAI;AAAA,IACR,IAAI,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IACjF,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IAChF,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IAC3E,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IAChF,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IACrE,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IAChF,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI;AAAA,IAC/D,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IAChF,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,IAC1D,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IAChF,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,IAC1D,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,KAAK,KAAK,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IAC1E,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,IAC1D,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IACpE,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,IAC1D,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IAC9D,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,IAC1D,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI;AAAA,IACxD,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,IAC1D,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,IACnD,KAAK,OAAO;AAAA,IACZ,MAAM;AAAA,IACN,KAAM,KAAK,KAAK,IAAK;AAAA,IACrB,IAAK,IAAI,KAAM;AAAA,IACf,KAAK,IAAI;AAAA,IACT,IAAI,MAAM;AAAA,IACV,MAAM;AAAA,IACN,EAAE,KAAK;AAAA,IACP,EAAE,KAAK;AAAA,IACP,EAAE,KAAK;AAAA,IACP,EAAE,KAAK;AAAA,IACP,EAAE,KAAK;AAAA,IACP,EAAE,KAAK;AAAA,IACP,EAAE,KAAK;AAAA,IACP,EAAE,KAAK;AAAA,IACP,EAAE,KAAK;AAAA,IACP,EAAE,KAAK;AAAA;AAAA,EAEX,QAAQ,GAAG;AAAA,IACP,QAAQ,GAAG,QAAQ;AAAA,IACnB,MAAM,IAAI,IAAI,YAAY,EAAE;AAAA,IAC5B,IAAI,IAAI,EAAE,OAAO;AAAA,IACjB,EAAE,MAAM;AAAA,IACR,SAAS,IAAI,EAAG,IAAI,IAAI,KAAK;AAAA,MACzB,EAAE,MAAM;AAAA,MACR,IAAI,EAAE,OAAO;AAAA,MACb,EAAE,MAAM;AAAA,IACZ;AAAA,IACA,EAAE,MAAM,IAAI;AAAA,IACZ,IAAI,EAAE,OAAO;AAAA,IACb,EAAE,MAAM;AAAA,IACR,EAAE,MAAM;AAAA,IACR,IAAI,EAAE,OAAO;AAAA,IACb,EAAE,MAAM;AAAA,IACR,EAAE,MAAM;AAAA,IACR,EAAE,KAAK,EAAE,KAAK;AAAA,IACd,IAAI,EAAE,OAAO;AAAA,IACb,EAAE,MAAM;AAAA,IACR,SAAS,IAAI,EAAG,IAAI,IAAI,KAAK;AAAA,MACzB,EAAE,KAAK,EAAE,KAAK;AAAA,MACd,IAAI,EAAE,OAAO;AAAA,MACb,EAAE,MAAM;AAAA,IACZ;AAAA,IACA,EAAE,MAAM,KAAK;AAAA,IACb,IAAI,QAAQ,IAAI,KAAK;AAAA,IACrB,SAAS,IAAI,EAAG,IAAI,IAAI;AAAA,MACpB,EAAE,MAAM;AAAA,IACZ,OAAO,CAAC;AAAA,IACR,SAAS,IAAI,EAAG,IAAI,IAAI;AAAA,MACpB,EAAE,KAAM,EAAE,KAAK,OAAQ,EAAE;AAAA,IAC7B,EAAE,MAAM,EAAE,KAAM,EAAE,MAAM,MAAO;AAAA,IAC/B,EAAE,MAAO,EAAE,OAAO,IAAM,EAAE,MAAM,MAAO;AAAA,IACvC,EAAE,MAAO,EAAE,OAAO,IAAM,EAAE,MAAM,KAAM;AAAA,IACtC,EAAE,MAAO,EAAE,OAAO,IAAM,EAAE,MAAM,KAAM;AAAA,IACtC,EAAE,MAAO,EAAE,OAAO,KAAO,EAAE,MAAM,IAAM,EAAE,MAAM,MAAO;AAAA,IACtD,EAAE,MAAO,EAAE,OAAO,IAAM,EAAE,MAAM,MAAO;AAAA,IACvC,EAAE,MAAO,EAAE,OAAO,IAAM,EAAE,MAAM,KAAM;AAAA,IACtC,EAAE,MAAO,EAAE,OAAO,IAAM,EAAE,MAAM,KAAM;AAAA,IACtC,IAAI,IAAI,EAAE,KAAK,IAAI;AAAA,IACnB,EAAE,KAAK,IAAI;AAAA,IACX,SAAS,IAAI,EAAG,IAAI,GAAG,KAAK;AAAA,MACxB,KAAO,EAAE,KAAK,IAAI,KAAM,MAAM,MAAM,MAAO;AAAA,MAC3C,EAAE,KAAK,IAAI;AAAA,IACf;AAAA,IACA,MAAM,CAAC;AAAA;AAAA,EAEX,MAAM,CAAC,MAAM;AAAA,IACT,QAAQ,IAAI;AAAA,IACZ,OAAO,QAAQ,IAAI;AAAA,IACnB,OAAO,IAAI;AAAA,IACX,QAAQ,QAAQ,aAAa;AAAA,IAC7B,MAAM,MAAM,KAAK;AAAA,IACjB,SAAS,MAAM,EAAG,MAAM,OAAM;AAAA,MAC1B,MAAM,OAAO,KAAK,IAAI,WAAW,KAAK,KAAK,MAAM,GAAG;AAAA,MAEpD,IAAI,SAAS,UAAU;AAAA,QACnB,MAAO,YAAY,MAAM,KAAK,OAAO;AAAA,UACjC,KAAK,QAAQ,MAAM,GAAG;AAAA,QAC1B;AAAA,MACJ;AAAA,MACA,OAAO,IAAI,KAAK,SAAS,KAAK,MAAM,IAAI,GAAG,KAAK,GAAG;AAAA,MACnD,KAAK,OAAO;AAAA,MACZ,OAAO;AAAA,MACP,IAAI,KAAK,QAAQ,UAAU;AAAA,QACvB,KAAK,QAAQ,QAAQ,GAAG,KAAK;AAAA,QAC7B,KAAK,MAAM;AAAA,MACf;AAAA,IACJ;AAAA,IACA,OAAO;AAAA;AAAA,EAEX,OAAO,GAAG;AAAA,IACN,MAAM,KAAK,GAAG,KAAK,GAAG,KAAK,QAAQ,KAAK,GAAG;AAAA;AAAA,EAE/C,UAAU,CAAC,KAAK;AAAA,IACZ,QAAQ,IAAI;AAAA,IACZ,QAAQ,KAAK,IAAI;AAAA,IACjB,KAAK,WAAW;AAAA,IAChB,QAAQ,QAAQ,MAAM;AAAA,IACtB,MAAM,QAAQ;AAAA,IACd,IAAI,KAAK;AAAA,MACL,OAAO,SAAS;AAAA,MAChB,MAAO,MAAM,IAAI;AAAA,QACb,OAAO,OAAO;AAAA,MAClB,KAAK,QAAQ,QAAQ,GAAG,IAAI;AAAA,IAChC;AAAA,IACA,KAAK,SAAS;AAAA,IACd,IAAI,OAAO;AAAA,IACX,SAAS,IAAI,EAAG,IAAI,GAAG,KAAK;AAAA,MACxB,IAAI,UAAU,EAAE,OAAO;AAAA,MACvB,IAAI,UAAU,EAAE,OAAO;AAAA,IAC3B;AAAA,IACA,OAAO;AAAA;AAAA,EAEX,MAAM,GAAG;AAAA,IACL,QAAQ,QAAQ,cAAc;AAAA,IAC9B,KAAK,WAAW,MAAM;AAAA,IACtB,MAAM,MAAM,OAAO,MAAM,GAAG,SAAS;AAAA,IACrC,KAAK,QAAQ;AAAA,IACb,OAAO;AAAA;AAEf;AACO,SAAS,sBAAsB,CAAC,UAAU;AAAA,EAC7C,MAAM,QAAQ,CAAC,KAAK,QAAQ,SAAS,GAAG,EAAE,OAAO,QAAQ,GAAG,CAAC,EAAE,OAAO;AAAA,EACtE,MAAM,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;AAAA,EACvC,MAAM,YAAY,IAAI;AAAA,EACtB,MAAM,WAAW,IAAI;AAAA,EACrB,MAAM,SAAS,CAAC,QAAQ,SAAS,GAAG;AAAA,EACpC,OAAO;AAAA;AAGJ,IAAM,WAAW,uBAAuB,CAAC,QAAQ,IAAI,SAAS,GAAG,CAAC;;;AC9PzE,SAAS,UAAU,CAAC,GAAG,GAAG,GAAG,KAAK,KAAK,SAAS,IAAI;AAAA,EAChD,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,IAChD,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,IAC5C,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,IAC5C,MAAM,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE;AAAA,EAE3C,IAAI,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM;AAAA,EAC/K,SAAS,IAAI,EAAG,IAAI,QAAQ,KAAK,GAAG;AAAA,IAChC,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,M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M,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM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",
|
|
27
|
+
"debugId": "EA1F81AA6907139F64756E2164756E21",
|
|
28
|
+
"names": []
|
|
29
|
+
}
|