@squord/sdk 0.0.0-stage → 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/TypedEmitter.ts","../src/managers/appCommands.ts","../src/managers/bots.ts","../src/managers/channels.ts","../src/errors/index.ts","../src/builders/components.ts","../src/builders/embed.ts","../src/builders/message.ts","../src/managers/interactions.ts","../src/managers/members.ts","../src/utils/misc.ts","../src/managers/messages.ts","../src/managers/uploads.ts","../src/logger.ts","../src/utils/backoff.ts","../src/rest/RestClient.ts","../src/gateway/WebSocketLike.ts","../src/types/gateway.ts","../src/gateway/Gateway.ts","../src/structures/base.ts","../src/permissions.ts","../src/types/api.ts","../src/structures/User.ts","../src/structures/Message.ts","../src/structures/Channel.ts","../src/structures/Interaction.ts","../src/utils/snowflake.ts","../src/cache/Cache.ts","../src/client/SquordClient.ts","../src/commands/CommandRegistry.ts","../src/rest/pagination.ts","../src/intents.ts"],"sourcesContent":["/**\n * Event emitter tipado, sem dependências externas.\n *\n * Suporta `on`, `once`, `off` e `emit`, com mapa de eventos estritamente\n * tipado. Handlers síncronos e assíncronos são aceitos; erros de handlers\n * assíncronos são capturados e entregues ao evento `error` da mesma instância\n * (ou `uncaught`), sem derrubar o processo.\n */\n\nexport type EventHandler<K> = [K] extends [unknown[]] ? (...args: K) => unknown : (payload: K) => unknown;\n\n/** Converte o tipo de payload em tupla de argumentos (sem distribuir unions). */\ntype ArgsOf<K> = [K] extends [unknown[]] ? K : [K];\n\nexport interface EventMap {\n [event: string]: unknown;\n}\n\nexport class TypedEmitter<Events extends EventMap> {\n private handlers = new Map<keyof Events, Set<EventHandler<never>>>();\n\n /** Registra um handler. Devolve uma função que o remove. */\n on<E extends keyof Events>(event: E, handler: EventHandler<Events[E]>): () => void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler as EventHandler<never>);\n return () => this.off(event, handler);\n }\n\n /** Registra um handler que é removido após a primeira chamada. */\n once<E extends keyof Events>(event: E, handler: EventHandler<Events[E]>): () => void {\n const wrapper = ((...args: ArgsOf<Events[E]>) => {\n this.off(event, wrapper as EventHandler<Events[E]>);\n void (handler as (...a: unknown[]) => unknown)(...args);\n }) as unknown as EventHandler<Events[E]>;\n return this.on(event, wrapper);\n }\n\n /** Remove um handler (ou todos do evento, se omitido). */\n off<E extends keyof Events>(event: E, handler?: EventHandler<Events[E]>): void {\n if (!handler) {\n this.handlers.delete(event);\n return;\n }\n this.handlers.get(event)?.delete(handler as EventHandler<never>);\n }\n\n /** Remove todos os handlers de todos os eventos. */\n removeAllListeners(): void {\n this.handlers.clear();\n }\n\n /** Emite um evento. Erros síncronos de handlers propagam para `error`. */\n emit<E extends keyof Events>(event: E, ...args: ArgsOf<Events[E]>): boolean {\n const set = this.handlers.get(event);\n if (!set || set.size === 0) return false;\n for (const handler of [...set]) {\n try {\n const result = (handler as (...a: unknown[]) => unknown)(...args);\n if (result instanceof Promise) {\n void result.catch((err: unknown) => this.handleAsyncError(event, err));\n }\n } catch (err) {\n this.handleAsyncError(event, err);\n }\n }\n return true;\n }\n\n /** Quantos handlers estão registrados para um evento. */\n listenerCount<E extends keyof Events>(event: E): number {\n return this.handlers.get(event)?.size ?? 0;\n }\n\n /** Nomes de eventos com pelo menos um handler. */\n eventNames(): Array<keyof Events> {\n return [...this.handlers.keys()].filter((k) => (this.handlers.get(k)?.size ?? 0) > 0);\n }\n\n private handleAsyncError(event: keyof Events, err: unknown): void {\n if (event === \"error\") throw err;\n const error = err instanceof Error ? err : new Error(String(err));\n (this.emit as unknown as (event: \"error\", payload: Error) => void)(\"error\", error);\n }\n}\n","/**\n * Manager de comandos de aplicação (slash).\n *\n * Registrar é uma **sobrescrita em bloco** (`PUT`): a lista enviada substitui\n * a anterior — comandos fora da lista são apagados; um comando cujo nome\n * continua mantém o `id`. O padrão é registrar a lista inteira na partida\n * do bot, sempre a mesma.\n *\n * Escopos: global (`PUT /bots/@me/commands`, vale em todos os Spaces do bot)\n * ou por Space (`PUT /bots/@me/guilds/{guild.id}/commands`). O limite é\n * `COMMANDS_UPDATE`: 10 sobrescritas por minuto.\n */\n\nimport type { RestClient } from \"../rest/RestClient\";\nimport type { APICommand, APICommandInput } from \"../types/api\";\nimport type { Snowflake } from \"../types/common\";\n\nexport class ApplicationCommandsManager {\n constructor(private readonly rest: RestClient) {}\n\n /** Lista os comandos globais do bot. */\n listGlobal(signal?: AbortSignal): Promise<APICommand[]> {\n return this.rest.get<APICommand[]>(\"/bots/@me/commands\", { signal });\n }\n\n /** Sobrescreve os comandos globais (idempotente por ser PUT). */\n setGlobal(commands: APICommandInput[], signal?: AbortSignal): Promise<APICommand[]> {\n return this.rest.put<APICommand[]>(\"/bots/@me/commands\", commands, { signal });\n }\n\n /** Lista os comandos de um Space. */\n listGuild(guildId: Snowflake, signal?: AbortSignal): Promise<APICommand[]> {\n return this.rest.get<APICommand[]>(`/bots/@me/guilds/${guildId}/commands`, { signal });\n }\n\n /** Sobrescreve os comandos de um Space (o bot precisa estar instalado nele). */\n setGuild(guildId: Snowflake, commands: APICommandInput[], signal?: AbortSignal): Promise<APICommand[]> {\n return this.rest.put<APICommand[]>(`/bots/@me/guilds/${guildId}/commands`, commands, {\n signal,\n });\n }\n}\n","/**\n * Manager do próprio bot e de usuários.\n */\n\nimport type { RestClient } from \"../rest/RestClient\";\nimport type { APIBot, APICurrentUser } from \"../types/api\";\nimport type { Snowflake } from \"../types/common\";\n\nexport class BotManager {\n constructor(private readonly rest: RestClient) {}\n\n /** `GET /bots/@me`: o bot na visão do dono (inclui as intents configuradas). */\n fetchCurrent(signal?: AbortSignal): Promise<APIBot> {\n return this.rest.get<APIBot>(\"/bots/@me\", { signal });\n }\n\n /** `GET /bots/{botId}`: o cartão público de um bot. */\n fetch(botId: Snowflake, signal?: AbortSignal): Promise<APIBot> {\n return this.rest.get<APIBot>(`/bots/${botId}`, { signal });\n }\n}\n\nexport class UsersManager {\n constructor(private readonly rest: RestClient) {}\n\n /** `GET /users/@me`: a própria conta (em um bot, campos privados são padrão). */\n fetchMe(signal?: AbortSignal): Promise<APICurrentUser> {\n return this.rest.get<APICurrentUser>(\"/users/@me\", { signal });\n }\n}\n","/**\n * Manager de canais e threads: consultar, listar a árvore do Space e\n * criar threads e posts de fórum.\n */\n\nimport type { RestClient } from \"../rest/RestClient\";\nimport type {\n APIChannel,\n APIChannelTreeNode,\n APIForumPostCreateBody,\n APIThread,\n APIThreadCreateBody,\n APIThreadListParams,\n APIThreadPage,\n} from \"../types/api\";\nimport type { Snowflake } from \"../types/common\";\n\nexport class ChannelsManager {\n constructor(private readonly rest: RestClient) {}\n\n /** Busca um canal (ou uma thread, que também é canal) pelo id. */\n fetch(channelId: Snowflake, signal?: AbortSignal): Promise<APIChannel> {\n return this.rest.get<APIChannel>(`/channels/${channelId}`, { signal });\n }\n\n /**\n * Lista a árvore de canais do Space: grupos por categoria.\n * Requer que o bot veja os canais (`VIEW_CHANNEL` do cargo dele).\n */\n fetchTree(guildId: Snowflake, signal?: AbortSignal): Promise<APIChannelTreeNode[]> {\n return this.rest.get<APIChannelTreeNode[]>(`/guilds/${guildId}/channels`, { signal });\n }\n\n /** Cria uma thread em um canal de texto ou de anúncios. */\n createThread(\n channelId: Snowflake,\n body: APIThreadCreateBody,\n options: { signal?: AbortSignal } = {},\n ): Promise<APIThread> {\n return this.rest.post<APIThread>(`/channels/${channelId}/threads`, body, {\n signal: options.signal,\n retryable: false,\n });\n }\n\n /** Cria um post em um canal de fórum (a primeira mensagem vai no corpo). */\n createForumPost(\n channelId: Snowflake,\n body: APIForumPostCreateBody,\n options: { signal?: AbortSignal } = {},\n ): Promise<APIThread> {\n return this.rest.post<APIThread>(`/channels/${channelId}/threads`, body, {\n signal: options.signal,\n retryable: false,\n });\n }\n\n /** Cria uma thread a partir de uma mensagem de um canal de texto/anúncios. */\n createThreadFromMessage(\n channelId: Snowflake,\n messageId: Snowflake,\n body: APIThreadCreateBody,\n options: { signal?: AbortSignal } = {},\n ): Promise<APIThread> {\n return this.rest.post<APIThread>(\n `/channels/${channelId}/messages/${messageId}/threads`,\n body,\n { signal: options.signal, retryable: false },\n );\n }\n\n /** Lista uma página de threads do canal (`cursor` = `nextCursor` anterior). */\n listThreads(\n channelId: Snowflake,\n params: APIThreadListParams = {},\n signal?: AbortSignal,\n ): Promise<APIThreadPage> {\n return this.rest.get<APIThreadPage>(`/channels/${channelId}/threads`, {\n query: {\n limit: params.limit,\n cursor: params.after ?? params.before,\n archived: params.archived,\n tagId: params.tagId,\n },\n signal,\n });\n }\n}\n","/**\n * Hierarquia de erros do SDK.\n *\n * A API devolve um envelope único (`statusCode`, `code`, `message`, `details`,\n * `requestId`). Decida pelo `code`, nunca pela `message`. Cada erro do SDK\n * expõe propriedades consistentes: `code`, `status`, `requestId`,\n * `retryAfter` e `cause`, quando aplicáveis.\n *\n * @see https://docs.squord.com.br/referencia/erros\n */\n\nimport type { APIErrorBody, APIRateLimitDetails, APIValidationIssue } from \"../types/api\";\n\n/** Base de todos os erros lançados pelo SDK. */\nexport class SquordError extends Error {\n /** Código estável do erro, em `SCREAMING_SNAKE`. */\n readonly code: string;\n\n constructor(code: string, message: string, options?: { cause?: unknown }) {\n super(message, options as ErrorOptions);\n this.name = new.target.name;\n this.code = code;\n }\n}\n\n/**\n * Erro devolvido pela API REST do Squord. Teste sempre pelo `code`\n * (ex.: `err.code === \"MISSING_PERMISSION\"`), nunca pela `message`.\n */\nexport class SquordAPIError extends SquordError {\n /** Status HTTP da resposta. */\n readonly status: number;\n /** O mesmo valor do header `x-request-id` da resposta. */\n readonly requestId: string | null;\n /** Corpo bruto do erro (o envelope completo), quando disponível. */\n readonly responseBody: APIErrorBody | null;\n /** `details` do envelope, quando existe. */\n readonly details: unknown;\n\n constructor(body: APIErrorBody, status: number, requestId?: string | null) {\n super(body.code, body.message ?? `Erro da API do Squord (HTTP ${status})`);\n this.status = status;\n this.requestId = requestId ?? body.requestId ?? null;\n this.details = body.details;\n this.responseBody = body;\n }\n}\n\n/** `401 UNAUTHENTICATED` — não há credencial na requisição. */\nexport class AuthenticationError extends SquordAPIError {}\n\n/** `401 INVALID_TOKEN` — token malformado, revogado ou trocado, ou bot/dono excluído ou suspenso. */\nexport class InvalidTokenError extends AuthenticationError {}\n\n/** `403` — a credencial é válida, mas a ação não é permitida (`MISSING_PERMISSION`, `FORBIDDEN`, `NOT_A_MEMBER`, ...). */\nexport class PermissionError extends SquordAPIError {\n /** Nome da permissão que faltou, quando o erro é `MISSING_PERMISSION`. */\n readonly missingPermission: string | null;\n\n constructor(body: APIErrorBody, status: number, requestId?: string | null) {\n super(body, status, requestId);\n const details = body.details as { permission?: string } | null | undefined;\n this.missingPermission = details?.permission ?? null;\n }\n}\n\n/** `404` — recurso inexistente ou invisível para o bot. */\nexport class NotFoundError extends SquordAPIError {}\n\n/** `422 VALIDATION_FAILED` — corpo bem formado, mas inválido. */\nexport class ValidationError extends SquordAPIError {\n /** Os itens de validação (campo, código do item, limite violado). */\n readonly issues: APIValidationIssue[];\n\n constructor(body: APIErrorBody, status: number, requestId?: string | null) {\n super(body, status, requestId);\n this.issues = Array.isArray(body.details) ? (body.details as APIValidationIssue[]) : [];\n }\n}\n\n/** `429 RATE_LIMITED` — limite de taxa. Espere `retryAfter` segundos. */\nexport class RateLimitError extends SquordAPIError {\n /** Segundos de espera informados pelo servidor (mínimo 1). */\n readonly retryAfter: number;\n /** O bucket que recusou (`MESSAGE_CREATE`, `BOT_GLOBAL`, ...). */\n readonly bucket: string | null;\n /** `true` quando o SDK já esgotou as retentativas automáticas. */\n readonly exhaustedRetries: boolean;\n\n constructor(\n body: APIErrorBody,\n status: number,\n options?: { requestId?: string | null; exhaustedRetries?: boolean },\n ) {\n super(body, status, options?.requestId);\n const details = body.details as APIRateLimitDetails | null | undefined;\n this.retryAfter = details?.retryAfter ?? 1;\n this.bucket = details?.bucket ?? null;\n this.exhaustedRetries = options?.exhaustedRetries ?? false;\n }\n}\n\n/** Falha de rede antes de receber qualquer resposta (DNS, TCP, TLS). */\nexport class NetworkError extends SquordError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(\"NETWORK_ERROR\", message, options);\n }\n}\n\n/** A requisição excedeu o tempo limite configurado. */\nexport class RequestTimeoutError extends SquordError {\n /** Milissegundos configurados de timeout. */\n readonly timeoutMs: number;\n /** Método HTTP da requisição que expirou. */\n readonly method: string;\n /** Caminho da requisição que expirou. */\n readonly path: string;\n\n constructor(method: string, path: string, timeoutMs: number, options?: { cause?: unknown }) {\n super(\n \"REQUEST_TIMEOUT\",\n `A requisição ${method} ${path} excedeu o timeout de ${timeoutMs} ms`,\n options,\n );\n this.method = method;\n this.path = path;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** Erro de conexão/fechamento do gateway. */\nexport class GatewayError extends SquordError {\n /** Código de fechamento (4000+) ou `null` em falhas de rede. */\n readonly closeCode: number | null;\n /** Razão textual enviada pelo servidor (informativa; use `closeCode`). */\n readonly reason: string | null;\n\n constructor(closeCode: number | null, reason: string | null, message?: string) {\n super(\n closeCode === null ? \"GATEWAY_NETWORK_ERROR\" : \"GATEWAY_CLOSE\",\n message ?? `Gateway fechou a conexão${closeCode !== null ? ` (código ${closeCode})` : \"\"}${reason ? `: ${reason}` : \"\"}`,\n { cause: undefined },\n );\n this.closeCode = closeCode;\n this.reason = reason;\n }\n}\n\n/** Erro de uso incorreto da API do SDK (argumentos inválidos no cliente). */\nexport class SquordTypeError extends SquordError {\n constructor(message: string) {\n super(\"SDK_INVALID_ARGUMENT\", message);\n }\n}\n\n/**\n * Normaliza um corpo de erro em {@link SquordAPIError} ou uma subclasse.\n * Exportado para testes e uso avançado.\n */\nexport function makeAPIError(\n body: APIErrorBody,\n status: number,\n requestId?: string | null,\n): SquordAPIError {\n switch (status) {\n case 401:\n return body.code === \"INVALID_TOKEN\"\n ? new InvalidTokenError(body, status, requestId)\n : new AuthenticationError(body, status, requestId);\n case 403:\n return new PermissionError(body, status, requestId);\n case 404:\n return new NotFoundError(body, status, requestId);\n case 422:\n return new ValidationError(body, status, requestId);\n case 429:\n return new RateLimitError(body, status, { requestId });\n default:\n return new SquordAPIError(body, status, requestId);\n }\n}\n","/**\n * Builders de componentes: botões e menus de seleção.\n *\n * Regras do Squord: uma mensagem tem até 5 linhas; cada linha guarda até 5\n * botões **ou** exatamente 1 menu (nunca os dois); `customId` é único na\n * mensagem (até 100 caracteres); `link` tem `url` e não tem `customId`.\n */\n\nimport { SquordTypeError } from \"../errors\";\nimport type { APIButton, APIComponentRow, APISelectMenu, APISelectOption, ButtonStyle } from \"../types/api\";\n\nexport const ComponentLimits = {\n RowsPerMessage: 5,\n ButtonsPerRow: 5,\n CustomId: 100,\n Label: 80,\n OptionsPerMenu: 25,\n} as const;\n\nexport class ButtonBuilder {\n private customIdValue: string | undefined;\n private urlValue: string | undefined;\n private disabledValue = false;\n\n constructor(\n private readonly style: ButtonStyle,\n private labelValue: string,\n ) {}\n\n /** Identificador da ação; obrigatório (e único na mensagem) fora do estilo `link`. */\n setCustomId(customId: string): this {\n assertCustomId(customId);\n this.customIdValue = customId;\n return this;\n }\n\n /** URL aberta ao clicar; obrigatória e exclusiva do estilo `link`. */\n setURL(url: string): this {\n if (!/^https:\\/\\//.test(url)) {\n throw new SquordTypeError(`Botão de link exige URL https:// (recebido: ${url})`);\n }\n this.urlValue = url;\n return this;\n }\n\n setDisabled(disabled: boolean): this {\n this.disabledValue = disabled;\n return this;\n }\n\n setLabel(label: string): this {\n this.labelValue = label;\n return this;\n }\n\n build(): APIButton {\n if (this.style === \"link\" && !this.urlValue) {\n throw new SquordTypeError(\"Botão de link exige setURL(...)\");\n }\n if (this.style !== \"link\" && !this.customIdValue) {\n throw new SquordTypeError(`Botão de estilo ${this.style} exige setCustomId(...)`);\n }\n if (this.labelValue.length > ComponentLimits.Label) {\n throw new SquordTypeError(`Label de botão excede ${ComponentLimits.Label} caracteres`);\n }\n return {\n type: \"button\",\n style: this.style,\n label: this.labelValue,\n customId: this.style === \"link\" ? undefined : this.customIdValue,\n url: this.style === \"link\" ? this.urlValue : undefined,\n disabled: this.disabledValue || undefined,\n };\n }\n}\n\nexport class SelectMenuBuilder {\n private placeholderValue: string | undefined;\n private minValuesValue: number | undefined;\n private maxValuesValue: number | undefined;\n private disabledValue = false;\n private optionsValue: APISelectOption[] = [];\n\n constructor(private readonly customId: string) {\n assertCustomId(customId);\n }\n\n setPlaceholder(placeholder: string): this {\n if (placeholder.length > 150) {\n throw new SquordTypeError(\"Placeholder de menu excede 150 caracteres\");\n }\n this.placeholderValue = placeholder;\n return this;\n }\n\n setMinValues(min: number): this {\n this.minValuesValue = min;\n return this;\n }\n\n setMaxValues(max: number): this {\n this.maxValuesValue = max;\n return this;\n }\n\n setDisabled(disabled: boolean): this {\n this.disabledValue = disabled;\n return this;\n }\n\n addOption(option: APISelectOption): this {\n if (this.optionsValue.length >= ComponentLimits.OptionsPerMenu) {\n throw new SquordTypeError(`Menu aceita no máximo ${ComponentLimits.OptionsPerMenu} opções`);\n }\n if (!option.label || !option.value) {\n throw new SquordTypeError(\"Opção de menu exige label e value\");\n }\n if (option.label.length > ComponentLimits.Label || option.value.length > 100) {\n throw new SquordTypeError(\"Label de opção: até 80 caracteres; value: até 100\");\n }\n this.optionsValue.push(option);\n return this;\n }\n\n addOptions(...options: APISelectOption[]): this {\n for (const option of options) this.addOption(option);\n return this;\n }\n\n build(): APISelectMenu {\n if (this.optionsValue.length === 0) {\n throw new SquordTypeError(\"Menu de seleção precisa de ao menos uma opção\");\n }\n const min = this.minValuesValue ?? 1;\n const max = this.maxValuesValue ?? Math.max(1, this.optionsValue.length);\n if (min > max) {\n throw new SquordTypeError(`minValues (${min}) não pode passar de maxValues (${max})`);\n }\n return {\n type: \"select\",\n customId: this.customId,\n placeholder: this.placeholderValue,\n minValues: this.minValuesValue,\n maxValues: this.maxValuesValue,\n disabled: this.disabledValue || undefined,\n options: [...this.optionsValue],\n };\n }\n}\n\nexport class ActionRowBuilder {\n private components: Array<APIButton | APISelectMenu> = [];\n\n /** Adiciona um botão (até 5 por linha). */\n addButton(button: ButtonBuilder | APIButton): this {\n if (this.components.length >= ComponentLimits.ButtonsPerRow || this.components.some((c) => c.type === \"select\")) {\n throw new SquordTypeError(\"Uma linha aceita até 5 botões e não mistura botões com menus\");\n }\n this.components.push(button instanceof ButtonBuilder ? button.build() : button);\n return this;\n }\n\n /** Define o menu da linha (exatamente 1, sozinho). */\n setSelectMenu(menu: SelectMenuBuilder | APISelectMenu): this {\n if (this.components.length > 0) {\n throw new SquordTypeError(\"Um menu ocupa a linha sozinho; não misture com botões\");\n }\n this.components.push(menu instanceof SelectMenuBuilder ? menu.build() : menu);\n return this;\n }\n\n addComponents(...components: Array<ButtonBuilder | SelectMenuBuilder | APIButton | APISelectMenu>): this {\n for (const component of components) {\n if (component instanceof ButtonBuilder || (\"type\" in component && component.type === \"button\")) {\n this.addButton(component as ButtonBuilder | APIButton);\n } else {\n this.setSelectMenu(component as SelectMenuBuilder | APISelectMenu);\n }\n }\n return this;\n }\n\n build(): APIComponentRow {\n if (this.components.length === 0) {\n throw new SquordTypeError(\"Linha de componentes vazia\");\n }\n return { type: \"row\", components: [...this.components] };\n }\n}\n\n/** Atalhos para botões dos quatro estilos. */\nexport const Buttons = {\n primary: (label: string) => new ButtonBuilder(\"primary\", label),\n secondary: (label: string) => new ButtonBuilder(\"secondary\", label),\n danger: (label: string) => new ButtonBuilder(\"danger\", label),\n link: (label: string) => new ButtonBuilder(\"link\", label),\n};\n\nfunction assertCustomId(customId: string): void {\n if (typeof customId !== \"string\" || customId.length < 1 || customId.length > ComponentLimits.CustomId) {\n throw new SquordTypeError(\n `customId precisa ter de 1 a ${ComponentLimits.CustomId} caracteres`,\n );\n }\n}\n","/**\n * `EmbedBuilder`: cria embeds tipados com validação local dos limites reais\n * da plataforma (antes de gastar uma chamada com um `422 VALIDATION_FAILED`).\n *\n * Limites do Squord: 10 embeds por mensagem, 25 campos por embed, título 256,\n * descrição 4096, nome de campo 256, valor de campo 1024, rodapé 2048,\n * autor 256 e 6000 caracteres somando o texto dos embeds da mensagem.\n */\n\nimport { SquordTypeError } from \"../errors\";\nimport type { APIEmbed, APIEmbedInput } from \"../types/api\";\n\nexport const EmbedLimits = {\n EmbedsPerMessage: 10,\n FieldsPerEmbed: 25,\n Title: 256,\n Description: 4096,\n FieldName: 256,\n FieldValue: 1024,\n FooterText: 2048,\n AuthorName: 256,\n TotalTextPerMessage: 6000,\n} as const;\n\ninterface EmbedFieldInput {\n name: string;\n value: string;\n inline?: boolean;\n}\n\nexport interface EmbedAuthorInput {\n name: string;\n url?: string | null;\n iconUrl?: string | null;\n}\n\nexport interface EmbedFooterInput {\n text: string;\n iconUrl?: string | null;\n}\n\n/** Converte cores: `#rrggbb` → inteiro, inteiro → `#rrggbb`. */\nexport function normalizeEmbedColor(color: number | string): number {\n if (typeof color === \"number\") {\n if (!Number.isInteger(color) || color < 0 || color > 0xff_ff_ff) {\n throw new SquordTypeError(\n `Cor de embed inválida: ${color} — use um inteiro de 0 a 16777215 ou \"#rrggbb\"`,\n );\n }\n return color;\n }\n const trimmed = color.trim();\n const hex = trimmed.startsWith(\"#\") ? trimmed.slice(1) : trimmed;\n if (!/^[0-9a-fA-F]{6}$/.test(hex)) {\n throw new SquordTypeError(`Cor de embed inválida: ${JSON.stringify(color)} — use \"#rrggbb\"`);\n }\n return Number.parseInt(hex, 16);\n}\n\nexport class EmbedBuilder {\n private titleValue: string | null = null;\n private descriptionValue: string | null = null;\n private urlValue: string | null = null;\n private colorValue: number | null = null;\n private timestampValue: string | null = null;\n private authorValue: EmbedAuthorInput | null = null;\n private footerValue: EmbedFooterInput | null = null;\n private imageValue: string | null = null;\n private thumbnailValue: string | null = null;\n private fieldsValue: EmbedFieldInput[] = [];\n\n /** Título do embed (até 256 caracteres). */\n setTitle(title: string): this {\n assertLength(\"title\", title, EmbedLimits.Title);\n this.titleValue = title;\n return this;\n }\n\n /** Descrição (até 4096 caracteres). */\n setDescription(description: string): this {\n assertLength(\"description\", description, EmbedLimits.Description);\n this.descriptionValue = description;\n return this;\n }\n\n /** URL do título (só `http://` ou `https://`). */\n setURL(url: string): this {\n assertHttpUrl(\"url\", url);\n this.urlValue = url;\n return this;\n }\n\n /** Cor: inteiro de 0 a 16777215 ou `#rrggbb`. */\n setColor(color: number | string): this {\n this.colorValue = normalizeEmbedColor(color);\n return this;\n }\n\n /** Momento exibido no rodapé. Um `Date` ou string ISO 8601 com fuso. */\n setTimestamp(timestamp: Date | string = new Date()): this {\n this.timestampValue =\n timestamp instanceof Date ? timestamp.toISOString() : timestamp;\n return this;\n }\n\n /** Autor exibido no topo (nome até 256 caracteres). */\n setAuthor(author: EmbedAuthorInput | null): this {\n if (author) {\n assertLength(\"author.name\", author.name, EmbedLimits.AuthorName);\n if (author.url) assertHttpUrl(\"author.url\", author.url);\n }\n this.authorValue = author;\n return this;\n }\n\n /** Rodapé (texto até 2048 caracteres). */\n setFooter(footer: EmbedFooterInput | null): this {\n if (footer) {\n assertLength(\"footer.text\", footer.text, EmbedLimits.FooterText);\n }\n this.footerValue = footer;\n return this;\n }\n\n /** Imagem principal (baixada e hospedada pelo Squord em segundo plano). */\n setImage(url: string): this {\n this.imageValue = url;\n return this;\n }\n\n /** Miniatura. */\n setThumbnail(url: string): this {\n this.thumbnailValue = url;\n return this;\n }\n\n /** Adiciona um campo (nome até 256, valor até 1024). */\n addField(name: string, value: string, inline = false): this {\n return this.addFields({ name, value, inline });\n }\n\n /** Adiciona vários campos. */\n addFields(...fields: EmbedFieldInput[]): this {\n if (this.fieldsValue.length + fields.length > EmbedLimits.FieldsPerEmbed) {\n throw new SquordTypeError(\n `Um embed aceita no máximo ${EmbedLimits.FieldsPerEmbed} campos`,\n );\n }\n for (const field of fields) {\n assertLength(\"field.name\", field.name, EmbedLimits.FieldName);\n assertLength(\"field.value\", field.value, EmbedLimits.FieldValue);\n this.fieldsValue.push(field);\n }\n return this;\n }\n\n /** Remove todos os campos. */\n clearFields(): this {\n this.fieldsValue = [];\n return this;\n }\n\n /** Payload pronto para o campo `embeds` (só campos preenchidos). */\n build(): APIEmbedInput {\n if (\n !this.titleValue &&\n !this.descriptionValue &&\n !this.imageValue &&\n !this.thumbnailValue &&\n this.fieldsValue.length === 0 &&\n !this.footerValue &&\n !this.authorValue\n ) {\n throw new SquordTypeError(\n \"O embed não tem nada visível: defina título, descrição, campos, imagem ou rodapé (o Squord recusa embeds vazios com BLANK)\",\n );\n }\n const embed: APIEmbedInput = {};\n if (this.titleValue) embed.title = this.titleValue;\n if (this.descriptionValue) embed.description = this.descriptionValue;\n if (this.urlValue) embed.url = this.urlValue;\n if (this.colorValue !== null) embed.color = this.colorValue;\n if (this.timestampValue) embed.timestamp = this.timestampValue;\n if (this.authorValue) {\n const author: NonNullable<APIEmbedInput[\"author\"]> = { name: this.authorValue.name };\n if (this.authorValue.url) author.url = this.authorValue.url;\n if (this.authorValue.iconUrl) author.icon_url = this.authorValue.iconUrl;\n embed.author = author;\n }\n if (this.footerValue) {\n const footer: NonNullable<APIEmbedInput[\"footer\"]> = { text: this.footerValue.text };\n if (this.footerValue.iconUrl) footer.icon_url = this.footerValue.iconUrl;\n embed.footer = footer;\n }\n if (this.imageValue) embed.image = { url: this.imageValue };\n if (this.thumbnailValue) embed.thumbnail = { url: this.thumbnailValue };\n if (this.fieldsValue.length > 0) embed.fields = [...this.fieldsValue];\n return embed;\n }\n\n /** Soma dos textos do embed (para conferir o limite de 6000 por mensagem). */\n get textLength(): number {\n let total = 0;\n if (this.titleValue) total += this.titleValue.length;\n if (this.descriptionValue) total += this.descriptionValue.length;\n if (this.footerValue) total += this.footerValue.text.length;\n if (this.authorValue) total += this.authorValue.name.length;\n for (const field of this.fieldsValue) {\n total += field.name.length + field.value.length;\n }\n return total;\n }\n\n /** Cria um builder a partir de um payload existente. */\n static from(embed: APIEmbed | APIEmbedInput): EmbedBuilder {\n const builder = new EmbedBuilder();\n if (embed.title) builder.setTitle(embed.title);\n if (embed.description) builder.setDescription(embed.description);\n if (embed.url) builder.setURL(embed.url);\n if (embed.color != null) builder.setColor(embed.color);\n if (embed.timestamp) builder.setTimestamp(embed.timestamp);\n if (\"author\" in embed && embed.author) {\n builder.setAuthor({\n name: embed.author.name,\n url: \"url\" in embed.author ? (embed.author.url ?? undefined) : undefined,\n iconUrl: \"iconUrl\" in embed.author ? (embed.author.iconUrl ?? undefined) : undefined,\n });\n }\n if (\"footer\" in embed && embed.footer) {\n builder.setFooter({\n text: embed.footer.text,\n iconUrl: \"iconUrl\" in embed.footer ? (embed.footer.iconUrl ?? undefined) : undefined,\n });\n }\n if (\"fields\" in embed && Array.isArray(embed.fields) && embed.fields.length > 0) {\n builder.addFields(...embed.fields);\n }\n const image = \"image\" in embed ? embed.image : null;\n if (image && \"url\" in image) builder.setImage(image.url);\n const thumbnail = \"thumbnail\" in embed ? (embed as APIEmbedInput).thumbnail : null;\n if (thumbnail && \"url\" in thumbnail) builder.setThumbnail(thumbnail.url);\n return builder;\n }\n}\n\nfunction assertLength(field: string, value: string, max: number): void {\n if (value.length > max) {\n throw new SquordTypeError(`Embed.${field} excede ${max} caracteres (${value.length})`);\n }\n}\n\nfunction assertHttpUrl(field: string, url: string): void {\n if (!/^https?:\\/\\//.test(url)) {\n throw new SquordTypeError(`Embed.${field} precisa ser http:// ou https:// (recebido: ${url})`);\n }\n}\n","/**\n * Normalização de payloads de mensagem: aceita strings, objetos crus e\n * builders, e devolve o corpo aceito pela API.\n *\n * Menções são seguras por padrão: quando `allowedMentions` não é informado,\n * o SDK envia `{ users: true, roles: false, everyone: false }` — o padrão\n * da plataforma — evitando menções acidentais em massa.\n */\n\nimport { SquordTypeError } from \"../errors\";\nimport { ActionRowBuilder } from \"./components\";\nimport { EmbedBuilder } from \"./embed\";\nimport type {\n APIComponentRow,\n APIEmbedInput,\n APIMessageCreateBody,\n APIMessageEditBody,\n} from \"../types/api\";\nimport type { AllowedMentions, Snowflake } from \"../types/common\";\n\n/** Payload de envio/edição aceito pelos métodos `send`/`reply`/`edit`. */\nexport interface MessagePayload {\n content?: string;\n embeds?: Array<APIEmbedInput | EmbedBuilder>;\n components?: Array<APIComponentRow | ActionRowBuilder>;\n allowedMentions?: AllowedMentions;\n replyToId?: Snowflake;\n attachmentIds?: Snowflake[];\n nonce?: string;\n ephemeral?: boolean;\n}\n\n/** Uma mensagem pode ser passada como string (só `content`) ou como payload. */\nexport type MessagePayloadLike = string | MessagePayload;\n\nconst SAFE_ALLOWED_MENTIONS: AllowedMentions = { users: true, roles: false, everyone: false };\n\n/** Converte builders e valores crus no formato da API. */\nexport function resolveMessagePayload(\n payload: MessagePayloadLike,\n): APIMessageCreateBody & { ephemeral?: boolean } {\n const source: MessagePayload =\n typeof payload === \"string\" ? { content: payload } : payload;\n\n const body: APIMessageCreateBody & { ephemeral?: boolean } = {};\n let hasVisibleContent = false;\n\n if (source.content !== undefined) {\n if (typeof source.content !== \"string\") {\n throw new SquordTypeError(\"content precisa ser string\");\n }\n if (source.content.length > 4000) {\n throw new SquordTypeError(`content excede 4000 caracteres (${source.content.length})`);\n }\n body.content = source.content;\n if (source.content.length > 0) hasVisibleContent = true;\n }\n\n if (source.embeds !== undefined) {\n if (!Array.isArray(source.embeds) || source.embeds.length > 10) {\n throw new SquordTypeError(\"embeds aceita até 10 itens\");\n }\n body.embeds = source.embeds.map((embed) =>\n embed instanceof EmbedBuilder ? embed.build() : (embed as APIEmbedInput),\n );\n if (body.embeds.length > 0) hasVisibleContent = true;\n }\n\n if (source.components !== undefined) {\n if (!Array.isArray(source.components) || source.components.length > 5) {\n throw new SquordTypeError(\"components aceita até 5 linhas\");\n }\n body.components = source.components.map((row) =>\n row instanceof ActionRowBuilder ? row.build() : (row as APIComponentRow),\n );\n if (body.components.length > 0) hasVisibleContent = true;\n }\n\n // Menções seguras por padrão: sem allowedMentions explícito, o SDK envia\n // o padrão da plataforma (pessoas sim; cargos e @everyone não), tornando\n // a proteção contra menções em massa explícita no payload.\n body.allowedMentions = source.allowedMentions ?? SAFE_ALLOWED_MENTIONS;\n\n if (source.replyToId !== undefined) {\n body.replyToId = source.replyToId;\n }\n\n if (source.attachmentIds !== undefined) {\n if (!Array.isArray(source.attachmentIds) || source.attachmentIds.length > 10) {\n throw new SquordTypeError(\"attachmentIds aceita até 10 itens\");\n }\n body.attachmentIds = source.attachmentIds;\n if (body.attachmentIds.length > 0) hasVisibleContent = true;\n }\n\n if (source.nonce !== undefined) {\n if (typeof source.nonce !== \"string\" || source.nonce.length > 64) {\n throw new SquordTypeError(\"nonce precisa ser string de até 64 caracteres\");\n }\n body.nonce = source.nonce;\n }\n\n if (source.ephemeral !== undefined) {\n body.ephemeral = source.ephemeral;\n }\n\n if (!hasVisibleContent) {\n throw new SquordTypeError(\n \"A mensagem precisa de ao menos um entre content (não vazio), embeds, components e attachmentIds\",\n );\n }\n\n return body;\n}\n\n/** Corpo de edição: o que não for informado continua como estava. */\nexport function resolveMessageEditPayload(payload: MessagePayloadLike): APIMessageEditBody {\n const source: MessagePayload =\n typeof payload === \"string\" ? { content: payload } : payload;\n const body: APIMessageEditBody = {};\n let hasField = false;\n\n if (source.content !== undefined) {\n if (source.content.length > 4000) {\n throw new SquordTypeError(`content excede 4000 caracteres (${source.content.length})`);\n }\n body.content = source.content;\n hasField = true;\n }\n if (source.embeds !== undefined) {\n body.embeds = source.embeds.map((embed) =>\n embed instanceof EmbedBuilder ? embed.build() : (embed as APIEmbedInput),\n );\n hasField = true;\n }\n if (source.components !== undefined) {\n body.components = source.components.map((row) =>\n row instanceof ActionRowBuilder ? row.build() : (row as APIComponentRow),\n );\n hasField = true;\n }\n if (source.allowedMentions !== undefined) {\n body.allowedMentions = source.allowedMentions;\n }\n if (!hasField) {\n throw new SquordTypeError(\n \"Edição precisa de ao menos um entre content, embeds e components (EMPTY_UPDATE)\",\n );\n }\n return body;\n}\n\n/** Menções seguras quando o payload não especifica. */\nexport function safeAllowedMentions(allowed?: AllowedMentions): AllowedMentions {\n return allowed ?? SAFE_ALLOWED_MENTIONS;\n}\n","/**\n * Manager de interações: callback da primeira resposta e follow-ups.\n *\n * As rotas são públicas: o token da interação vai no caminho e não se envia\n * o header `Authorization`. A janela é de **15 minutos**; a primeira resposta\n * é a única aceita como callback (`409 INTERACTION_ALREADY_ACKNOWLEDGED` na\n * segunda), e follow-up antes da primeira resposta dá\n * `409 INTERACTION_NOT_ACKNOWLEDGED`. O limite por interação é de\n * 5 respostas (callback + follow-ups) a cada 5 segundos.\n *\n * O padrão para trabalho demorado é `DEFERRED` + follow-up.\n */\n\nimport { resolveMessagePayload } from \"../builders/message\";\nimport type { RestClient } from \"../rest/RestClient\";\nimport type {\n APIInteractionCallbackBody,\n APIInteractionReplyData,\n InteractionCallbackType,\n} from \"../types/api\";\nimport type { MessagePayloadLike } from \"../builders/message\";\n\nexport class InteractionsManager {\n constructor(private readonly rest: RestClient) {}\n\n /**\n * Primeira resposta a uma interação (`type`: `MESSAGE`, `DEFERRED`,\n * `UPDATE` ou `DEFERRED_UPDATE`). Resolve em `204` (sem corpo).\n *\n * Não é retentável automaticamente: uma repetição pode encontrar\n * `409 INTERACTION_ALREADY_ACKNOWLEDGED`. O SDK trata esse 409 como\n * \"resposta já entregue\" e resolve sem erro (veja `reply`).\n */\n callback(\n interactionId: string,\n interactionToken: string,\n body: APIInteractionCallbackBody,\n signal?: AbortSignal,\n ): Promise<void> {\n return this.rest\n .post<null>(`/interactions/${interactionId}/${interactionToken}/callback`, body, {\n auth: false,\n signal,\n retryable: false,\n })\n .then(() => undefined);\n }\n\n /**\n * Follow-up depois da primeira resposta. Age como `MESSAGE`: cria uma\n * mensagem (ou resposta efêmera). Responde `204`.\n */\n followup(\n interactionId: string,\n interactionToken: string,\n data: APIInteractionReplyData,\n signal?: AbortSignal,\n ): Promise<void> {\n return this.rest\n .post<null>(`/interactions/${interactionId}/${interactionToken}/followups`, data, {\n auth: false,\n signal,\n retryable: false,\n })\n .then(() => undefined);\n }\n\n /**\n * Resposta `MESSAGE` com payload conveniente (string ou objeto).\n * Um `409 INTERACTION_ALREADY_ACKNOWLEDGED` é tratado como sucesso:\n * significa que a resposta já foi entregue (por exemplo, após um timeout\n * de rede em que a primeira tentativa chegou ao servidor).\n */\n async reply(\n interactionId: string,\n interactionToken: string,\n payload: MessagePayloadLike,\n options: { ephemeral?: boolean; signal?: AbortSignal } = {},\n ): Promise<void> {\n const data = resolveMessagePayload(payload);\n if (options.ephemeral) data.ephemeral = true;\n try {\n await this.callback(interactionId, interactionToken, { type: \"MESSAGE\", data }, options.signal);\n } catch (err) {\n if (isAlreadyAcknowledged(err)) return;\n throw err;\n }\n }\n\n /** `DEFERRED`: avisa que o bot está processando (\"pensando\"). Depois, use follow-ups. */\n async defer(\n interactionId: string,\n interactionToken: string,\n options: { signal?: AbortSignal } = {},\n ): Promise<void> {\n try {\n await this.callback(\n interactionId,\n interactionToken,\n { type: \"DEFERRED\" },\n options.signal,\n );\n } catch (err) {\n if (isAlreadyAcknowledged(err)) return;\n throw err;\n }\n }\n\n /** `UPDATE` (só componente): edita a mensagem que tinha o componente clicado. */\n async update(\n interactionId: string,\n interactionToken: string,\n payload: MessagePayloadLike,\n options: { signal?: AbortSignal } = {},\n ): Promise<void> {\n const data = resolveMessagePayload(payload);\n try {\n await this.callback(\n interactionId,\n interactionToken,\n { type: \"UPDATE\", data },\n options.signal,\n );\n } catch (err) {\n if (isAlreadyAcknowledged(err)) return;\n throw err;\n }\n }\n\n /** `DEFERRED_UPDATE` (só componente): confirma o clique sem mudar nada. */\n async acknowledgeComponent(\n interactionId: string,\n interactionToken: string,\n options: { signal?: AbortSignal } = {},\n ): Promise<void> {\n try {\n await this.callback(\n interactionId,\n interactionToken,\n { type: \"DEFERRED_UPDATE\" },\n options.signal,\n );\n } catch (err) {\n if (isAlreadyAcknowledged(err)) return;\n throw err;\n }\n }\n}\n\nfunction isAlreadyAcknowledged(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n (err as { status?: number; code?: string }).status === 409 &&\n (err as { code?: string }).code === \"INTERACTION_ALREADY_ACKNOWLEDGED\"\n );\n}\n\nexport type { InteractionCallbackType };\n","/**\n * Manager de Spaces (guilds), membros, cargos e moderação.\n *\n * A nomenclatura do SDK usa \"Space\" na documentação, mas a API chama o\n * recurso de `guild` (`/guilds/...`), o que o SDK preserva nos caminhos.\n */\n\nimport type { RestClient } from \"../rest/RestClient\";\nimport type {\n APIGuild,\n APIMember,\n APIMemberBan,\n APIMemberBanBody,\n APIMemberEditBody,\n APIMemberPage,\n APIRole,\n} from \"../types/api\";\nimport type { CursorPaginationParams, ISODate, Snowflake } from \"../types/common\";\n\nexport class GuildsManager {\n constructor(private readonly rest: RestClient) {}\n\n /** Busca um Space pelo id, com o bloco `self` do bot nele. */\n fetch(guildId: Snowflake, signal?: AbortSignal): Promise<APIGuild> {\n return this.rest.get<APIGuild>(`/guilds/${guildId}`, { signal });\n }\n}\n\nexport interface MemberListParams extends CursorPaginationParams {\n /** Só membros com este cargo. */\n roleId?: Snowflake;\n /** Prefixo do `username` ou parte do `displayName`. */\n search?: string;\n /** Só membros que enxergam este canal (threads valem pelo canal pai). */\n channelId?: Snowflake;\n}\n\nexport class MembersManager {\n constructor(private readonly rest: RestClient) {}\n\n /** Busca um membro de um Space. */\n fetch(guildId: Snowflake, userId: Snowflake, signal?: AbortSignal): Promise<APIMember> {\n return this.rest.get<APIMember>(`/guilds/${guildId}/members/${userId}`, { signal });\n }\n\n /** Lista membros com paginação por cursor e filtros. */\n list(guildId: Snowflake, params: MemberListParams = {}, signal?: AbortSignal): Promise<APIMemberPage> {\n return this.rest.get<APIMemberPage>(`/guilds/${guildId}/members`, {\n query: {\n limit: params.limit,\n before: params.before,\n after: params.after,\n roleId: params.roleId,\n search: params.search,\n channelId: params.channelId,\n },\n signal,\n });\n }\n\n /**\n * Edita um membro: apelido, cargos (substituem o conjunto), timeout,\n * silenciamento. O bot precisa das permissões correspondentes.\n */\n edit(\n guildId: Snowflake,\n userId: Snowflake,\n body: APIMemberEditBody,\n options: { signal?: AbortSignal } = {},\n ): Promise<APIMember> {\n return this.rest.patch<APIMember>(`/guilds/${guildId}/members/${userId}`, body, {\n signal: options.signal,\n // PATCH de membro é substituição declarativa; seguro repetir.\n retryable: true,\n });\n }\n\n /** Aplica um timeout até a data informada (`TIMEOUT_MEMBERS`). */\n timeout(guildId: Snowflake, userId: Snowflake, until: ISODate, options?: { signal?: AbortSignal }): Promise<APIMember> {\n return this.edit(guildId, userId, { timeoutUntil: until }, options);\n }\n\n /** Remove o timeout de um membro. */\n removeTimeout(guildId: Snowflake, userId: Snowflake, options?: { signal?: AbortSignal }): Promise<APIMember> {\n return this.edit(guildId, userId, { timeoutUntil: null }, options);\n }\n\n /** Expulsa um membro (`KICK_MEMBERS`). Ele pode voltar com um novo convite. */\n kick(\n guildId: Snowflake,\n userId: Snowflake,\n reason?: string,\n options: { signal?: AbortSignal } = {},\n ): Promise<void> {\n return this.rest\n .delete<null>(`/guilds/${guildId}/members/${userId}`, {\n body: reason ? { reason } : {},\n signal: options.signal,\n })\n .then(() => undefined);\n }\n\n /** Dá um cargo a um membro (`MANAGE_ROLES`, hierarquia abaixo do bot). */\n addRole(guildId: Snowflake, userId: Snowflake, roleId: Snowflake, options: { signal?: AbortSignal } = {}): Promise<void> {\n return this.rest\n .put<null>(`/guilds/${guildId}/members/${userId}/roles/${roleId}`, undefined, {\n signal: options.signal,\n })\n .then(() => undefined);\n }\n\n /** Tira um cargo de um membro. */\n removeRole(guildId: Snowflake, userId: Snowflake, roleId: Snowflake, options: { signal?: AbortSignal } = {}): Promise<void> {\n return this.rest\n .delete<null>(`/guilds/${guildId}/members/${userId}/roles/${roleId}`, {\n signal: options.signal,\n })\n .then(() => undefined);\n }\n}\n\nexport class RolesManager {\n constructor(private readonly rest: RestClient) {}\n\n /** Lista os cargos de um Space. */\n list(guildId: Snowflake, signal?: AbortSignal): Promise<APIRole[]> {\n return this.rest.get<APIRole[]>(`/guilds/${guildId}/roles`, { signal });\n }\n}\n\n/** Moderação: banimentos e desbanimentos (por enquanto o que a API expõe a bots). */\nexport class ModerationManager {\n constructor(private readonly rest: RestClient) {}\n\n /**\n * Ban um membro (`BAN_MEMBERS`). Pode apagar até 7 dias de histórico\n * recente com `deleteMessageSeconds`. Não é retentável por padrão.\n */\n ban(\n guildId: Snowflake,\n userId: Snowflake,\n body: APIMemberBanBody = {},\n options: { signal?: AbortSignal } = {},\n ): Promise<APIMemberBan> {\n return this.rest.put<APIMemberBan>(`/guilds/${guildId}/bans/${userId}`, body, {\n signal: options.signal,\n retryable: false,\n });\n }\n\n /** Desbane (`BAN_MEMBERS`). Banimentos da plataforma não podem ser desfeitos. */\n unban(guildId: Snowflake, userId: Snowflake, options: { signal?: AbortSignal } = {}): Promise<void> {\n return this.rest\n .delete<null>(`/guilds/${guildId}/bans/${userId}`, { signal: options.signal })\n .then(() => undefined);\n }\n}\n","/** Utilitários gerais. */\n\nimport { randomUUID } from \"node:crypto\";\n\n/** Gera um id de requisição (rastreável no header `x-request-id`). */\nexport function newRequestId(): string {\n return randomUUID();\n}\n\n/** Gera uma chave de idempotência (`nonce`) para envio de mensagens. */\nexport function newNonce(): string {\n return randomUUID().replace(/-/g, \"\").slice(0, 32);\n}\n\n/** Verifica se um valor parece um token de bot do Squord (`sqb_<id>.<segredo>`). */\nexport function isBotToken(token: string): boolean {\n return typeof token === \"string\" && /^sqb_.+\\..+/.test(token);\n}\n\n/** Remove o prefixo `Bot ` de um token, se presente. */\nexport function stripTokenPrefix(token: string): string {\n return token.startsWith(\"Bot \") ? token.slice(4) : token;\n}\n\n/** Divide argumentos de uma linha de comando, respeitando aspas. */\nexport function splitArguments(input: string): string[] {\n const args: string[] = [];\n let current = \"\";\n let inQuotes: '\"' | \"'\" | null = null;\n\n for (const char of input) {\n if (inQuotes) {\n if (char === inQuotes) {\n inQuotes = null;\n } else {\n current += char;\n }\n continue;\n }\n if (char === '\"' || char === \"'\") {\n inQuotes = char;\n continue;\n }\n if (/\\s/.test(char)) {\n if (current) {\n args.push(current);\n current = \"\";\n }\n continue;\n }\n current += char;\n }\n if (current) args.push(current);\n return args;\n}\n\n/** Delega em `setTimeout` agendável (usado para avançar relógio em testes). */\nexport const timers = {\n setTimeout: (fn: () => void, ms: number) => setTimeout(fn, ms),\n clearTimeout: (id: NodeJS.Timeout) => clearTimeout(id),\n};\n","/**\n * Manager de mensagens: enviar, editar, apagar, reagir, fixar e consultar.\n */\n\nimport { resolveMessageEditPayload, resolveMessagePayload, safeAllowedMentions } from \"../builders/message\";\nimport type { RestClient } from \"../rest/RestClient\";\nimport type {\n APIMessage,\n APIMessageCreateBody,\n APIMessageEditBody,\n APIMessageListParams,\n APIMessagePage,\n APIReaction,\n} from \"../types/api\";\nimport type { MessagePayloadLike } from \"../builders/message\";\nimport type { Snowflake } from \"../types/common\";\nimport { newNonce } from \"../utils/misc\";\n\nexport interface SendOptions {\n /** Anula a requisição. */\n signal?: AbortSignal;\n /**\n * Chave de idempotência da mensagem. Se omitida, o SDK gera uma — o que\n * torna seguro repetir o envio após falha de rede sem duplicar a mensagem.\n */\n nonce?: string;\n}\n\nexport class MessagesManager {\n constructor(private readonly rest: RestClient) {}\n\n /** Busca uma mensagem pelo id. */\n fetch(channelId: Snowflake, messageId: Snowflake): Promise<APIMessage> {\n return this.rest.get<APIMessage>(\n `/channels/${channelId}/messages/${messageId}`,\n );\n }\n\n /** Lista uma página do histórico do canal (padrão: 50, máximo 100). */\n list(\n channelId: Snowflake,\n params: APIMessageListParams = {},\n signal?: AbortSignal,\n ): Promise<APIMessagePage> {\n return this.rest.get<APIMessagePage>(`/channels/${channelId}/messages`, {\n query: { limit: params.limit, before: params.before, after: params.after },\n signal,\n });\n }\n\n /**\n * Envia uma mensagem. O SDK anexa um `nonce` automático (idempotência),\n * então a operação pode ser repetida com segurança pelo cliente REST em\n * falhas transitórias.\n */\n send(\n channelId: Snowflake,\n payload: MessagePayloadLike,\n options: SendOptions = {},\n ): Promise<APIMessage> {\n const body = resolveMessagePayload(payload);\n const nonce = body.nonce ?? options.nonce ?? newNonce();\n const createBody: APIMessageCreateBody = {\n ...body,\n nonce,\n allowedMentions: safeAllowedMentions(body.allowedMentions),\n };\n return this.rest.post<APIMessage>(`/channels/${channelId}/messages`, createBody, {\n signal: options.signal,\n // Protegido por nonce: seguro repetir.\n retryable: true,\n });\n }\n\n /** Edita uma mensagem (do próprio bot). `embeds`/`components` substituem a lista inteira. */\n edit(\n channelId: Snowflake,\n messageId: Snowflake,\n payload: MessagePayloadLike,\n options: { signal?: AbortSignal } = {},\n ): Promise<APIMessage> {\n const body: APIMessageEditBody = resolveMessageEditPayload(payload);\n return this.rest.patch<APIMessage>(\n `/channels/${channelId}/messages/${messageId}`,\n body,\n { signal: options.signal },\n );\n }\n\n /** Apaga uma mensagem (própria ou de outros, com `MANAGE_MESSAGES`). Responde 204. */\n delete(channelId: Snowflake, messageId: Snowflake, options: { signal?: AbortSignal } = {}): Promise<void> {\n return this.rest\n .delete<null>(`/channels/${channelId}/messages/${messageId}`, { signal: options.signal })\n .then(() => undefined);\n }\n\n /** Reage a uma mensagem (`ADD_REACTIONS`). `emoji` é o caractere ou `<:nome:id>`. */\n react(channelId: Snowflake, messageId: Snowflake, emoji: string, options: { signal?: AbortSignal } = {}): Promise<void> {\n return this.rest\n .put<null>(\n `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`,\n undefined,\n { signal: options.signal },\n )\n .then(() => undefined);\n }\n\n /** Remove a reação do bot. */\n removeReaction(channelId: Snowflake, messageId: Snowflake, emoji: string, options: { signal?: AbortSignal } = {}): Promise<void> {\n return this.rest\n .delete<null>(\n `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`,\n { signal: options.signal },\n )\n .then(() => undefined);\n }\n\n /** Lista as reações de uma mensagem. */\n listReactions(channelId: Snowflake, messageId: Snowflake, signal?: AbortSignal): Promise<APIReaction[]> {\n return this.rest.get<APIReaction[]>(\n `/channels/${channelId}/messages/${messageId}/reactions`,\n { signal },\n );\n }\n\n /** Fixa uma mensagem no canal (`PIN_MESSAGES`). */\n pin(channelId: Snowflake, messageId: Snowflake, options: { signal?: AbortSignal } = {}): Promise<void> {\n return this.rest\n .put<null>(`/channels/${channelId}/pins/${messageId}`, undefined, { signal: options.signal })\n .then(() => undefined);\n }\n\n /** Desafixa uma mensagem. */\n unpin(channelId: Snowflake, messageId: Snowflake, options: { signal?: AbortSignal } = {}): Promise<void> {\n return this.rest\n .delete<null>(`/channels/${channelId}/pins/${messageId}`, { signal: options.signal })\n .then(() => undefined);\n }\n\n /** Lista as mensagens fixadas do canal. */\n listPins(channelId: Snowflake, signal?: AbortSignal): Promise<APIMessage[]> {\n return this.rest.get<APIMessage[]>(`/channels/${channelId}/pins`, { signal });\n }\n}\n","/**\n * Manager de uploads: o fluxo oficial de anexos do Squord.\n *\n * Anexos não vão no JSON da mensagem. O fluxo tem três passos:\n * 1. **Reservar** (`POST /uploads`): devolve o upload e um alvo assinado.\n * 2. **Enviar os bytes** com `PUT` ao alvo (fora da API do Squord, sem o\n * header `Authorization`, repetindo os headers do alvo exatamente).\n * 3. **Confirmar** (`POST /uploads/{id}/confirm`): o Squord confere o que\n * chegou (tipo, tamanho, primeiros bytes). Confirmar de novo devolve o\n * mesmo resultado — a rota é idempotente.\n *\n * Depois, o `id` do upload entra em `attachmentIds` da mensagem\n * (até 10 por mensagem; cada upload só entra em uma).\n *\n * Nota: `Readable` é consumido em memória antes do `PUT`. Para arquivos\n * muito grandes, prefira passar o caminho (`path`) e confira o limite do\n * plano do Space (25 MB no gratuito; o teto da API é 500 MB).\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport type { Readable } from \"node:stream\";\nimport { NetworkError, SquordTypeError } from \"../errors\";\nimport type { Logger } from \"../logger\";\nimport { noopLogger } from \"../logger\";\nimport type { RestClient } from \"../rest/RestClient\";\nimport type {\n APIUpload,\n APIUploadConfirmBody,\n APIUploadCreateBody,\n APIUploadReservation,\n} from \"../types/api\";\nimport type { Snowflake } from \"../types/common\";\n\nexport type UploadSource = Buffer | Uint8Array | string | Readable;\n\nexport interface UploadOptions {\n /** Space do canal onde o anexo será usado. Bots sempre informam. */\n guildId: Snowflake;\n /** Nome do arquivo (1 a 256 caracteres). Padrão: nome do caminho. */\n filename?: string;\n /** Tipo de conteúdo, ex.: `image/png`. Precisa bater com os bytes. */\n contentType?: string;\n /** Caminho local do arquivo. */\n path?: string;\n /** Conteúdo em memória ou stream. */\n data?: UploadSource;\n /** Tamanho em bytes (obrigatório ao usar stream). */\n size?: number;\n /** Anula a operação. */\n signal?: AbortSignal;\n}\n\nexport class UploadsManager {\n private readonly logger: Logger;\n\n constructor(\n private readonly rest: RestClient,\n logger?: Logger,\n ) {\n this.logger = (logger ?? noopLogger).child(\"uploads\");\n }\n\n /** Reserva um upload (`POST /uploads`). Não é idempotente. */\n reserve(body: APIUploadCreateBody, signal?: AbortSignal): Promise<APIUploadReservation> {\n return this.rest.post<APIUploadReservation>(\"/uploads\", body, {\n signal,\n retryable: false,\n });\n }\n\n /** Confirma um upload (`POST /uploads/{id}/confirm`). Idempotente. */\n confirm(uploadId: Snowflake, body: APIUploadConfirmBody = {}, signal?: AbortSignal): Promise<APIUpload> {\n return this.rest.post<APIUpload>(`/uploads/${uploadId}/confirm`, body, {\n signal,\n retryable: true,\n });\n }\n\n /**\n * Fluxo completo: reserva, envia os bytes e confirma. Devolve o upload em\n * `status: \"READY\"`, pronto para `attachmentIds`.\n *\n * Aceita caminho local (`path`), `Buffer`/`Uint8Array` ou `Readable`\n * (informe `size`). Streams são sempre encerrados, mesmo em falha.\n */\n async upload(options: UploadOptions): Promise<APIUpload> {\n const { path, data, signal } = options;\n\n let bytes: Buffer;\n let filename = options.filename;\n let size = options.size;\n\n if (path !== undefined) {\n bytes = await readFile(path).catch(() => {\n throw new SquordTypeError(`Não foi possível ler o arquivo: ${path}`);\n });\n filename ??= basename(path);\n size ??= bytes.length;\n } else if (data !== undefined) {\n if (typeof data === \"string\") {\n bytes = Buffer.from(data, \"utf8\");\n } else if (Buffer.isBuffer(data) || data instanceof Uint8Array) {\n bytes = Buffer.isBuffer(data) ? data : Buffer.from(data);\n } else if (typeof (data as Readable).read === \"function\") {\n bytes = await this.collectStream(data as Readable, signal);\n } else {\n throw new SquordTypeError(\"data precisa ser Buffer, Uint8Array, string ou Readable\");\n }\n filename ??= \"arquivo\";\n size ??= bytes.length;\n } else {\n throw new SquordTypeError(\"Informe path ou data para o upload\");\n }\n\n if (size === undefined || Number.isNaN(size)) {\n throw new SquordTypeError(\"Informe o size ao enviar um stream\");\n }\n if (size <= 0) {\n throw new SquordTypeError(\"O arquivo está vazio (size 0)\");\n }\n if (size > 524_288_000) {\n throw new SquordTypeError(\n `O arquivo passa de 500 MB (${size} bytes); o limite real vem do plano do Space`,\n );\n }\n const contentType = options.contentType ?? guessContentType(filename ?? \"arquivo\");\n\n const reservation = await this.reserve(\n { scope: \"attachments\", filename: filename ?? \"arquivo\", contentType, size, guildId: options.guildId },\n signal,\n );\n\n // PUT dos bytes ao alvo: fora da API do Squord, sem Authorization,\n // repetindo os headers do alvo exatamente como vieram.\n const target = reservation.target;\n const response = await this.rest.fetch(target.uploadUrl, {\n method: \"PUT\",\n headers: { ...target.headers },\n body: new Uint8Array(bytes),\n signal,\n });\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new NetworkError(\n `O envio dos bytes falhou (HTTP ${response.status})${text ? `: ${text.slice(0, 200)}` : \"\"}`,\n );\n }\n\n const upload = await this.confirm(reservation.upload.id, {}, signal);\n if (upload.status !== \"READY\") {\n this.logger.warn(\"upload confirmado fora do esperado\", {\n id: upload.id,\n status: upload.status,\n scanStatus: upload.scanStatus,\n });\n }\n return upload;\n }\n\n /** Atalho: envia um arquivo e devolve o `id` pronto para `attachmentIds`. */\n async uploadForAttachment(options: UploadOptions): Promise<Snowflake> {\n const upload = await this.upload(options);\n return upload.id;\n }\n\n private async collectStream(stream: Readable, signal?: AbortSignal): Promise<Buffer> {\n const chunks: Buffer[] = [];\n try {\n for await (const chunk of stream) {\n if (signal?.aborted) throw new DOMException(\"Upload cancelado\", \"AbortError\");\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk as Uint8Array));\n }\n } catch (err) {\n stream.destroy();\n throw err;\n }\n return Buffer.concat(chunks);\n }\n}\n\nfunction basename(path: string): string {\n const parts = path.split(/[\\\\/]/);\n return parts[parts.length - 1] || \"arquivo\";\n}\n\nfunction guessContentType(filename: string): string {\n const ext = filename.toLowerCase().split(\".\").pop() ?? \"\";\n const table: Record<string, string> = {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n mp3: \"audio/mpeg\",\n ogg: \"audio/ogg\",\n wav: \"audio/wav\",\n pdf: \"application/pdf\",\n txt: \"text/plain\",\n json: \"application/json\",\n csv: \"text/csv\",\n md: \"text/markdown\",\n zip: \"application/zip\",\n };\n return table[ext] ?? \"application/octet-stream\";\n}\n","/**\n * Logger estruturado com redação automática de segredos.\n *\n * Tokens de bot (`sqb_...`) e tokens de interação são substituídos por\n * `[REDACTED]` antes de qualquer entrega. O logger nunca registra o conteúdo\n * de mensagens por conta própria: os eventos são emitidos, mas o logger só\n * fala de metadados operacionais.\n */\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n silent: 100,\n};\n\nexport interface Logger {\n debug(message: string, meta?: Record<string, unknown>): void;\n info(message: string, meta?: Record<string, unknown>): void;\n warn(message: string, meta?: Record<string, unknown>): void;\n error(message: string, meta?: Record<string, unknown>): void;\n /** Cria um logger filho com campos fixos (ex.: `rest`, `gateway`). */\n child(prefix: string): Logger;\n}\n\n/** Redação aplicada a todas as saídas do logger padrão. */\nexport function redact(input: string): string {\n return (\n input\n // Tokens de bot: sqb_<id>.<segredo>\n .replace(/sqb_[A-Za-z0-9._-]+/g, \"sqb_[REDACTED]\")\n // Header Authorization completo\n .replace(/Bot\\s+sqb_[A-Za-z0-9._-]+/gi, \"Bot [REDACTED]\")\n // Tokens de interação que escapem em meta\n .replace(/\"token\"\\s*:\\s*\"[^\"]+\"/g, '\"token\":\"[REDACTED]\"')\n );\n}\n\nexport interface ConsoleLoggerOptions {\n /** Nível mínimo exibido. Padrão: `silent` (o SDK não imprime nada). */\n level?: LogLevel;\n /** Destino dos logs. Padrão: `console`. */\n write?: (line: string) => void;\n}\n\nexport function createConsoleLogger(options: ConsoleLoggerOptions = {}): Logger {\n const level = options.level ?? \"silent\";\n const write = options.write ?? ((line: string) => console.log(line));\n\n const log =\n (lvl: Exclude<LogLevel, \"silent\">, prefix: string) =>\n (message: string, meta?: Record<string, unknown>) => {\n if (LEVEL_ORDER[lvl] < LEVEL_ORDER[level]) return;\n const entry = {\n t: new Date().toISOString(),\n level: lvl,\n scope: prefix || undefined,\n msg: redact(message),\n ...meta,\n };\n write(redact(JSON.stringify(entry)));\n };\n\n const make = (prefix: string): Logger => ({\n debug: log(\"debug\", prefix),\n info: log(\"info\", prefix),\n warn: log(\"warn\", prefix),\n error: log(\"error\", prefix),\n child: (childPrefix: string) => make(prefix ? `${prefix}:${childPrefix}` : childPrefix),\n });\n\n return make(\"\");\n}\n\n/** Logger que descarta tudo. Útil como padrão e em testes. */\nexport const noopLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n child: () => noopLogger,\n};\n\n/**\n * Atende por `process.env.SQUORD_LOG` (`debug|info|warn|error`) e cria o\n * logger padrão. `debug` também é habilitado por `SQUORD_DEBUG=1`.\n */\nexport function loggerFromEnv(): Logger {\n const fromEnv = (process.env.SQUORD_LOG ?? \"\").toLowerCase();\n if (fromEnv in LEVEL_ORDER) {\n return createConsoleLogger({ level: fromEnv as LogLevel });\n }\n if (process.env.SQUORD_DEBUG === \"1\" || process.env.SQUORD_DEBUG === \"true\") {\n return createConsoleLogger({ level: \"debug\" });\n }\n return noopLogger;\n}\n","/**\n * Backoff exponencial com jitter, para reconexões do gateway e retentativas\n * de REST. A recomendação da documentação: 1 s, 2 s, 4 s ... até 60 s, mais\n * um valor aleatório.\n */\n\nexport interface BackoffOptions {\n /** Primeira espera, em milissegundos. Padrão 1000. */\n baseMs?: number;\n /** Multiplicador entre tentativas. Padrão 2. */\n factor?: number;\n /** Teto da espera base, em milissegundos. Padrão 60000. */\n maxMs?: number;\n /** Fração de jitter: 0.25 espera ±25%. Padrão 0.25. */\n jitter?: number;\n}\n\n/** Calcula a espera para a tentativa `attempt` (0-based). */\nexport function backoffDelay(attempt: number, options: BackoffOptions = {}): number {\n const { baseMs = 1000, factor = 2, maxMs = 60_000, jitter = 0.25 } = options;\n const bounded = Math.min(attempt, 16); // evita overflow\n const exp = Math.min(baseMs * factor ** bounded, maxMs);\n const jitterAmount = exp * jitter * (Math.random() * 2 - 1);\n return Math.max(250, Math.round(exp + jitterAmount));\n}\n\n/** Cria um gerador de esperas de backoff infinito. */\nexport function* backoffSequence(options: BackoffOptions = {}): Generator<number, never, void> {\n for (let attempt = 0; ; attempt++) {\n yield backoffDelay(attempt, options);\n }\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) return Promise.resolve();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new DOMException(\"Sleep aborted\", \"AbortError\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/** Jitter uniforme em [0, max]. */\nexport function jitter(max: number): number {\n return Math.floor(Math.random() * max);\n}\n","/**\n * Cliente REST do Squord.\n *\n * Encapsula `https://api.squord.com.br/api/v1` com:\n * - autenticação por token de bot (`Authorization: Bot sqb_...`);\n * - timeout configurável e cancelamento via `AbortSignal`;\n * - `x-request-id` em toda requisição (o valor volta nos erros);\n * - respeito aos limites de taxa: espera `details.retryAfter` em 429,\n * observa os headers `X-RateLimit-*` e aplica um teto global conservador;\n * - retentativas para falhas transitórias (5xx, rede, 429) **somente em\n * operações idempotentes ou protegidas por `nonce`** — a regra de ouro:\n * nunca repetir automaticamente uma operação sem saber se a primeira foi\n * processada;\n * - erros tipados (veja `../errors`).\n */\n\nimport {\n NetworkError,\n RateLimitError,\n RequestTimeoutError,\n SquordAPIError,\n makeAPIError,\n} from \"../errors\";\nimport type { Logger } from \"../logger\";\nimport { noopLogger } from \"../logger\";\nimport { backoffDelay, sleep } from \"../utils/backoff\";\nimport { newRequestId } from \"../utils/misc\";\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\nexport interface RestClientOptions {\n /** URL base da API. Padrão: `https://api.squord.com.br/api/v1`. */\n baseURL?: string;\n /** Token do bot (`sqb_...`). O SDK adiciona o prefixo `Bot `. */\n token: string;\n /** Timeout por requisição, em milissegundos. Padrão: 15000. */\n timeoutMs?: number;\n /**\n * Retentativas automáticas adicionais para falhas transitórias\n * (429, 5xx, rede). Padrão: 3.\n */\n maxRetries?: number;\n /**\n * Teto global de requisições por segundo, abaixo do `BOT_GLOBAL`\n * oficial (50/s). Padrão: 45. Use `0` para desligar.\n */\n globalRequestsPerSecond?: number;\n /** Implementação de fetch (injetável para testes). Padrão: global `fetch`. */\n fetchImpl?: typeof fetch;\n /** Logger. O SDK não imprime nada por padrão. */\n logger?: Logger;\n}\n\nexport interface RequestOptions {\n /** Parâmetros de query string (valores `undefined`/`null` são omitidos). */\n query?: Record<string, string | number | boolean | undefined | null>;\n /** Corpo JSON da requisição. */\n body?: unknown;\n /** Sinal de cancelamento externo. */\n signal?: AbortSignal;\n /** Id de requisição para rastreamento (`x-request-id`). */\n requestId?: string;\n /**\n * `false` para rotas públicas, como os callbacks de interação\n * (`/interactions/{id}/{token}/callback`), que não levam o header\n * `Authorization`. Padrão: `true`.\n */\n auth?: boolean;\n /**\n * Se a operação pode ser repetida com segurança após falha incerta\n * (timeout de rede, 5xx). Padrão: `true` para GET/PUT/DELETE e `false`\n * para POST. Operações POST protegidas por `nonce` (envio de mensagens,\n * confirmação de upload) devem marcar `true`.\n */\n retryable?: boolean;\n}\n\nexport interface RestResponse<T> {\n data: T;\n status: number;\n headers: Headers;\n requestId: string | null;\n request: Request;\n}\n\n/** Headers de rate limit de uma resposta. */\nexport interface RateLimitState {\n limit: number | null;\n remaining: number | null;\n /** Quando a janela renova, em segundos Unix. */\n reset: number | null;\n}\n\nconst DEFAULT_BASE_URL = \"https://api.squord.com.br/api/v1\";\nconst DEFAULT_TIMEOUT_MS = 15_000;\nconst DEFAULT_MAX_RETRIES = 3;\n\nexport class RestClient {\n readonly baseURL: string;\n private readonly token: string;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly fetchImpl: typeof fetch;\n private readonly logger: Logger;\n private readonly bucketStates = new Map<string, RateLimitState>();\n private readonly bucketBlockedUntil = new Map<string, number>();\n private readonly globalWindow: number[] = [];\n private readonly globalLimit: number;\n private destroyed = false;\n\n constructor(options: RestClientOptions) {\n this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.token = options.token;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n this.fetchImpl = options.fetchImpl ?? fetch;\n this.logger = (options.logger ?? noopLogger).child(\"rest\");\n const rps = options.globalRequestsPerSecond ?? 45;\n this.globalLimit = rps > 0 ? rps : Number.POSITIVE_INFINITY;\n }\n\n /** GET tipado. */\n get<T>(path: string, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(\"GET\", path, options);\n }\n\n /** Implementação de fetch em uso (exposta para uploads e testes). */\n get fetch(): typeof fetch {\n return this.fetchImpl;\n }\n\n /** POST tipado. Não é retentável por padrão. */\n post<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(\"POST\", path, { ...options, body });\n }\n\n /** PUT tipado (idempotente). */\n put<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(\"PUT\", path, { ...options, body });\n }\n\n /** PATCH tipado (retentável por padrão quando idempotente pelo caller). */\n patch<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(\"PATCH\", path, { ...options, body });\n }\n\n /** DELETE tipado. Resposta 204 devolve `null`. */\n delete<T = null>(path: string, options: RequestOptions = {}): Promise<T | null> {\n return this.request<T | null>(\"DELETE\", path, options);\n }\n\n /** Executa uma requisição com política completa de erros, retries e rate limits. */\n async request<T>(\n method: HttpMethod,\n path: string,\n options: RequestOptions = {},\n ): Promise<T> {\n const response = await this.requestRaw<T>(method, path, options);\n return response.data;\n }\n\n /** Como `request`, mas devolve também status, headers e `x-request-id`. */\n async requestRaw<T>(\n method: HttpMethod,\n path: string,\n options: RequestOptions = {},\n ): Promise<RestResponse<T>> {\n if (this.destroyed) {\n throw new SquordAPIError(\n { statusCode: 0, code: \"SDK_DESTROYED\", message: \"O cliente foi destruído\" },\n 0,\n );\n }\n\n const retryable = options.retryable ?? method !== \"POST\";\n const url = this.buildUrl(path, options.query);\n const requestId = options.requestId ?? newRequestId();\n const routeKey = routeKeyOf(method, path);\n\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (options.signal?.aborted) throw new DOMException(\"Requisição cancelada\", \"AbortError\");\n\n await this.waitForRouteBucket(routeKey, options.signal);\n await this.acquireGlobalSlot(options.signal);\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-request-id\": requestId,\n };\n if (options.auth !== false) {\n headers.Authorization = `Bot ${this.token}`;\n }\n const request = new Request(url, {\n method,\n headers,\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n });\n\n // Compõe timeout + sinal externo (com cancelamento do timer ao final).\n const signals: AbortSignal[] = [];\n const timeoutController = new AbortController();\n const timer = setTimeout(() => {\n timeoutController.abort(new DOMException(\"Request timed out\", \"TimeoutError\"));\n }, this.timeoutMs);\n signals.push(timeoutController.signal);\n if (options.signal) signals.push(options.signal);\n const compositeSignal =\n signals.length === 1 ? signals[0]! : AbortSignal.any(signals);\n\n let response: Response;\n try {\n response = await this.fetchImpl(request, { signal: compositeSignal });\n } catch (err) {\n lastError = this.toNetworkError(err, method, path);\n const canRetry = retryable && attempt < this.maxRetries;\n this.logger.debug(\"network failure\", { method, path, attempt, retryable, canRetry });\n if (!canRetry) throw lastError;\n await sleep(backoffDelay(attempt, { baseMs: 500, maxMs: 8_000 }), options.signal);\n continue;\n } finally {\n clearTimeout(timer);\n }\n\n this.recordBucketState(routeKey, response.headers);\n\n if (response.ok) {\n const data = (await this.parseBody<T>(response)) as T;\n return {\n data,\n status: response.status,\n headers: response.headers,\n requestId: response.headers.get(\"x-request-id\") ?? requestId,\n request,\n };\n }\n\n // Erro HTTP: decide entre esperar/repetir ou falhar.\n const apiError = await this.toAPIError(response);\n lastError = apiError;\n\n if (apiError.status === 429 && apiError instanceof RateLimitError) {\n if (attempt < this.maxRetries) {\n const waitMs = apiError.retryAfter * 1000;\n this.logger.warn(\"rate limit, aguardando\", {\n bucket: apiError.bucket,\n retryAfter: apiError.retryAfter,\n });\n await sleep(waitMs, options.signal);\n continue;\n }\n throw new RateLimitError(apiError.responseBody!, 429, {\n requestId: apiError.requestId,\n exhaustedRetries: true,\n });\n }\n\n if (\n apiError.status >= 500 &&\n retryable &&\n attempt < this.maxRetries\n ) {\n const waitMs = backoffDelay(attempt, { baseMs: 500, maxMs: 8_000 });\n this.logger.warn(\"erro 5xx, repetindo\", { status: apiError.status, attempt, waitMs });\n await sleep(waitMs, options.signal);\n continue;\n }\n\n if (\n apiError.status === 409 &&\n (apiError.code === \"COMMANDS_CONFLICT\" || apiError.code === \"THREAD_CHANGED\") &&\n attempt < this.maxRetries\n ) {\n await sleep(250 + backoffDelay(attempt, { baseMs: 200, maxMs: 2_000 }), options.signal);\n continue;\n }\n\n throw apiError;\n }\n\n throw lastError;\n }\n\n /** Encerra o cliente: novas requisições falham imediatamente. */\n destroy(): void {\n this.destroyed = true;\n this.bucketStates.clear();\n this.bucketBlockedUntil.clear();\n }\n\n /** Estado de rate limit conhecido para uma rota (diagnóstico). */\n bucketState(method: HttpMethod, path: string): RateLimitState | undefined {\n return this.bucketStates.get(routeKeyOf(method, path));\n }\n\n // -----------------------------------------------------------------\n\n private buildUrl(\n path: string,\n query?: Record<string, string | number | boolean | undefined | null>,\n ): string {\n let url = `${this.baseURL}${path.startsWith(\"/\") ? path : `/${path}`}`;\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query ?? {})) {\n if (value === undefined || value === null) continue;\n params.set(key, String(value));\n }\n const qs = params.toString();\n if (qs) url += `?${qs}`;\n return url;\n }\n\n private async parseBody<T>(response: Response): Promise<T | null> {\n if (response.status === 204) return null;\n const text = await response.text();\n if (!text) return null;\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as unknown as T;\n }\n }\n\n private async toAPIError(response: Response): Promise<SquordAPIError> {\n let body: {\n statusCode?: number;\n code?: string;\n message?: string;\n details?: unknown;\n requestId?: string;\n } = {};\n try {\n body = (await response.json()) as typeof body;\n } catch {\n // resposta sem corpo\n }\n const enriched = {\n statusCode: response.status,\n code: body.code ?? `HTTP_${response.status}`,\n message: body.message ?? response.statusText,\n details: body.details,\n requestId: body.requestId ?? response.headers.get(\"x-request-id\") ?? undefined,\n };\n return makeAPIError(enriched as Parameters<typeof makeAPIError>[0], response.status, enriched.requestId);\n }\n\n private toNetworkError(err: unknown, method: string, path: string): unknown {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n return new RequestTimeoutError(method, path, this.timeoutMs, { cause: err });\n }\n if (err instanceof DOMException && err.name === \"AbortError\") {\n return err; // cancelamento explícito: propaga\n }\n const reason = (err as { reason?: unknown })?.reason;\n if (reason instanceof DOMException && reason.name === \"TimeoutError\") {\n return new RequestTimeoutError(method, path, this.timeoutMs, { cause: err });\n }\n return new NetworkError(`Falha de rede em ${method} ${path}: ${String((err as Error)?.message ?? err)}`, {\n cause: err,\n });\n }\n\n private recordBucketState(routeKey: string, headers: Headers): void {\n const limit = headers.get(\"x-ratelimit-limit\");\n const remaining = headers.get(\"x-ratelimit-remaining\");\n const reset = headers.get(\"x-ratelimit-reset\");\n if (limit === null && remaining === null && reset === null) return;\n const state: RateLimitState = {\n limit: limit !== null ? Number(limit) : null,\n remaining: remaining !== null ? Number(remaining) : null,\n reset: reset !== null ? Number(reset) : null,\n };\n this.bucketStates.set(routeKey, state);\n if (state.remaining === 0 && state.reset !== null) {\n const blockedUntil = state.reset * 1000;\n this.bucketBlockedUntil.set(routeKey, blockedUntil);\n }\n }\n\n private async waitForRouteBucket(routeKey: string, signal?: AbortSignal): Promise<void> {\n for (;;) {\n const blockedUntil = this.bucketBlockedUntil.get(routeKey);\n if (blockedUntil === undefined) return;\n const waitMs = blockedUntil - Date.now();\n if (waitMs <= 0) {\n this.bucketBlockedUntil.delete(routeKey);\n return;\n }\n await sleep(waitMs, signal).catch(() => {});\n if (signal?.aborted) return;\n }\n }\n\n private async acquireGlobalSlot(signal?: AbortSignal): Promise<void> {\n if (this.globalLimit === Number.POSITIVE_INFINITY) return;\n for (;;) {\n const now = Date.now();\n while (this.globalWindow.length > 0 && now - this.globalWindow[0]! >= 1000) {\n this.globalWindow.shift();\n }\n if (this.globalWindow.length < this.globalLimit) {\n this.globalWindow.push(now);\n return;\n }\n const waitMs = 1000 - (now - this.globalWindow[0]!) + 10;\n await sleep(waitMs, signal);\n }\n }\n}\n\n/**\n * Chave de bucket de rate limit: método + caminho com ids substituídos.\n * Ex.: `POST /channels/{id}/messages` para qualquer canal.\n */\nexport function routeKeyOf(method: string, path: string): string {\n const normalized = path\n .replace(/\\/\\d{5,20}\\b/g, \"/{id}\")\n .replace(/\\/[0-9a-f]{24}\\b/gi, \"/{id}\");\n return `${method} ${normalized}`;\n}\n","/**\n * Abstração mínima de WebSocket usada pelo gateway.\n *\n * O SDK usa o `WebSocket` global do Node.js (22+) por padrão e aceita\n * qualquer implementação compatível — inclusive o pacote `ws` e os mocks\n * de teste (`@squord/sdk/testing`).\n */\n\nexport interface WebSocketCloseEvent {\n code: number;\n reason: string;\n wasClean: boolean;\n}\n\nexport interface WebSocketHandlers {\n open: () => void;\n message: (data: string) => void;\n close: (event: WebSocketCloseEvent) => void;\n error: (error: unknown) => void;\n}\n\nexport interface WebSocketLike {\n send(data: string): void;\n close(code?: number, reason?: string): void;\n readonly readyState: number;\n}\n\nexport type WebSocketFactory = (url: string) => unknown;\n\n/** Envelopa a implementação escolhida e normaliza os eventos. */\nexport function attachWebSocket(ws: unknown, handlers: WebSocketHandlers): WebSocketLike {\n const target = ws as {\n send?: (data: string) => void;\n close?: (code?: number, reason?: string) => void;\n readyState?: number;\n addEventListener?: (type: string, listener: (event: never) => void) => void;\n on?: (event: string, listener: (...args: never[]) => unknown) => unknown;\n };\n\n if (typeof target.addEventListener === \"function\") {\n const onOpen = () => handlers.open();\n const onMessage = (event: { data?: unknown }) => {\n const data = event.data;\n if (typeof data === \"string\") handlers.message(data);\n else if (data instanceof ArrayBuffer) handlers.message(new TextDecoder().decode(data));\n else if (data && typeof data === \"object\" && \"toString\" in data) {\n handlers.message(String(data));\n }\n };\n const onClose = (event: { code?: number; reason?: string; wasClean?: boolean }) => {\n handlers.close({\n code: event.code ?? 1005,\n reason: event.reason ?? \"\",\n wasClean: event.wasClean ?? false,\n });\n };\n const onError = (event: unknown) => handlers.error(event);\n\n target.addEventListener(\"open\", onOpen as (event: never) => void);\n target.addEventListener(\"message\", onMessage as (event: never) => void);\n target.addEventListener(\"close\", onClose as (event: never) => void);\n target.addEventListener(\"error\", onError as (event: never) => void);\n\n return {\n send: (data: string) => target.send?.(data),\n close: (code?: number, reason?: string) => target.close?.(code, reason),\n get readyState(): number {\n return target.readyState ?? 0;\n },\n };\n }\n\n // API estilo `ws` (EventEmitter: on(\"open\"), on(\"message\", data), ...)\n const onMessage = (data: unknown) => {\n if (typeof data === \"string\") handlers.message(data);\n else if (Buffer.isBuffer(data)) handlers.message(data.toString(\"utf8\"));\n else handlers.message(String(data));\n };\n const onClose = (code: number, reason: string) =>\n handlers.close({ code, reason, wasClean: true });\n const onError = (error: unknown) => handlers.error(error);\n\n target.on?.(\"open\", handlers.open as (...args: never[]) => unknown);\n target.on?.(\"message\", onMessage as (...args: never[]) => unknown);\n target.on?.(\"close\", onClose as (...args: never[]) => unknown);\n target.on?.(\"error\", onError as (...args: never[]) => unknown);\n\n return {\n send: (data: string) => target.send?.(data),\n close: (code?: number, reason?: string) => target.close?.(code, reason),\n get readyState(): number {\n return target.readyState ?? 0;\n },\n };\n}\n\n/**\n * Fábrica padrão: o `WebSocket` global. Requer Node.js 22+; em versões\n * anteriores, passe `ws` (ou outra implementação) em `GatewayOptions.ws`.\n */\nexport const globalWebSocketFactory: WebSocketFactory = (url) => new WebSocket(url);\n","/**\n * Tipos do protocolo do gateway do Squord.\n *\n * Referência: https://docs.squord.com.br/gateway/visao-geral\n *\n * Todo frame é um objeto JSON em texto UTF-8. Os frames enviados pelo bot têm\n * `{ op, d, requestId? }`; os recebidos têm `{ op, d, timestamp, ... }`.\n */\n\nimport type {\n APIChannel,\n APIGuild,\n APIInteraction,\n APIMember,\n APIMessage,\n APIRole,\n APIThread,\n APIUser,\n} from \"./api\";\nimport type { Snowflake } from \"./common\";\n\n/* ------------------------------------------------------------------ */\n/* Opcodes */\n/* ------------------------------------------------------------------ */\n\n/** Opcodes que o bot pode enviar. */\nexport type ClientOpcode =\n | \"identify\"\n | \"resume\"\n | \"heartbeat\"\n | \"presence.update\"\n // Aceitos pelo protocolo, mas inúteis a bots (assina escopos que já vêm todos).\n | \"subscribe\"\n | \"unsubscribe\"\n // Ignorados pelo servidor quando enviados por bots.\n | \"typing.start\"\n | \"voice.state.update\";\n\n/** Opcodes que o servidor envia. */\nexport type ServerOpcode =\n | \"hello\"\n | \"ready\"\n | \"resumed\"\n | \"heartbeat.ack\"\n | \"invalid_session\"\n | \"reconnect\"\n | \"error\"\n | \"event\";\n\n/* ------------------------------------------------------------------ */\n/* Frames */\n/* ------------------------------------------------------------------ */\n\n/** Base de um frame enviado pelo bot. */\nexport interface GatewayFrame {\n op: ClientOpcode;\n d: unknown;\n /** Até 64 caracteres; o servidor devolve no frame de resposta correspondente. */\n requestId?: string;\n}\n\n/** `hello`: o primeiro frame, assim que a conexão é aceita. */\nexport interface GatewayHello {\n heartbeatIntervalMs: number;\n sessionId: string;\n protocolVersion: number;\n}\n\n/** Corpo do `identify`. */\nexport interface GatewayIdentify {\n token: string;\n protocolVersion: number;\n /** Aceito e ignorado para bots. */\n guildIds?: string[];\n /** Aceito e ignorado para bots. */\n capabilities?: string[];\n}\n\n/** Corpo do `resume`. */\nexport interface GatewayResume {\n token: string;\n sessionId: string;\n lastSequence: number;\n}\n\n/** `ready`: resposta ao `identify`. */\nexport interface GatewayReady {\n sessionId: string;\n /** Id da conta do bot (igual ao id do bot). */\n userId: Snowflake;\n /** Spaces onde o bot está instalado: `id`, `name`, `iconUrl`. */\n guilds: Array<{ id: Snowflake; name: string; iconUrl: string | null }>;\n resumeGatewayUrl: string;\n}\n\n/** `resumed`: resposta ao `resume` (os eventos perdidos chegam antes dele). */\nexport interface GatewayResumed {\n sessionId: string;\n replayed: number;\n sequence: number;\n}\n\n/** `invalid_session`: o `resume` foi recusado; a conexão continua aberta. */\nexport interface GatewayInvalidSession {\n resumable: boolean;\n}\n\n/** `reconnect`: o servidor pediu reconexão; seguido do fechamento 4007. */\nexport interface GatewayReconnect {\n reason: string;\n resumable: boolean;\n}\n\n/** `error`: um frame foi recusado sem fechar a conexão. */\nexport interface GatewayError {\n code: string;\n message: string;\n details?: unknown;\n}\n\nexport type PresenceStatus = \"ONLINE\" | \"IDLE\" | \"DND\" | \"INVISIBLE\";\n\n/** Corpo do `presence.update`. */\nexport interface GatewayPresenceUpdate {\n status?: PresenceStatus;\n /** Até 128 caracteres; `null` apaga. */\n customStatus?: string | null;\n afk?: boolean;\n}\n\n/** Um frame `event` recebido do gateway. */\nexport interface GatewayEventFrame<T = unknown> {\n op: \"event\";\n type: string;\n d: T;\n /** Sequência da sessão; cresce de um em um. Só em eventos duráveis. */\n s?: number;\n timestamp: number;\n}\n\n/** Qualquer frame recebido do servidor. */\nexport type ServerFrame =\n | (GatewayEventFrame & { requestId?: string })\n | ({ op: \"hello\"; d: GatewayHello; timestamp: number; requestId?: string })\n | ({ op: \"ready\"; d: GatewayReady; timestamp: number; requestId?: string })\n | ({ op: \"resumed\"; d: GatewayResumed; timestamp: number; requestId?: string })\n | ({ op: \"heartbeat.ack\"; d: { sequence: number }; timestamp: number; requestId?: string })\n | ({ op: \"invalid_session\"; d: GatewayInvalidSession; timestamp: number; requestId?: string })\n | ({ op: \"reconnect\"; d: GatewayReconnect; timestamp: number; requestId?: string })\n | ({ op: \"error\"; d: GatewayError; timestamp: number; requestId?: string });\n\n/* ------------------------------------------------------------------ */\n/* Códigos de fechamento */\n/* ------------------------------------------------------------------ */\n\nexport const GatewayCloseCodes = {\n UnknownError: 4000,\n UnknownOpcode: 4001,\n DecodeError: 4002,\n NotAuthenticated: 4003,\n AuthenticationFailed: 4004,\n AlreadyAuthenticated: 4005,\n InvalidSequence: 4007,\n RateLimited: 4008,\n SessionTimeout: 4009,\n InvalidProtocolVersion: 4012,\n AccountSuspended: 4013,\n BotSessionLimit: 4014,\n} as const;\n\nexport type GatewayCloseCode = (typeof GatewayCloseCodes)[keyof typeof GatewayCloseCodes];\n\n/* ------------------------------------------------------------------ */\n/* Nomes de eventos */\n/* ------------------------------------------------------------------ */\n\n/** Eventos duráveis entregues pelo gateway (campo `type` do frame `event`). */\nexport type GatewayEventName =\n | \"message.created\"\n | \"message.updated\"\n | \"message.deleted\"\n | \"message.bulk_deleted\"\n | \"poll.vote.cast\"\n | \"poll.vote.removed\"\n | \"reaction.added\"\n | \"reaction.removed\"\n | \"member.joined\"\n | \"member.updated\"\n | \"member.left\"\n | \"member.banned\"\n | \"member.unbanned\"\n | \"guild.updated\"\n | \"guild.deleted\"\n | \"guild.taken_down\"\n | \"guild.boost.added\"\n | \"guild.boost.removed\"\n | \"channel.created\"\n | \"channel.updated\"\n | \"channel.deleted\"\n | \"channel.tree.invalidated\"\n | \"role.created\"\n | \"role.updated\"\n | \"role.deleted\"\n | \"thread.created\"\n | \"thread.updated\"\n | \"thread.deleted\"\n | \"emoji.created\"\n | \"emoji.updated\"\n | \"emoji.deleted\"\n | \"sticker.created\"\n | \"sticker.updated\"\n | \"sticker.deleted\"\n | \"guild_event.created\"\n | \"guild_event.updated\"\n | \"guild_event.deleted\"\n | \"announcement.follow.created\"\n | \"announcement.follow.deleted\"\n | \"voice.state.updated\"\n | \"voice.room.updated\"\n | \"voice.member.moved\"\n | \"voice.e2ee.bot_key_requested\"\n | \"interaction.created\"\n | \"application_command.updated\";\n\n/* ------------------------------------------------------------------ */\n/* Payloads dos eventos */\n/* ------------------------------------------------------------------ */\n\nexport interface PollResults {\n voterCount: number;\n answers: Array<{ answerId: Snowflake; count: number }>;\n}\n\nexport interface PollVotePayload {\n messageId: Snowflake;\n channelId: Snowflake;\n guildId: Snowflake | null;\n userId: Snowflake;\n results: PollResults;\n}\n\nexport interface ReactionAddedPayload {\n messageId: Snowflake;\n channelId: Snowflake;\n guildId: Snowflake | null;\n userId: Snowflake;\n /** A reação após a mudança. O `me` não é confiável num evento. */\n reaction: { emoji: string; count: number; userIds: Snowflake[]; me: boolean };\n /** Emoji customizado resolvido; `null` para emoji padrão. */\n customEmoji: { id: Snowflake; name: string; animated: boolean; url: string } | null;\n}\n\nexport interface ReactionRemovedPayload {\n messageId: Snowflake;\n channelId: Snowflake;\n guildId: Snowflake | null;\n userId: Snowflake;\n emoji: string;\n}\n\nexport interface MessageCreatedPayload {\n message: APIMessage;\n}\n\nexport interface MessageUpdatedPayload {\n message: APIMessage;\n}\n\nexport interface MessageDeletedPayload {\n messageId: Snowflake;\n channelId: Snowflake;\n guildId: Snowflake | null;\n /** Só quando o delete apagou a mensagem mais nova do canal. */\n lastMessageId?: Snowflake | null;\n}\n\nexport interface MessageBulkDeletedPayload {\n messageIds: Snowflake[];\n channelId: Snowflake;\n guildId: Snowflake | null;\n lastMessageId?: Snowflake | null;\n}\n\nexport interface MemberJoinedPayload {\n guildId: Snowflake;\n member: APIMember;\n}\n\nexport interface MemberUpdatedPayload {\n guildId: Snowflake;\n member: APIMember;\n}\n\nexport interface MemberLeftPayload {\n guildId: Snowflake;\n userId: Snowflake;\n}\n\nexport interface MemberBannedPayload {\n guildId: Snowflake;\n userId: Snowflake;\n reason: string | null;\n}\n\nexport interface MemberUnbannedPayload {\n guildId: Snowflake;\n userId: Snowflake;\n}\n\nexport interface GuildUpdatedPayload {\n guild: APIGuild;\n}\n\nexport interface GuildDeletedPayload {\n guildId: Snowflake;\n}\n\nexport interface GuildTakenDownPayload {\n guildId: Snowflake;\n name: string;\n}\n\nexport interface GuildBoostPayload {\n guildId: Snowflake;\n userId: Snowflake;\n boostIds: Snowflake[];\n boostCount: number;\n boostLevel: number;\n previousLevel: number;\n /** Só em `guild.boost.removed`. */\n reason?: \"REMOVED\" | \"MOVED\" | \"LEFT\" | \"LAPSED\" | \"SPACE_GONE\" | \"OPERATOR\";\n}\n\nexport interface ChannelCreatedPayload {\n channel: APIChannel;\n}\n\nexport interface ChannelUpdatedPayload {\n channel: APIChannel;\n}\n\nexport interface ChannelDeletedPayload {\n channelId: Snowflake;\n guildId: Snowflake;\n}\n\nexport interface ChannelTreeInvalidatedPayload {\n guildId: Snowflake;\n}\n\nexport interface RoleCreatedPayload {\n role: APIRole;\n}\n\nexport interface RoleUpdatedPayload {\n role: APIRole;\n}\n\nexport interface RoleDeletedPayload {\n roleId: Snowflake;\n guildId: Snowflake;\n}\n\nexport interface ThreadCreatedPayload {\n thread: APIThread;\n}\n\nexport interface ThreadUpdatedPayload {\n thread: APIThread;\n}\n\nexport interface ThreadDeletedPayload {\n threadId: Snowflake;\n parentId: Snowflake;\n guildId: Snowflake;\n}\n\nexport interface EmojiPayload {\n emoji: {\n id: Snowflake;\n guildId: Snowflake;\n name: string;\n url: string;\n creatorId: Snowflake | null;\n animated: boolean;\n roleIds: Snowflake[];\n available: boolean;\n createdAt: string;\n updatedAt: string;\n };\n}\n\nexport interface EmojiDeletedPayload {\n emojiId: Snowflake;\n guildId: Snowflake;\n}\n\nexport interface StickerPayload {\n sticker: {\n id: Snowflake;\n guildId: Snowflake;\n name: string;\n description: string | null;\n tags: string;\n url: string;\n format: string;\n animated: boolean;\n available: boolean;\n creatorId: Snowflake | null;\n createdAt: string;\n updatedAt: string;\n };\n}\n\nexport interface StickerDeletedPayload {\n stickerId: Snowflake;\n guildId: Snowflake;\n}\n\nexport interface GuildEventPayload {\n event: {\n id: Snowflake;\n guildId: Snowflake;\n name: string;\n description: string | null;\n startsAt: string;\n endsAt: string | null;\n channelId: Snowflake | null;\n location: string | null;\n coverUrl: string | null;\n recurrence: Record<string, unknown> | null;\n earlyReminderMinutes: number | null;\n status: \"SCHEDULED\" | \"ACTIVE\" | \"COMPLETED\" | \"CANCELED\";\n creatorId: Snowflake | null;\n interestedCount: number;\n createdAt: string;\n updatedAt: string;\n };\n}\n\nexport interface GuildEventDeletedPayload {\n eventId: Snowflake;\n guildId: Snowflake;\n}\n\nexport interface AnnouncementFollowCreatedPayload {\n /** Na origem: o seguidor. No destino: o vínculo. Uma das formas chega. */\n follower?: {\n id: Snowflake;\n sourceChannelId: Snowflake;\n guild: { id: Snowflake; name: string; iconUrl: string | null };\n createdAt: string;\n };\n follow?: {\n id: Snowflake;\n targetChannelId: Snowflake;\n targetGuildId: Snowflake;\n source: { id: Snowflake; name: string; iconUrl: string | null };\n createdBy: Snowflake;\n createdAt: string;\n };\n}\n\nexport interface AnnouncementFollowDeletedPayload {\n followId: Snowflake;\n sourceChannelId: Snowflake;\n targetChannelId?: Snowflake;\n}\n\nexport interface VoiceState {\n userId: Snowflake;\n guildId: Snowflake | null;\n channelId: Snowflake;\n sessionId: string;\n serverMute: boolean;\n serverDeaf: boolean;\n selfMute: boolean;\n selfDeaf: boolean;\n selfVideo: boolean;\n selfScreenShare: boolean;\n watchingUserId: Snowflake | null;\n suppressed: boolean;\n joinedAt: string;\n connectedAt: string | null;\n}\n\nexport interface VoiceStateUpdatedPayload {\n /** `null` quando a pessoa saiu da sala. */\n state: VoiceState | null;\n userId: Snowflake;\n channelId: Snowflake;\n}\n\nexport interface VoiceRoomUpdatedPayload {\n room: {\n channelId: Snowflake;\n participants: Array<{ state: VoiceState; user: APIUser }>;\n hasScreenShare: boolean;\n hasVideo: boolean;\n };\n}\n\nexport interface VoiceMemberMovedPayload {\n userId: Snowflake;\n guildId: Snowflake;\n fromChannelId: Snowflake;\n toChannelId: Snowflake;\n state: VoiceState;\n}\n\nexport interface VoiceBotKeyRequestedPayload {\n channelId: Snowflake;\n recipients: Array<{ userId: Snowflake; publicKey: string }>;\n}\n\nexport interface InteractionCreatedPayload extends APIInteraction {}\n\nexport interface ApplicationCommandUpdatedPayload {\n guildId: Snowflake;\n botId: Snowflake;\n}\n","/**\n * Gateway do Squord: WebSocket que entrega eventos em tempo real.\n *\n * Ciclo de vida (https://docs.squord.com.br/gateway/visao-geral):\n * 1. Abre a conexão; o servidor envia `hello` (intervalo de heartbeat).\n * 2. O bot envia `identify` com o token em até 15 segundos.\n * 3. O servidor responde `ready`; os eventos passam a chegar.\n * 4. O bot envia `heartbeat` a cada `heartbeatIntervalMs`; o servidor responde\n * `heartbeat.ack`. Sem ack dentro de um intervalo, a conexão é considerada\n * zumbi e é refeita com `resume`.\n * 5. Após uma queda, o bot reconecta e envia `resume` com a última sequência;\n * o servidor reenvia os eventos perdidos e depois envia `resumed`. Se não\n * puder retomar, responde `invalid_session` na mesma conexão, e o bot faz\n * `identify` de novo.\n *\n * Códigos de fechamento seguem a tabela oficial: 4004/4013/4014 não são\n * retomáveis; 4001/4002/4005/4012 são erros do bot; os demais reconectam com\n * backoff exponencial e jitter, tentando `resume`.\n */\n\nimport type { Logger } from \"../logger\";\nimport { noopLogger } from \"../logger\";\nimport { GatewayError } from \"../errors\";\nimport { TypedEmitter } from \"../utils/TypedEmitter\";\nimport { backoffDelay, sleep } from \"../utils/backoff\";\nimport { attachWebSocket, globalWebSocketFactory } from \"./WebSocketLike\";\nimport type { WebSocketFactory, WebSocketLike } from \"./WebSocketLike\";\nimport { newRequestId } from \"../utils/misc\";\nimport { GatewayCloseCodes } from \"../types/gateway\";\nimport type {\n ClientOpcode,\n GatewayError as GatewayErrorFrame,\n GatewayEventFrame,\n GatewayHello,\n GatewayInvalidSession,\n GatewayPresenceUpdate,\n GatewayReady,\n GatewayReconnect,\n GatewayResumed,\n ServerFrame,\n} from \"../types/gateway\";\n\nexport type GatewayStatus =\n | \"idle\"\n | \"connecting\"\n | \"ready\"\n | \"reconnecting\"\n | \"disconnected\"\n | \"destroyed\";\n\nexport interface GatewayEvents extends Record<string, unknown> {\n ready: GatewayReady;\n resumed: GatewayResumed;\n reconnecting: { attempt: number; delayMs: number; closeCode: number | null; reason: string };\n disconnect: { code: number | null; reason: string; fatal: boolean };\n invalidSession: GatewayInvalidSession;\n serverError: GatewayErrorFrame;\n raw: ServerFrame;\n event: { type: string; d: unknown; s?: number; timestamp: number };\n error: Error;\n statusChange: GatewayStatus;\n}\n\nexport interface GatewayOptions {\n /** URL do gateway. Padrão: `wss://gateway.squord.com.br/gateway`. */\n url?: string;\n /** Token do bot (`sqb_...`), sem prefixo. */\n token: string;\n /** Fábrica de WebSocket (injetável para testes). Padrão: `WebSocket` global. */\n ws?: WebSocketFactory;\n /** Tempo máximo esperando `ready`/`resumed` após o `identify`/`resume`. Padrão: 20000 ms. */\n handshakeTimeoutMs?: number;\n /** `false` para não reconectar automaticamente. */\n autoReconnect?: boolean;\n /** Base do backoff de reconexão, em ms. Padrão: 1000 (dobra até 60000). */\n reconnectBaseMs?: number;\n /** Logger. */\n logger?: Logger;\n}\n\nconst DEFAULT_URL = \"wss://gateway.squord.com.br/gateway\";\nconst PROTOCOL_VERSION = 1;\n\n/** Códigos que encerram sem tentar reconectar com o mesmo token. */\nconst FATAL_CLOSE_CODES = new Set<number>([\n GatewayCloseCodes.AuthenticationFailed, // 4004\n GatewayCloseCodes.AccountSuspended, // 4013\n GatewayCloseCodes.BotSessionLimit, // 4014\n]);\n\n/** Códigos que indicam erro do próprio bot: corrigir antes de reconectar. */\nconst BOT_BUG_CLOSE_CODES = new Set<number>([\n GatewayCloseCodes.UnknownOpcode, // 4001\n GatewayCloseCodes.DecodeError, // 4002\n GatewayCloseCodes.AlreadyAuthenticated, // 4005\n GatewayCloseCodes.InvalidProtocolVersion, // 4012\n]);\n\ninterface HandshakeWaiters {\n resolve: (ready: GatewayReady) => void;\n reject: (error: Error) => void;\n}\n\nexport class Gateway extends TypedEmitter<GatewayEvents> {\n readonly url: string;\n private readonly token: string;\n private readonly wsFactory: WebSocketFactory;\n private readonly handshakeTimeoutMs: number;\n private readonly autoReconnect: boolean;\n private readonly reconnectBaseMs: number;\n private readonly logger: Logger;\n\n private ws: WebSocketLike | null = null;\n private statusValue: GatewayStatus = \"idle\";\n private reconnectAttempts = 0;\n private connectLoop: Promise<GatewayReady> | null = null;\n\n // Estado de sessão (para resume)\n private sessionId: string | null = null;\n private resumeUrl: string | null = null;\n private lastSequence: number | null = null;\n private established = false;\n\n // Handshake em curso\n private handshake: HandshakeWaiters | null = null;\n private handshakeTimer: NodeJS.Timeout | null = null;\n\n // Heartbeat\n private heartbeatIntervalMs: number | null = null;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n private awaitingAck = false;\n private lastHeartbeatSentAt: number | null = null;\n\n private destroyed = false;\n private closingByClient = false;\n private reconnectRequested = false;\n\n /** Latência do gateway: último heartbeat até o ack, em ms. */\n heartbeatLatencyMs: number | null = null;\n /** Quantas reconexões ocorreram desde a criação. */\n reconnectCount = 0;\n /** Quantos frames de evento foram recebidos (incluindo duplicados). */\n eventsReceived = 0;\n /** Quantos eventos foram descartados como duplicados. */\n eventsDropped = 0;\n\n get sequence(): number | null {\n return this.lastSequence;\n }\n get session(): string | null {\n return this.sessionId;\n }\n get status(): GatewayStatus {\n return this.statusValue;\n }\n get isReady(): boolean {\n return this.statusValue === \"ready\";\n }\n\n constructor(options: GatewayOptions) {\n super();\n this.url = options.url ?? DEFAULT_URL;\n this.token = options.token;\n this.wsFactory = options.ws ?? globalWebSocketFactory;\n this.handshakeTimeoutMs = options.handshakeTimeoutMs ?? 20_000;\n this.autoReconnect = options.autoReconnect ?? true;\n this.reconnectBaseMs = options.reconnectBaseMs ?? 1_000;\n this.logger = (options.logger ?? noopLogger).child(\"gateway\");\n }\n\n // ------------------------------------------------------------------\n // API pública\n // ------------------------------------------------------------------\n\n /**\n * Conecta ao gateway e resolve quando a sessão está pronta\n * (`ready` ou `resumed`). Em quedas transitórias, segue tentando com\n * backoff — a promise só é rejeitada em erros não retomáveis\n * (token inválido/revogado, conta suspensa, sessões demais, erro de\n * protocolo) ou se o gateway for destruído.\n */\n async connect(): Promise<GatewayReady> {\n if (this.destroyed) throw new GatewayError(null, null, \"O gateway foi destruído\");\n if (this.isReady) {\n throw new GatewayError(null, null, \"O gateway já está conectado\");\n }\n if (this.connectLoop) return this.connectLoop;\n\n this.closingByClient = false;\n this.connectLoop = this.runConnectLoop().finally(() => {\n this.connectLoop = null;\n });\n return this.connectLoop;\n }\n\n /** Envia `presence.update`. O status escolhido vale também nas próximas conexões. */\n setPresence(presence: GatewayPresenceUpdate): void {\n if (!this.ws) {\n this.emit(\"error\", new GatewayError(null, null, \"Sem conexão para atualizar a presença\"));\n return;\n }\n this.sendFrame(\"presence.update\", presence);\n }\n\n /** Fecha a conexão, encerra as reconexões e descarta o estado de sessão. */\n async destroy(): Promise<void> {\n if (this.destroyed) return;\n this.destroyed = true;\n this.closingByClient = true;\n this.stopHeartbeat();\n this.failHandshake(new GatewayError(null, null, \"Gateway destruído\"));\n this.setStatus(\"destroyed\");\n const ws = this.ws;\n this.ws = null;\n if (ws && ws.readyState <= 1) {\n try {\n ws.close(1000, \"client shutdown\");\n } catch {\n // ignora\n }\n }\n }\n\n /** Descarta o estado de sessão: a próxima conexão fará `identify` limpo. */\n invalidateSession(): void {\n this.sessionId = null;\n this.resumeUrl = null;\n this.lastSequence = null;\n }\n\n /** Força uma reconexão imediata (que tentará `resume`). */\n reconnectNow(): void {\n if (!this.ws) return;\n this.reconnectRequested = true;\n try {\n this.ws.close(4000, \"manual reconnect\");\n } catch {\n // ignora\n }\n }\n\n // ------------------------------------------------------------------\n // Loop de conexão\n // ------------------------------------------------------------------\n\n private async runConnectLoop(): Promise<GatewayReady> {\n this.setStatus(this.sessionId ? \"reconnecting\" : \"connecting\");\n for (;;) {\n try {\n const ready = await this.openSocketOnce(this.resumeUrl ?? this.url);\n this.reconnectAttempts = 0;\n return ready;\n } catch (err) {\n if (this.destroyed) throw err;\n const gatewayErr = err as GatewayError;\n const code = gatewayErr?.closeCode ?? null;\n if (\n code !== null &&\n (FATAL_CLOSE_CODES.has(code) || BOT_BUG_CLOSE_CODES.has(code))\n ) {\n this.setStatus(\"disconnected\");\n this.emit(\"error\", gatewayErr);\n throw gatewayErr;\n }\n\n if (!this.autoReconnect) {\n this.setStatus(\"disconnected\");\n throw err;\n }\n\n const attempt = this.reconnectAttempts++;\n const delayMs = backoffDelay(attempt, { baseMs: this.reconnectBaseMs });\n this.reconnectCount++;\n this.setStatus(\"reconnecting\");\n this.emit(\"reconnecting\", {\n attempt,\n delayMs,\n closeCode: code,\n reason: gatewayErr?.reason ?? String((err as Error)?.message ?? err),\n });\n this.logger.info(\"reconectando\", { attempt, delayMs });\n await sleep(delayMs);\n this.setStatus(this.sessionId ? \"reconnecting\" : \"connecting\");\n }\n }\n }\n\n /** Abre um socket e resolve no `ready`/`resumed` (handshake completo). */\n private openSocketOnce(url: string): Promise<GatewayReady> {\n return new Promise<GatewayReady>((resolve, reject) => {\n let socket: unknown;\n try {\n socket = this.wsFactory(url);\n } catch (err) {\n reject(\n new GatewayError(\n null,\n null,\n `Não foi possível criar o WebSocket para ${url}: ${String((err as Error)?.message ?? err)}`,\n ),\n );\n return;\n }\n\n this.handshake = { resolve, reject };\n this.established = false;\n\n this.handshakeTimer = setTimeout(() => {\n this.failHandshake(\n new GatewayError(\n null,\n null,\n `Handshake do gateway excedeu ${this.handshakeTimeoutMs} ms sem ready/resumed`,\n ),\n );\n }, this.handshakeTimeoutMs);\n\n this.ws = attachWebSocket(socket, {\n open: () => this.logger.debug(\"socket aberto, aguardando hello\"),\n message: (data) => this.handleMessage(data),\n close: (event) => this.handleClose(event.code, event.reason),\n error: (err) =>\n this.logger.debug(\"erro de socket\", {\n err: String((err as Error)?.message ?? err),\n }),\n });\n });\n }\n\n private resolveHandshake(ready: GatewayReady): void {\n const handshake = this.handshake;\n if (!handshake) return;\n this.clearHandshakeTimer();\n this.handshake = null;\n handshake.resolve(ready);\n }\n\n private failHandshake(error: Error): void {\n const handshake = this.handshake;\n this.clearHandshakeTimer();\n if (!handshake) return;\n this.handshake = null;\n handshake.reject(error);\n }\n\n private clearHandshakeTimer(): void {\n if (this.handshakeTimer) {\n clearTimeout(this.handshakeTimer);\n this.handshakeTimer = null;\n }\n }\n\n // ------------------------------------------------------------------\n // Entrada de frames\n // ------------------------------------------------------------------\n\n private handleMessage(data: string): void {\n let frame: ServerFrame;\n try {\n frame = JSON.parse(data) as ServerFrame;\n } catch {\n this.logger.warn(\"frame não-JSON recebido; ignorado\");\n return;\n }\n\n this.emit(\"raw\", frame);\n\n switch (frame.op) {\n case \"hello\":\n this.handleHello(frame.d as GatewayHello);\n break;\n case \"ready\":\n this.handleReady(frame.d as GatewayReady);\n break;\n case \"resumed\":\n this.handleResumed(frame.d as GatewayResumed);\n break;\n case \"heartbeat.ack\":\n this.handleHeartbeatAck(frame.d as { sequence: number });\n break;\n case \"invalid_session\":\n this.handleInvalidSession(frame.d as GatewayInvalidSession);\n break;\n case \"reconnect\":\n this.handleReconnectRequest(frame.d as GatewayReconnect);\n break;\n case \"error\":\n this.handleServerError(frame.d as GatewayErrorFrame);\n break;\n case \"event\":\n this.handleEvent(frame as GatewayEventFrame);\n break;\n default:\n this.logger.debug(\"opcode desconhecido\", {\n op: (frame as { op?: string }).op,\n });\n }\n }\n\n private handleHello(hello: GatewayHello): void {\n this.heartbeatIntervalMs = hello.heartbeatIntervalMs;\n this.logger.debug(\"hello\", { heartbeatIntervalMs: hello.heartbeatIntervalMs });\n\n if (this.sessionId !== null) {\n // Temos sessão: retomar. `lastSequence` 0 é válido quando nenhum\n // evento foi visto ainda; se o servidor não puder retomar, ele\n // responde invalid_session e o identify acontece na mesma conexão.\n this.sendFrame(\"resume\", {\n token: this.token,\n sessionId: this.sessionId,\n lastSequence: this.lastSequence ?? 0,\n });\n } else {\n this.sendFrame(\"identify\", {\n token: this.token,\n protocolVersion: PROTOCOL_VERSION,\n });\n }\n this.startHeartbeat();\n }\n\n private handleReady(ready: GatewayReady): void {\n this.sessionId = ready.sessionId;\n this.resumeUrl = ready.resumeGatewayUrl || this.url;\n this.lastSequence = null;\n this.established = true;\n this.setStatus(\"ready\");\n this.logger.info(\"sessão pronta\", {\n sessionId: ready.sessionId,\n guilds: ready.guilds.length,\n });\n this.emit(\"ready\", ready);\n this.resolveHandshake(ready);\n }\n\n private handleResumed(resumed: GatewayResumed): void {\n this.sessionId = resumed.sessionId;\n this.established = true;\n this.setStatus(\"ready\");\n this.logger.info(\"sessão retomada\", {\n replayed: resumed.replayed,\n sequence: resumed.sequence,\n });\n this.emit(\"resumed\", resumed);\n this.resolveHandshake({\n sessionId: resumed.sessionId,\n userId: \"\",\n guilds: [],\n resumeGatewayUrl: this.resumeUrl ?? this.url,\n });\n }\n\n private handleHeartbeatAck(ack: { sequence: number }): void {\n this.awaitingAck = false;\n if (this.lastHeartbeatSentAt !== null) {\n this.heartbeatLatencyMs = Date.now() - this.lastHeartbeatSentAt;\n }\n this.logger.debug(\"heartbeat.ack\", { sequence: ack.sequence });\n }\n\n private handleInvalidSession(payload: GatewayInvalidSession): void {\n this.logger.warn(\"resume recusado; fazendo identify\", { payload });\n this.emit(\"invalidSession\", payload);\n this.invalidateSession();\n // A conexão continua aberta: identify imediato (o prazo de 15 s reinicia).\n this.sendFrame(\"identify\", {\n token: this.token,\n protocolVersion: PROTOCOL_VERSION,\n });\n }\n\n private handleReconnectRequest(payload: GatewayReconnect): void {\n this.logger.warn(\"servidor pediu reconexão\", { payload });\n // O fechamento 4007 chega em seguida e dispara a reconexão com resume.\n const watchdog = setTimeout(() => {\n if (!this.destroyed && this.ws) {\n this.logger.warn(\"watchdog: fechando para reconectar\");\n try {\n this.ws.close(4000, \"reconnect watchdog\");\n } catch {\n // ignora\n }\n }\n }, 5_000);\n watchdog.unref?.();\n }\n\n private handleServerError(errorFrame: GatewayErrorFrame): void {\n // Frame `error` não fecha a conexão.\n this.emit(\"serverError\", errorFrame);\n this.logger.warn(\"frame error do servidor\", { frame: errorFrame as unknown as Record<string, unknown> });\n }\n\n private handleEvent(frame: GatewayEventFrame): void {\n this.eventsReceived++;\n if (typeof frame.s === \"number\") {\n if (this.lastSequence !== null && frame.s <= this.lastSequence) {\n this.eventsDropped++;\n this.logger.debug(\"evento duplicado descartado\", {\n type: frame.type,\n s: frame.s,\n });\n return;\n }\n this.lastSequence = frame.s;\n }\n this.emit(\"event\", {\n type: frame.type,\n d: frame.d,\n s: frame.s,\n timestamp: frame.timestamp,\n });\n }\n\n // ------------------------------------------------------------------\n // Fechamento\n // ------------------------------------------------------------------\n\n private handleClose(code: number, reason: string): void {\n this.stopHeartbeat();\n this.ws = null;\n const wasEstablished = this.established;\n this.established = false;\n\n if (this.reconnectRequested) {\n this.reconnectRequested = false;\n this.emit(\"disconnect\", { code, reason, fatal: false });\n void this.kickReconnectAfterDrop(code, reason);\n return;\n }\n\n if (this.destroyed || this.closingByClient) {\n this.closingByClient = false;\n this.emit(\"disconnect\", { code, reason, fatal: false });\n this.failHandshake(new GatewayError(code, reason, \"Conexão encerrada\"));\n return;\n }\n\n const fatal = FATAL_CLOSE_CODES.has(code);\n const botBug = BOT_BUG_CLOSE_CODES.has(code);\n\n const error = new GatewayError(\n code,\n reason,\n describeClose(code, reason, fatal, botBug),\n );\n\n this.emit(\"disconnect\", { code, reason, fatal: fatal || botBug });\n\n if (fatal || botBug) {\n this.logger.error(\"conexão encerrada sem retomada\", { code, reason });\n this.setStatus(\"disconnected\");\n this.failHandshake(error);\n return;\n }\n\n if (wasEstablished) {\n // Queda com sessão aberta: o loop externo não está mais ativo;\n // retoma a reconexão agora.\n this.emit(\"error\", error);\n void this.kickReconnectAfterDrop(code, reason);\n } else {\n // Durante o handshake: apenas rejeita; o loop de conexão decide.\n this.failHandshake(error);\n }\n }\n\n private async kickReconnectAfterDrop(code: number, reason: string): Promise<void> {\n if (!this.autoReconnect || this.destroyed) {\n this.setStatus(\"disconnected\");\n return;\n }\n const attempt = this.reconnectAttempts++;\n const delayMs = backoffDelay(attempt, { baseMs: this.reconnectBaseMs });\n this.reconnectCount++;\n this.setStatus(\"reconnecting\");\n this.emit(\"reconnecting\", { attempt, delayMs, closeCode: code, reason });\n this.logger.info(\"reconectando após queda\", { attempt, delayMs, code });\n await sleep(delayMs);\n if (this.destroyed) return;\n this.setStatus(this.sessionId ? \"reconnecting\" : \"connecting\");\n try {\n await this.openSocketOnce(this.resumeUrl ?? this.url);\n this.reconnectAttempts = 0;\n } catch {\n // openSocketOnce só falha o handshake em códigos fatais (tratados\n // via evento error/disconnect) ou timeout, que cai aqui e continua.\n if (!this.destroyed) void this.kickReconnectAfterDrop(code, reason);\n }\n }\n\n // ------------------------------------------------------------------\n // Heartbeat\n // ------------------------------------------------------------------\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n if (!this.heartbeatIntervalMs) return;\n\n // Espalha o primeiro heartbeat por uma fração aleatória do intervalo,\n // para que uma reconexão em massa não chegue toda junta.\n const firstDelay = Math.max(250, Math.random() * this.heartbeatIntervalMs);\n this.heartbeatTimer = setTimeout(() => {\n this.sendHeartbeat();\n if (this.heartbeatIntervalMs) {\n this.heartbeatTimer = setInterval(\n () => this.sendHeartbeat(),\n this.heartbeatIntervalMs,\n );\n }\n }, firstDelay);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearTimeout(this.heartbeatTimer);\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n this.awaitingAck = false;\n }\n\n private sendHeartbeat(): void {\n if (this.destroyed || !this.ws) return;\n\n // Zumbi: o heartbeat anterior ainda não foi confirmado dentro de um\n // intervalo — a recomendação da documentação é assumir conexão zumbi,\n // fechá-la e retomar com `resume`.\n if (this.awaitingAck) {\n this.logger.warn(\"sem heartbeat.ack desde o último heartbeat; conexão zumbi, reconectando\");\n try {\n this.ws.close(4000, \"zombie connection\");\n } catch {\n // ignora\n }\n return;\n }\n\n this.lastHeartbeatSentAt = Date.now();\n this.sendFrame(\"heartbeat\", { s: this.lastSequence ?? undefined });\n this.awaitingAck = true;\n }\n\n // ------------------------------------------------------------------\n\n private sendFrame(op: ClientOpcode, d: unknown): void {\n const ws = this.ws;\n if (!ws) {\n this.logger.debug(\"frame descartado: sem socket\", { op });\n return;\n }\n const payload = JSON.stringify({ op, d, requestId: newRequestId() });\n if (Buffer.byteLength(payload, \"utf8\") > 65_536) {\n this.emit(\n \"error\",\n new GatewayError(null, null, `Frame ${op} excede 65536 bytes e não foi enviado`),\n );\n return;\n }\n try {\n ws.send(payload);\n } catch (err) {\n this.emit(\n \"error\",\n new GatewayError(null, null, `Falha ao enviar frame ${op}: ${String((err as Error)?.message ?? err)}`),\n );\n }\n }\n\n private setStatus(status: GatewayStatus): void {\n if (this.statusValue === status) return;\n this.statusValue = status;\n this.emit(\"statusChange\", status);\n }\n}\n\nfunction describeClose(code: number, reason: string, fatal: boolean, botBug: boolean): string {\n if (fatal) {\n if (code === GatewayCloseCodes.AuthenticationFailed) {\n return `O token foi recusado (4004${reason ? `: ${reason}` : \"\"}). Ele foi trocado, revogado, ou o bot/dono foi excluído ou suspenso. Não reconecte com o mesmo token.`;\n }\n if (code === GatewayCloseCodes.BotSessionLimit) {\n return `O bot já tem 2 sessões simultâneas (4014). Feche uma das sessões antes de reconectar.`;\n }\n return `A conta do bot está suspensa (4013). Não reconecte.`;\n }\n if (botBug) {\n return `Erro de protocolo do bot (código ${code}${reason ? `: ${reason}` : \"\"}). Corrija o código antes de tentar de novo.`;\n }\n return `Conexão do gateway fechou (código ${code}${reason ? `: ${reason}` : \"\"}).`;\n}\n","/**\n * Contrato que o `SquordClient` cumpre para as estruturas (evita ciclo de\n * import em tempo de execução: estruturas importam apenas **tipos** dos\n * managers; as instâncias vêm do cliente).\n */\n\nimport type { ApplicationCommandsManager } from \"../managers/appCommands\";\nimport type { BotManager, UsersManager } from \"../managers/bots\";\nimport type { ChannelsManager } from \"../managers/channels\";\nimport type { InteractionsManager } from \"../managers/interactions\";\nimport type {\n GuildsManager,\n MembersManager,\n ModerationManager,\n RolesManager,\n} from \"../managers/members\";\nimport type { MessagesManager } from \"../managers/messages\";\nimport type { UploadsManager } from \"../managers/uploads\";\nimport type { RestClient } from \"../rest/RestClient\";\n\nexport interface ClientLike {\n readonly rest: RestClient;\n readonly messages: MessagesManager;\n readonly channels: ChannelsManager;\n readonly guilds: GuildsManager;\n readonly members: MembersManager;\n readonly roles: RolesManager;\n readonly moderation: ModerationManager;\n readonly uploads: UploadsManager;\n readonly interactions: InteractionsManager;\n readonly commands: ApplicationCommandsManager;\n readonly bot: BotManager;\n readonly users: UsersManager;\n /** Id da conta do bot (disponível após o login). */\n readonly userId: SnowflakeLike;\n}\n\ntype SnowflakeLike = string | null;\n\n/** Base das estruturas: guarda o payload cru e a referência ao cliente. */\nexport class Structure {\n constructor(\n protected readonly client: ClientLike,\n /** O payload cru devolvido pela API/gateway. */\n readonly raw: Record<string, unknown>,\n ) {}\n}\n","/**\n * Permissões do Squord.\n *\n * Permissões são bits de um número inteiro de 64 bits. Trafegam como\n * **string decimal** e devem ser calculadas com `BigInt`: os bits mais\n * altos passam de 2^53, e um `number` de JavaScript perde precisão.\n *\n * @see https://docs.squord.com.br/referencia/permissoes\n */\n\nimport type { APIChannelOverwrite, PermissionBits } from \"./types/api\";\nimport type { Snowflake } from \"./types/common\";\n\n/** Flags de permissão. O bit 32 (`VIEW_AUDIT_LOG`) está na tabela oficial. */\nexport const Permissions = {\n VIEW_CHANNEL: 1n << 0n,\n MANAGE_CHANNELS: 1n << 1n,\n MANAGE_GUILD: 1n << 2n,\n MANAGE_ROLES: 1n << 3n,\n MANAGE_INVITES: 1n << 4n,\n VIEW_AUDIT_LOG: 1n << 5n,\n MANAGE_EMOJIS: 1n << 6n,\n MANAGE_WEBHOOKS: 1n << 7n,\n KICK_MEMBERS: 1n << 8n,\n BAN_MEMBERS: 1n << 9n,\n TIMEOUT_MEMBERS: 1n << 10n,\n CHANGE_NICKNAME: 1n << 11n,\n MANAGE_NICKNAMES: 1n << 12n,\n SEND_MESSAGES: 1n << 13n,\n READ_MESSAGE_HISTORY: 1n << 14n,\n MANAGE_MESSAGES: 1n << 15n,\n ATTACH_FILES: 1n << 16n,\n EMBED_LINKS: 1n << 17n,\n ADD_REACTIONS: 1n << 18n,\n MENTION_EVERYONE: 1n << 19n,\n USE_EXTERNAL_EMOJIS: 1n << 20n,\n PIN_MESSAGES: 1n << 21n,\n CONNECT: 1n << 22n,\n SPEAK: 1n << 23n,\n VIDEO: 1n << 24n,\n STREAM: 1n << 25n,\n MUTE_MEMBERS: 1n << 26n,\n DEAFEN_MEMBERS: 1n << 27n,\n MOVE_MEMBERS: 1n << 28n,\n PRIORITY_SPEAKER: 1n << 29n,\n ADMINISTRATOR: 1n << 30n,\n SEND_POLLS: 1n << 31n,\n /** O bit 32 foi aposentado e nunca é reutilizado. */\n CREATE_INVITE: 1n << 33n,\n APPROVE_JOIN_REQUESTS: 1n << 34n,\n FORWARD_MESSAGES: 1n << 35n,\n HANDLE_REPORTS: 1n << 36n,\n PUBLISH_ANNOUNCEMENTS: 1n << 37n,\n BYPASS_SLOWMODE: 1n << 38n,\n CREATE_THREADS: 1n << 39n,\n SEND_MESSAGES_IN_THREADS: 1n << 40n,\n MANAGE_THREADS: 1n << 41n,\n MANAGE_EVENTS: 1n << 42n,\n} as const;\n\nexport type PermissionFlag = keyof typeof Permissions;\n\n/** Todas as permissões, somadas. */\nexport const ALL_PERMISSIONS: bigint = Object.values(Permissions).reduce((a, b) => a | b, 0n);\n\n/** Converte bits para string decimal (o formato aceito pela API). */\nexport function permissionsToString(bits: bigint): PermissionBits {\n return bits.toString();\n}\n\n/** Lê uma string decimal vinda da API como `BigInt`. */\nexport function parsePermissions(value: PermissionBits | string): bigint {\n return BigInt(value);\n}\n\n/** Testa se `bits` inclui todas as permissões em `flags`. */\nexport function hasPermissions(\n bits: bigint | PermissionBits,\n ...flags: bigint[]\n): boolean {\n const b = typeof bits === \"string\" ? BigInt(bits) : bits;\n return flags.every((flag) => (b & flag) === flag);\n}\n\n/** Testa se `bits` inclui pelo menos uma das permissões em `flags`. */\nexport function hasAnyPermission(\n bits: bigint | PermissionBits,\n ...flags: bigint[]\n): boolean {\n const b = typeof bits === \"string\" ? BigInt(bits) : bits;\n return flags.some((flag) => (b & flag) === flag);\n}\n\n/**\n * Resolve as permissões efetivas de um membro em um canal, seguindo o\n * algoritmo oficial: base do @everyone + OR dos cargos; `ADMINISTRATOR`\n * encerra a conta; overwrites (@everyone → cargos → membro); sem\n * `VIEW_CHANNEL`, o resultado é zero.\n *\n * O backend continua sendo a autoridade final: o resultado local é uma\n * conveniência para evitar chamadas, não uma garantia.\n */\nexport function resolveChannelPermissions(options: {\n /** Permissões do cargo @everyone (o id do cargo é o próprio id do Space). */\n everyonePermissions: bigint;\n /** Permissões dos cargos do membro (sem contar @everyone). */\n rolePermissions: bigint[];\n /** Overwrites do canal (e da categoria, se houver, aplicados antes). */\n overwrites: APIChannelOverwrite[];\n /** Id do membro. */\n memberId: Snowflake;\n /** Id do cargo @everyone (o mesmo id do Space). */\n everyoneRoleId: Snowflake;\n /** Ids dos cargos do membro, sem contar @everyone. */\n memberRoleIds: Snowflake[];\n}): bigint {\n let base = options.everyonePermissions;\n for (const role of options.rolePermissions) base |= role;\n\n if ((base & Permissions.ADMINISTRATOR) === Permissions.ADMINISTRATOR) {\n return ALL_PERMISSIONS;\n }\n\n const apply = (acc: bigint, overwrites: APIChannelOverwrite[]): bigint => {\n const everyone = overwrites.find((o) => o.targetId === options.everyoneRoleId);\n if (everyone) {\n acc &= ~BigInt(everyone.deny);\n acc |= BigInt(everyone.allow);\n }\n const roleOverwrites = overwrites.filter(\n (o) => o.targetType === \"ROLE\" && options.memberRoleIds.includes(o.targetId),\n );\n const deny = roleOverwrites.reduce((acc2, o) => acc2 | BigInt(o.deny), 0n);\n const allow = roleOverwrites.reduce((acc2, o) => acc2 | BigInt(o.allow), 0n);\n acc &= ~deny;\n acc |= allow;\n const member = overwrites.find((o) => o.targetType === \"MEMBER\" && o.targetId === options.memberId);\n if (member) {\n acc &= ~BigInt(member.deny);\n acc |= BigInt(member.allow);\n }\n return acc;\n };\n\n let result = apply(base, options.overwrites);\n if ((result & Permissions.VIEW_CHANNEL) !== Permissions.VIEW_CHANNEL) return 0n;\n return result;\n}\n\n/**\n * Escopo mínimo usual para um bot que lê e responde em canais.\n * Útil para gerar o valor do link de instalação.\n */\nexport const SUGGESTED_TEXT_BOT_PERMISSIONS: bigint =\n Permissions.VIEW_CHANNEL |\n Permissions.SEND_MESSAGES |\n Permissions.READ_MESSAGE_HISTORY |\n Permissions.EMBED_LINKS |\n Permissions.ATTACH_FILES |\n Permissions.ADD_REACTIONS;\n\n/** Escopo de moderação usual (exige confirmação na instalação). */\nexport const SUGGESTED_MODERATION_PERMISSIONS: bigint =\n Permissions.KICK_MEMBERS |\n Permissions.BAN_MEMBERS |\n Permissions.TIMEOUT_MEMBERS |\n Permissions.MANAGE_MESSAGES;\n","/**\n * Tipos dos payloads reais da API REST do Squord (v1).\n *\n * Espelham o contrato publicado em https://docs.squord.com.br (OpenAPI).\n * Todos os objetos trafegam em JSON UTF-8 com campos em `camelCase`.\n */\n\nimport type { AllowedMentions, CursorPaginationParams, ISODate, Nonce, Page, PermissionBits, Snowflake } from \"./common\";\n\n// Re-exporta os primitivos usados nos payloads, para consumo direto.\nexport type { AllowedMentions, CursorPaginationParams, ISODate, Nonce, Page, PermissionBits, Snowflake } from \"./common\";\n\n/* ------------------------------------------------------------------ */\n/* Usuários */\n/* ------------------------------------------------------------------ */\n\n/** Flags de uma conta, somadas em `flags`. */\nexport const UserFlags = {\n STAFF: 1 << 0,\n EARLY_SUPPORTER: 1 << 1,\n VERIFIED_BOT: 1 << 2,\n SYSTEM: 1 << 3,\n VERIFIED: 1 << 4,\n BOT: 1 << 5,\n} as const;\n\n/** Estilo de nome de usuário (Squord Plus). */\nexport interface APIUserNameStyle {\n font: string;\n effect: string;\n colors: string[];\n}\n\n/** Perfil público de uma conta, embutido em mensagens, membros e interações. */\nexport interface APIUser {\n id: Snowflake;\n /** Handle único em minúsculas. O de um bot começa com `bot~`. */\n username: string;\n displayName: string;\n avatarUrl: string | null;\n /** Só preenchido enquanto o usuário tem Squord Plus. */\n avatarAnimatedUrl: string | null;\n nameStyle: APIUserNameStyle | null;\n flags: number;\n deleted: boolean;\n suspended: boolean;\n premium: boolean;\n}\n\n/** Visão da própria conta (`GET /users/@me`). Em um bot, quase tudo é padrão. */\nexport interface APICurrentUser extends APIUser {\n email: string | null;\n // Campos privados adicionais existem, mas raramente interessam a bots.\n [key: string]: unknown;\n}\n\n/* ------------------------------------------------------------------ */\n/* Bots */\n/* ------------------------------------------------------------------ */\n\n/** O bot na visão do dono (`GET /bots/@me`). */\nexport interface APIBot {\n id: Snowflake;\n user: APIUser;\n description: string | null;\n ownerUsername: string;\n public: boolean;\n verified: boolean;\n installCount: number;\n termsUrl: string | null;\n privacyUrl: string | null;\n createdAt: ISODate;\n /** Soma de bits das intents configuradas (veja {@link Intents}). */\n intents?: number;\n}\n\n/* ------------------------------------------------------------------ */\n/* Spaces (guilds) */\n/* ------------------------------------------------------------------ */\n\n/** Flags de um Space, somadas em `flags`. */\nexport const GuildFlags = {\n OFFICIAL: 1 << 0,\n PARTNER: 1 << 1,\n DISCOVERY_BLOCKED: 1 << 2,\n VERIFIED: 1 << 3,\n DISCOVERY_AGE_WAIVED: 1 << 4,\n} as const;\n\n/** Uma regra publicada do Space. */\nexport interface APIGuildRule {\n title: string;\n description: string;\n}\n\n/** O bot (ou quem chama) dentro de um Space. */\nexport interface APIGuildSelf {\n memberId: Snowflake;\n roleIds: Snowflake[];\n /** Permissões no nível do Space (overwrites de canal ainda se aplicam). */\n permissions: PermissionBits;\n isOwner: boolean;\n}\n\n/** Um Space: comunidade com membros, cargos, canais e regras próprias. */\nexport interface APIGuild {\n id: Snowflake;\n ownerId: Snowflake;\n name: string;\n slug: string;\n description: string | null;\n iconUrl: string | null;\n iconAnimatedUrl: string | null;\n bannerUrl: string | null;\n bannerAnimatedUrl: string | null;\n bannerPlaceholder: string | null;\n defaultChannelId: Snowflake | null;\n systemChannelId: Snowflake | null;\n visibility: string;\n verificationLevel: string;\n accessMode: \"INVITE_ONLY\" | \"LINK\" | \"REQUEST\";\n requireVerifiedEmail: boolean;\n requireTwoFactor: boolean;\n moderationMfaRequired: boolean;\n joinRequestRoleIds: Snowflake[];\n requireJoinMessage: boolean;\n joinRequestRetryDays: number;\n /** Quantas pessoas são membros (não conta bots nem webhooks). */\n memberCount: number;\n flags: number;\n planId: string;\n vanityLapsesAt: ISODate | null;\n vanityInvite: boolean;\n boostCount: number;\n boostLevel: number;\n boostMessages: boolean;\n discoveryCategory: string | null;\n locale: string | null;\n rules: APIGuildRule[];\n rulesUpdatedAt: ISODate | null;\n discoverable: boolean;\n discoverableSince: ISODate | null;\n minAccountAgeDays: number;\n createdAt: ISODate;\n updatedAt: ISODate;\n self: APIGuildSelf;\n}\n\n/* ------------------------------------------------------------------ */\n/* Canais e threads */\n/* ------------------------------------------------------------------ */\n\nexport type ChannelType =\n | \"TEXT\"\n | \"ANNOUNCEMENT\"\n | \"CATEGORY\"\n | \"FORUM\"\n | \"VOICE\"\n | \"STAGE\"\n | \"THREAD\";\n\n/** Exceção de permissão de um cargo ou membro em um canal. */\nexport interface APIChannelOverwrite {\n targetId: Snowflake;\n targetType: \"ROLE\" | \"MEMBER\";\n allow: PermissionBits;\n deny: PermissionBits;\n}\n\n/** Tag de um canal de fórum. */\nexport interface APIForumTag {\n id: Snowflake;\n name: string;\n emoji: string | null;\n moderated: boolean;\n}\n\n/** Um canal do Space (threads têm o formato próprio {@link APIThread}). */\nexport interface APIChannel {\n id: Snowflake;\n guildId: Snowflake;\n categoryId: Snowflake | null;\n name: string;\n type: ChannelType;\n position: number;\n topic: string | null;\n topicUpdatedAt: ISODate | null;\n topicUpdatedById: Snowflake | null;\n isPrivate: boolean;\n /** Modo lento: segundos entre mensagens. `0` desliga. */\n rateLimitPerUser: number;\n bitrate: number | null;\n userLimit: number | null;\n chatEnabled: boolean;\n lastMessageId: Snowflake | null;\n overwrites: APIChannelOverwrite[];\n availableTags: APIForumTag[];\n requireTag: boolean;\n defaultAutoArchiveMinutes: number | null;\n createdAt: ISODate;\n updatedAt: ISODate;\n}\n\n/** Um grupo da árvore de canais de um Space. */\nexport interface APIChannelTreeNode {\n category: APIChannel | null;\n channels: APIChannel[];\n}\n\nexport type ThreadAutoArchiveMinutes = 60 | 1440 | 4320 | 10080;\n\n/** A primeira mensagem de um post de fórum, como o card mostra. */\nexport interface APIThreadPostPreview {\n messageId: Snowflake;\n author: APIUser;\n content: string;\n hasAttachment: boolean;\n hasImage: boolean;\n hasSticker: boolean;\n deleted: boolean;\n moderated: boolean;\n}\n\n/** Uma thread ou post de fórum. Use o `id` como `channelId` nas rotas de mensagem. */\nexport interface APIThread {\n id: Snowflake;\n guildId: Snowflake;\n type: \"THREAD\";\n /** Canal de texto, de anúncios ou fórum de onde ela parte. */\n parentId: Snowflake;\n name: string;\n ownerId: Snowflake;\n starterMessageId: Snowflake | null;\n isForumPost: boolean;\n archived: boolean;\n archivedAt: ISODate | null;\n locked: boolean;\n autoArchiveMinutes: ThreadAutoArchiveMinutes;\n rateLimitPerUser: number;\n messageCount: number;\n lastMessageId: Snowflake | null;\n lastMessageAt: ISODate;\n appliedTagIds: Snowflake[];\n postPreview: APIThreadPostPreview | null;\n createdAt: ISODate;\n updatedAt: ISODate;\n}\n\nexport interface APIThreadPage extends Page<APIThread> {}\n\n/** Corpo de criar thread em canal de texto/anúncios ou a partir de uma mensagem. */\nexport interface APIThreadCreateBody {\n name: string;\n autoArchiveMinutes?: ThreadAutoArchiveMinutes;\n rateLimitPerUser?: number;\n}\n\n/** Corpo de criar um post em fórum. */\nexport interface APIForumPostCreateBody {\n name: string;\n /** A primeira mensagem: corpo de criar mensagem, sem `replyToId`. */\n message: APIMessageCreateBody;\n appliedTagIds?: Snowflake[];\n autoArchiveMinutes?: ThreadAutoArchiveMinutes;\n}\n\nexport interface APIThreadListParams extends CursorPaginationParams {\n /** `true` lista as arquivadas; `false` (padrão), as ativas. */\n archived?: \"true\" | \"false\";\n /** Só em fórum: posts com esta tag. */\n tagId?: Snowflake;\n}\n\n/* ------------------------------------------------------------------ */\n/* Cargos */\n/* ------------------------------------------------------------------ */\n\nexport type RoleManagedKind = \"BOOSTER\" | \"BOT\";\n\n/** Um cargo agrupa permissões e uma aparência. Hierárquico por `position`. */\nexport interface APIRole {\n id: Snowflake;\n guildId: Snowflake;\n name: string;\n color: string | null;\n position: number;\n permissions: PermissionBits;\n hoist: boolean;\n mentionable: boolean;\n managed: boolean;\n managedKind: RoleManagedKind | null;\n botId: Snowflake | null;\n icon: string | null;\n selfAssignable: boolean;\n createdAt: ISODate;\n updatedAt: ISODate;\n}\n\n/* ------------------------------------------------------------------ */\n/* Membros */\n/* ------------------------------------------------------------------ */\n\nexport type MemberType = \"INTERNAL\" | \"BOT\" | \"WEBHOOK\";\n\nexport interface APIMemberNameStyle {\n font: string;\n effect: string;\n colors: string[];\n}\n\n/** Perfil de um usuário dentro de um Space, com o `user` embutido. */\nexport interface APIMember {\n id: Snowflake;\n guildId: Snowflake;\n userId: Snowflake;\n user: APIUser;\n type: MemberType;\n nickname: string | null;\n avatarUrl: string | null;\n avatarAnimatedUrl: string | null;\n bannerUrl: string | null;\n bannerAnimatedUrl: string | null;\n bio: string | null;\n bioEmojis: Array<{ id: Snowflake; name: string; animated: boolean; url: string }>;\n nameStyle: APIMemberNameStyle | null;\n profileFont: string | null;\n profileTheme: string[] | null;\n roleIds: Snowflake[];\n joinedAt: ISODate;\n timeoutUntil: ISODate | null;\n deaf: boolean;\n mute: boolean;\n pending: boolean;\n boostingSince: ISODate | null;\n createdAt: ISODate;\n updatedAt: ISODate;\n}\n\nexport interface APIMemberPage extends Page<APIMember> {}\n\n/** Corpo de `PATCH /guilds/{guildId}/members/{userId}` (todos os campos opcionais). */\nexport interface APIMemberEditBody {\n /** `null` limpa o apelido. */\n nickname?: string | null;\n /** **Substitui** o conjunto de cargos. */\n roleIds?: Snowflake[];\n /** Data futura aplica timeout; `null` retira. */\n timeoutUntil?: ISODate | null;\n deaf?: boolean;\n mute?: boolean;\n}\n\nexport interface APIMemberKickBody {\n reason?: string | null;\n}\n\nexport interface APIMemberBanBody {\n reason?: string | null;\n /** Quanto do histórico recente apagar, em segundos (até 7 dias). */\n deleteMessageSeconds?: number;\n}\n\n/** Um banimento. */\nexport interface APIMemberBan {\n id: Snowflake;\n guildId: Snowflake;\n userId: Snowflake;\n moderatorId: Snowflake;\n byPlatform: boolean;\n reason: string | null;\n createdAt: ISODate;\n}\n\n/* ------------------------------------------------------------------ */\n/* Mensagens */\n/* ------------------------------------------------------------------ */\n\nexport type MessageType =\n | \"DEFAULT\"\n | \"REPLY\"\n | \"POLL\"\n | \"SYSTEM_MEMBER_JOIN\"\n | \"SYSTEM_MEMBER_LEAVE\"\n | \"SYSTEM_CHANNEL_PINNED\"\n | \"SYSTEM_CALL_STARTED\"\n | \"SYSTEM_GROUP_CREATED\"\n | \"SYSTEM_MEMBER_ADDED\"\n | \"SYSTEM_MEMBER_REMOVED\"\n | \"SYSTEM_GROUP_LEFT\"\n | \"SYSTEM_CHANNEL_FOLLOWED\"\n | \"SYSTEM_GUILD_BOOST\"\n | \"SYSTEM_THREAD_CREATED\"\n | \"SYSTEM_AUTOMOD_ALERT\";\n\nexport type AttachmentScanStatus =\n | \"NOT_REQUIRED\"\n | \"PENDING\"\n | \"CLEAN\"\n | \"INFECTED\"\n | \"FAILED\"\n | \"EXPLICIT\";\n\n/** Arquivo anexado a uma mensagem. Para enviar, veja {@link APIUpload}. */\nexport interface APIAttachment {\n id: Snowflake;\n kind: string;\n source: \"UPLOAD\" | \"KLIPY\";\n providerId: string | null;\n filename: string;\n contentType: string;\n size: number;\n url: string;\n thumbnailUrl: string | null;\n width: number | null;\n height: number | null;\n durationMs: number | null;\n placeholder: string | null;\n scanStatus: AttachmentScanStatus;\n}\n\n/** Embed como é **lido**. O que se envia usa {@link APIEmbedInput}. */\nexport interface APIEmbed {\n type: \"RICH\" | \"LINK\" | \"IMAGE\" | \"VIDEO\";\n url: string | null;\n title: string | null;\n description: string | null;\n siteName: string | null;\n thumbnailUrl: string | null;\n color: string | null;\n author: { name: string; url?: string | null; iconUrl?: string | null } | null;\n fields: Array<{ name: string; value: string; inline?: boolean }>;\n image: { url: string } | null;\n footer: { text: string; iconUrl?: string | null } | null;\n timestamp: ISODate | null;\n video: { url: string } | null;\n}\n\n/** Embed que se **envia** (formato aceito pelo Squord). */\nexport interface APIEmbedInput {\n title?: string | null;\n description?: string | null;\n /** Só `http://` ou `https://`. */\n url?: string | null;\n /** Inteiro de 0 a 16777215, ou `#rrggbb`. */\n color?: number | string | null;\n /** ISO 8601 com fuso. */\n timestamp?: string | null;\n author?: { name: string; url?: string | null; /** snake_case na API. */ icon_url?: string | null } | null;\n footer?: { text: string; icon_url?: string | null } | null;\n image?: { url: string } | null;\n thumbnail?: { url: string } | null;\n fields?: Array<{ name: string; value: string; inline?: boolean }>;\n}\n\nexport interface APIReaction {\n /** Emoji Unicode, ou `<:nome:id>` / `<a:nome:id>` para um personalizado. */\n emoji: string;\n count: number;\n userIds: Snowflake[];\n me: boolean;\n}\n\nexport interface APIMessageEmoji {\n id: Snowflake;\n name: string;\n animated: boolean;\n url: string;\n}\n\nexport interface APIMessageMentions {\n userIds: Snowflake[];\n roleIds: Snowflake[];\n channelIds: Snowflake[];\n everyone: boolean;\n}\n\nexport interface APIMessageInteractionMeta {\n id: Snowflake;\n type: string;\n name: string | null;\n userId: Snowflake;\n}\n\nexport interface APIStickerItem {\n id: Snowflake;\n guildId: Snowflake;\n name: string;\n format: string;\n url: string;\n}\n\n/** A mensagem citada em uma resposta. */\nexport interface APIMessageReplyTo {\n id: Snowflake;\n authorId: Snowflake;\n author: APIUser;\n content: string;\n deleted: boolean;\n moderated: boolean;\n preview?: Record<string, unknown>;\n}\n\n/** Uma mensagem com o autor. */\nexport interface APIMessage {\n id: Snowflake;\n /** `null` em mensagem direta (bots não acessam DMs). */\n guildId: Snowflake | null;\n channelId: Snowflake;\n authorId: Snowflake;\n type: MessageType;\n content: string;\n replyToId: Snowflake | null;\n attachments: APIAttachment[];\n embeds: APIEmbed[];\n components: APIComponentRow[];\n interaction: APIMessageInteractionMeta | null;\n mentions: APIMessageMentions;\n reactions: APIReaction[];\n pinned: boolean;\n editedAt: ISODate | null;\n deletedAt: ISODate | null;\n moderated: boolean;\n nonce: Nonce | null;\n call: Record<string, unknown> | null;\n poll: Record<string, unknown> | null;\n forward: Record<string, unknown> | null;\n relay: Record<string, unknown> | null;\n relayedCount: number | null;\n stickers: APIStickerItem[];\n emojis: APIMessageEmoji[];\n thread: Record<string, unknown> | null;\n automod: Record<string, unknown> | null;\n createdAt: ISODate;\n updatedAt: ISODate;\n author: APIUser;\n memberNickname: string | null;\n memberAvatarUrl: string | null;\n memberNameStyle: APIMemberNameStyle | null;\n replyTo: APIMessageReplyTo | null;\n}\n\nexport interface APIMessagePage extends Page<APIMessage> {}\n\n/** Corpo de criar mensagem. Ao menos um entre `content`, `embeds`, `components` e `attachmentIds`. */\nexport interface APIMessageCreateBody {\n content?: string;\n embeds?: APIEmbedInput[];\n components?: APIComponentRow[];\n allowedMentions?: AllowedMentions;\n replyToId?: Snowflake | null;\n attachmentIds?: Snowflake[];\n /** Chave de idempotência (até 64 caracteres): repetir devolve a original. */\n nonce?: Nonce | null;\n}\n\n/** Corpo de editar mensagem. `embeds`/`components` substituem a lista inteira. */\nexport interface APIMessageEditBody {\n content?: string;\n embeds?: APIEmbedInput[];\n components?: APIComponentRow[];\n allowedMentions?: AllowedMentions;\n}\n\nexport interface APIMessageListParams extends CursorPaginationParams {}\n\n/* ------------------------------------------------------------------ */\n/* Componentes (botões e menus) */\n/* ------------------------------------------------------------------ */\n\nexport type ButtonStyle = \"primary\" | \"secondary\" | \"danger\" | \"link\";\n\nexport interface APIButton {\n type: \"button\";\n style: ButtonStyle;\n label: string;\n customId?: string;\n url?: string;\n disabled?: boolean;\n}\n\nexport interface APISelectOption {\n label: string;\n value: string;\n description?: string;\n}\n\nexport interface APISelectMenu {\n type: \"select\";\n customId: string;\n placeholder?: string;\n minValues?: number;\n maxValues?: number;\n disabled?: boolean;\n options: APISelectOption[];\n}\n\n/** Uma linha de componentes: 1 a 5 botões **ou** exatamente 1 menu. */\nexport interface APIComponentRow {\n type: \"row\";\n components: Array<APIButton | APISelectMenu>;\n}\n\n/* ------------------------------------------------------------------ */\n/* Comandos de aplicação (slash) */\n/* ------------------------------------------------------------------ */\n\nexport type CommandOptionType = \"STRING\" | \"INTEGER\" | \"BOOLEAN\" | \"USER\" | \"CHANNEL\" | \"ROLE\";\n\nexport interface APICommandOptionChoice {\n name: string;\n value: string | number;\n}\n\n/** Uma opção na **definição** de um comando. */\nexport interface APICommandOptionInput {\n type: CommandOptionType;\n /** Letras minúsculas, números, `_` e `-` (até 32 caracteres). */\n name: string;\n description: string;\n required?: boolean;\n choices?: APICommandOptionChoice[];\n}\n\n/** Uma opção no objeto comando devolvido pela API. */\nexport interface APICommandOption extends APICommandOptionInput {\n required: boolean;\n}\n\n/** Um comando de barra registrado por um bot. */\nexport interface APICommand {\n id: Snowflake;\n botId: Snowflake;\n guildId: Snowflake | null;\n name: string;\n description: string;\n options: APICommandOption[];\n updatedAt: ISODate;\n}\n\n/** Um comando no corpo do `PUT` em bloco. */\nexport interface APICommandInput {\n name: string;\n description: string;\n options?: APICommandOptionInput[];\n}\n\n/* ------------------------------------------------------------------ */\n/* Interações */\n/* ------------------------------------------------------------------ */\n\nexport type InteractionType = \"COMMAND\" | \"COMPONENT\";\n\nexport type InteractionCallbackType = \"MESSAGE\" | \"DEFERRED\" | \"UPDATE\" | \"DEFERRED_UPDATE\";\n\n/** Dados de um comando invocado: as opções já validadas pelo Squord. */\nexport interface APIInteractionCommandData {\n id: Snowflake;\n name: string;\n options: Array<{\n name: string;\n type: CommandOptionType;\n value: string | number | boolean;\n }>;\n}\n\n/** Dados de um clique/uso de componente. */\nexport interface APIInteractionComponentData {\n messageId: Snowflake;\n customId: string;\n type: \"button\" | \"select\";\n /** Valores escolhidos em um menu; vazio em um botão. */\n values: string[];\n}\n\n/** O `d` do evento `interaction.created`. Nenhuma rota REST devolve este objeto. */\nexport interface APIInteraction {\n id: Snowflake;\n /** Credencial da interação, válida por 15 minutos. Trate como segredo. */\n token: string;\n type: InteractionType;\n guildId: Snowflake;\n channelId: Snowflake;\n user: APIUser;\n member: APIMember | null;\n command?: APIInteractionCommandData;\n component?: APIInteractionComponentData;\n createdAt: ISODate;\n}\n\n/** Dados da resposta de uma interação ou follow-up. */\nexport interface APIInteractionReplyData {\n content?: string;\n embeds?: APIEmbedInput[];\n components?: APIComponentRow[];\n allowedMentions?: AllowedMentions;\n /** Só a pessoa que invocou vê. Não é salva; só aceita botões de link. */\n ephemeral?: boolean;\n}\n\nexport interface APIInteractionCallbackBody {\n type: InteractionCallbackType;\n data?: APIInteractionReplyData;\n}\n\n/* ------------------------------------------------------------------ */\n/* Uploads */\n/* ------------------------------------------------------------------ */\n\n/** Estado de um upload. */\nexport type UploadStatus = \"PENDING\" | \"READY\" | \"ATTACHED\";\n\n/** Um upload reservado/confirmado. */\nexport interface APIUpload {\n id: Snowflake;\n scope: string;\n filename: string;\n contentType: string;\n size: number;\n status: UploadStatus;\n url: string | null;\n thumbnailUrl: string | null;\n guildId: Snowflake | null;\n storageKey: string;\n scanStatus: AttachmentScanStatus;\n animated: boolean;\n animatedUrl: string | null;\n createdAt: ISODate;\n expiresAt: ISODate;\n}\n\n/** Alvo do `PUT` dos bytes, devolvido só na reserva. */\nexport interface APIUploadTarget {\n uploadUrl: string;\n method: \"PUT\";\n /** Cabeçalhos que o `PUT` precisa repetir exatamente. */\n headers: Record<string, string>;\n storageKey: string;\n publicUrl: string;\n expiresAt: ISODate;\n}\n\nexport interface APIUploadReservation {\n upload: APIUpload;\n target: APIUploadTarget;\n}\n\nexport interface APIUploadCreateBody {\n /** Para bots, sempre `attachments`. */\n scope: string;\n filename: string;\n contentType: string;\n size: number;\n guildId: Snowflake | null;\n}\n\n/** Corpo da confirmação de upload. Pode ser `{}`. */\nexport interface APIUploadConfirmBody {\n crop?: { left: number; top: number; width: number; height: number } | null;\n placeholder?: string | null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Erros */\n/* ------------------------------------------------------------------ */\n\n/** Envelope de todo erro da API. Decida pelo `code`, nunca pela `message`. */\nexport interface APIErrorBody {\n statusCode: number;\n code: string;\n message: string;\n details?: unknown;\n requestId?: string;\n}\n\n/** Item de validação de um `422 VALIDATION_FAILED`. */\nexport interface APIValidationIssue {\n path: string;\n code: string;\n message: string;\n params?: Record<string, unknown>;\n}\n\n/** Detalhes de um `429 RATE_LIMITED`. */\nexport interface APIRateLimitDetails {\n bucket: string;\n /** Segundos de espera (mínimo 1). Existe em toda recusa. */\n retryAfter: number;\n}\n\n/* ------------------------------------------------------------------ */\n/* Menções (formatação de conteúdo) */\n/* ------------------------------------------------------------------ */\n\n/** Menção de pessoa: `<@ID>`. */\nexport function userMention(id: Snowflake): string {\n return `<@${id}>`;\n}\n\n/** Menção de cargo: `<@&ID>`. */\nexport function roleMention(id: Snowflake): string {\n return `<@&${id}>`;\n}\n\n/** Menção de canal: `<#ID>`. */\nexport function channelMention(id: Snowflake): string {\n return `<#${id}>`;\n}\n","/**\n * Estruturas de usuário, membro, cargo e Space.\n */\n\nimport type {\n APIMember,\n APIRole,\n APIUser,\n APIGuild,\n} from \"../types/api\";\nimport type { ISODate, Snowflake } from \"../types/common\";\nimport { hasPermissions, parsePermissions } from \"../permissions\";\nimport { UserFlags } from \"../types/api\";\nimport { Structure } from \"./base\";\nimport type { ClientLike } from \"./base\";\nimport { Channel } from \"./Channel\";\n\n/** Conta de usuário (pessoa ou bot). */\nexport class User extends Structure {\n constructor(client: ClientLike, raw: APIUser) {\n super(client, raw as unknown as Record<string, unknown>);\n }\n\n get data(): APIUser {\n return this.raw as unknown as APIUser;\n }\n\n get id(): Snowflake {\n return this.data.id;\n }\n get username(): string {\n return this.data.username;\n }\n get displayName(): string {\n return this.data.displayName;\n }\n get avatarUrl(): string | null {\n return this.data.avatarUrl;\n }\n /** `true` para contas de bot (flag `BOT`). */\n get isBot(): boolean {\n return (this.data.flags & UserFlags.BOT) !== 0;\n }\n /** `true` para bots verificados pelo Squord. */\n get isVerifiedBot(): boolean {\n return (this.data.flags & UserFlags.VERIFIED_BOT) !== 0;\n }\n get deleted(): boolean {\n return this.data.deleted;\n }\n get suspended(): boolean {\n return this.data.suspended;\n }\n\n /** Menção `<@id>` para usar no conteúdo de mensagens. */\n get mention(): string {\n return `<@${this.id}>`;\n }\n\n /** Busca o membro correspondente em um Space. */\n member(guildId: Snowflake): Promise<Member | null> {\n return this.client.members\n .fetch(guildId, this.id)\n .then((m) => new Member(this.client, m))\n .catch(() => null);\n }\n}\n\n/** Perfil de um usuário dentro de um Space. */\nexport class Member extends Structure {\n constructor(client: ClientLike, raw: APIMember) {\n super(client, raw as unknown as Record<string, unknown>);\n }\n\n get data(): APIMember {\n return this.raw as unknown as APIMember;\n }\n\n /** Id da participação (não confundir com o id da conta). */\n get id(): Snowflake {\n return this.data.id;\n }\n get guildId(): Snowflake {\n return this.data.guildId;\n }\n get userId(): Snowflake {\n return this.data.userId;\n }\n get user(): User {\n return new User(this.client, this.data.user);\n }\n get nickname(): string | null {\n return this.data.nickname;\n }\n /** Nome de exibição efetivo: apelido no Space ou `displayName`. */\n get displayName(): string {\n return this.data.nickname ?? this.data.user.displayName;\n }\n get roleIds(): Snowflake[] {\n return this.data.roleIds;\n }\n get joinedAt(): ISODate {\n return this.data.joinedAt;\n }\n /** `null` ou data futura: enquanto futura, o membro está de castigo. */\n get timeoutUntil(): ISODate | null {\n return this.data.timeoutUntil;\n }\n get isTimedOut(): boolean {\n return this.timeoutUntil !== null && Date.parse(this.timeoutUntil) > Date.now();\n }\n get isBot(): boolean {\n return this.data.type === \"BOT\";\n }\n get mention(): string {\n return `<@${this.userId}>`;\n }\n\n /** Menciona o cargo do membro? Cargos não mencionáveis não notificam. */\n get mentionNicknameOnly(): string {\n return `<@!${this.userId}>`;\n }\n\n /** Recarrega o membro da API. */\n fetch(): Promise<Member> {\n return this.client.members\n .fetch(this.guildId, this.userId)\n .then((m) => new Member(this.client, m));\n }\n\n /** Lista os cargos do membro no Space. */\n fetchRoles(): Promise<Role[]> {\n return this.client.roles\n .list(this.guildId)\n .then((roles) =>\n roles\n .filter((r) => this.roleIds.includes(r.id) || r.id === this.guildId)\n .map((r) => new Role(this.client, r)),\n );\n }\n\n /** Dá um cargo ao membro (respeita hierarquia; cargos gerenciados dão `400 ROLE_MANAGED`). */\n addRole(roleId: Snowflake): Promise<void> {\n return this.client.members.addRole(this.guildId, this.userId, roleId);\n }\n\n /** Tira um cargo do membro. */\n removeRole(roleId: Snowflake): Promise<void> {\n return this.client.members.removeRole(this.guildId, this.userId, roleId);\n }\n\n /** Muda o apelido (`MANAGE_NICKNAMES`, ou `CHANGE_NICKNAME` em si mesmo). */\n setNickname(nickname: string | null): Promise<Member> {\n return this.client.members\n .edit(this.guildId, this.userId, { nickname })\n .then((m) => new Member(this.client, m));\n }\n\n /** Aplica timeout até uma data (`TIMEOUT_MEMBERS`). */\n timeout(until: ISODate | Date): Promise<Member> {\n const iso = until instanceof Date ? until.toISOString() : until;\n return this.client.members\n .edit(this.guildId, this.userId, { timeoutUntil: iso })\n .then((m) => new Member(this.client, m));\n }\n\n /** Remove o timeout. */\n removeTimeout(): Promise<Member> {\n return this.client.members\n .edit(this.guildId, this.userId, { timeoutUntil: null })\n .then((m) => new Member(this.client, m));\n }\n\n /** Expulsa o membro (`KICK_MEMBERS`). Ele pode voltar com novo convite. */\n kick(reason?: string): Promise<void> {\n return this.client.members.kick(this.guildId, this.userId, reason);\n }\n\n /** Bane o membro (`BAN_MEMBERS`). */\n ban(options: { reason?: string; deleteMessageSeconds?: number } = {}): Promise<void> {\n return this.client.moderation\n .ban(this.guildId, this.userId, options)\n .then(() => undefined);\n }\n}\n\n/** Um cargo do Space. */\nexport class Role extends Structure {\n constructor(client: ClientLike, raw: APIRole) {\n super(client, raw as unknown as Record<string, unknown>);\n }\n\n get data(): APIRole {\n return this.raw as unknown as APIRole;\n }\n\n get id(): Snowflake {\n return this.data.id;\n }\n get guildId(): Snowflake {\n return this.data.guildId;\n }\n get name(): string {\n return this.data.name;\n }\n get color(): string | null {\n return this.data.color;\n }\n get position(): number {\n return this.data.position;\n }\n /** Bits como `BigInt` (permissões trafegam como string decimal). */\n get permissions(): bigint {\n return parsePermissions(this.data.permissions);\n }\n /** Testa se o cargo concede um conjunto de permissões. */\n has(...flags: bigint[]): boolean {\n return hasPermissions(this.permissions, ...flags);\n }\n get managed(): boolean {\n return this.data.managed;\n }\n get managedKind(): string | null {\n return this.data.managedKind;\n }\n get mentionable(): boolean {\n return this.data.mentionable;\n }\n /** Menção `<@&id>`; só notifica se o cargo for mencionável. */\n get mention(): string {\n return `<@&${this.id}>`;\n }\n /** `true` para o cargo @everyone (o id é o próprio id do Space). */\n get isEveryone(): boolean {\n return this.id === this.guildId;\n }\n}\n\n/** Um Space (comunidade). */\nexport class Guild extends Structure {\n constructor(client: ClientLike, raw: APIGuild) {\n super(client, raw as unknown as Record<string, unknown>);\n }\n\n get data(): APIGuild {\n return this.raw as unknown as APIGuild;\n }\n\n get id(): Snowflake {\n return this.data.id;\n }\n get name(): string {\n return this.data.name;\n }\n get slug(): string {\n return this.data.slug;\n }\n get ownerId(): Snowflake {\n return this.data.ownerId;\n }\n get memberCount(): number {\n return this.data.memberCount;\n }\n get iconUrl(): string | null {\n return this.data.iconUrl;\n }\n get boostCount(): number {\n return this.data.boostCount;\n }\n\n /** O bot neste Space: id de participação, cargos e permissões no nível do Space. */\n get self(): { memberId: Snowflake; roleIds: Snowflake[]; permissions: bigint; isOwner: boolean } {\n const self = this.data.self;\n return {\n memberId: self.memberId,\n roleIds: self.roleIds,\n permissions: parsePermissions(self.permissions),\n isOwner: self.isOwner,\n };\n }\n\n /** Testa permissões do bot no nível do Space (overwrites de canal à parte). */\n botHas(...flags: bigint[]): boolean {\n return hasPermissions(this.self.permissions, ...flags);\n }\n\n /** Recarrega o Space. */\n fetch(): Promise<Guild> {\n return this.client.guilds\n .fetch(this.id)\n .then((g) => new Guild(this.client, g));\n }\n\n /** Árvore de canais do Space, agrupada por categorias. */\n fetchChannelTree(): Promise<ChannelTreeGroup[]> {\n return this.client.channels\n .fetchTree(this.id)\n .then((nodes) =>\n nodes.map((node) => ({\n category: node.category ? new Channel(this.client, node.category) : null,\n channels: node.channels.map((c) => new Channel(this.client, c)),\n })),\n );\n }\n\n /** Lista os cargos do Space. */\n fetchRoles(): Promise<Role[]> {\n return this.client.roles\n .list(this.id)\n .then((roles) => roles.map((r) => new Role(this.client, r)));\n }\n\n /** Busca um membro pelo id da conta. */\n fetchMember(userId: Snowflake): Promise<Member> {\n return this.client.members\n .fetch(this.id, userId)\n .then((m) => new Member(this.client, m));\n }\n}\n\n/** Grupo da árvore de canais (categoria e seus canais). */\nexport interface ChannelTreeGroup {\n category: Channel | null;\n channels: Channel[];\n}\n","/**\n * Estrutura de mensagem: leitura e ações de alto nível\n * (responder, editar, apagar, reagir, fixar, abrir thread).\n */\n\nimport type {\n APIMessage,\n APIReaction,\n MessageType,\n Snowflake,\n ThreadAutoArchiveMinutes,\n} from \"../types/api\";\nimport type { ISODate } from \"../types/common\";\nimport type { MessagePayloadLike } from \"../builders/message\";\nimport { Structure } from \"./base\";\nimport type { ClientLike } from \"./base\";\nimport { Channel, Thread } from \"./Channel\";\nimport { User } from \"./User\";\n\nexport class Message extends Structure {\n constructor(client: ClientLike, raw: APIMessage) {\n super(client, raw as unknown as Record<string, unknown>);\n }\n\n get data(): APIMessage {\n return this.raw as unknown as APIMessage;\n }\n\n get id(): Snowflake {\n return this.data.id;\n }\n get guildId(): Snowflake | null {\n return this.data.guildId;\n }\n get channelId(): Snowflake {\n return this.data.channelId;\n }\n get authorId(): Snowflake {\n return this.data.authorId;\n }\n get author(): User {\n return new User(this.client, this.data.author);\n }\n get type(): MessageType {\n return this.data.type;\n }\n get content(): string {\n return this.data.content;\n }\n get replyToId(): Snowflake | null {\n return this.data.replyToId;\n }\n get pinned(): boolean {\n return this.data.pinned;\n }\n get editedAt(): ISODate | null {\n return this.data.editedAt;\n }\n get moderated(): boolean {\n return this.data.moderated;\n }\n get attachments(): APIMessage[\"attachments\"] {\n return this.data.attachments;\n }\n get embeds(): APIMessage[\"embeds\"] {\n return this.data.embeds;\n }\n get components(): APIMessage[\"components\"] {\n return this.data.components;\n }\n get reactions(): APIReaction[] {\n return this.data.reactions;\n }\n get createdAt(): ISODate {\n return this.data.createdAt;\n }\n /** Apelido do autor no Space (quando houver). */\n get memberNickname(): string | null {\n return this.data.memberNickname;\n }\n /** Nome de exibição efetivo do autor (apelido ou displayName). */\n get authorDisplayName(): string {\n return this.data.memberNickname ?? this.data.author.displayName;\n }\n\n /** `true` se a mensagem veio do próprio bot. */\n get fromMe(): boolean {\n return this.client.userId !== null && this.authorId === this.client.userId;\n }\n\n /** `true` se o bot foi mencionado (`<@id>` no conteúdo). */\n get mentionsMe(): boolean {\n return this.client.userId !== null && this.data.mentions.userIds.includes(this.client.userId);\n }\n\n /** Ids mencionados na mensagem (só as menções que valeram). */\n get mentionedUserIds(): Snowflake[] {\n return this.data.mentions.userIds;\n }\n get mentionedRoleIds(): Snowflake[] {\n return this.data.mentions.roleIds;\n }\n get mentionsEveryone(): boolean {\n return this.data.mentions.everyone;\n }\n\n /** Recarrega a mensagem (ela pode ter sido apagada; isso lança 404). */\n fetch(): Promise<Message> {\n return this.client.messages\n .fetch(this.channelId, this.id)\n .then((m) => new Message(this.client, m));\n }\n\n /** Busca o canal da mensagem (uma thread também é canal). */\n fetchChannel(): Promise<Channel | Thread | null> {\n return this.client.channels\n .fetch(this.channelId)\n .then((channel) =>\n channel.type === \"THREAD\"\n ? new Thread(this.client, channel as never)\n : new Channel(this.client, channel),\n )\n .catch(() => null);\n }\n\n /** Responde a mensagem (usa `replyToId`). Idempotente por `nonce`. */\n reply(payload: MessagePayloadLike, options?: { signal?: AbortSignal; nonce?: string }): Promise<Message> {\n const source = typeof payload === \"string\" ? { content: payload } : payload;\n return this.client.messages\n .send(this.channelId, { ...source, replyToId: this.id }, options)\n .then((m) => new Message(this.client, m));\n }\n\n /** Edita a mensagem (só mensagens do próprio bot). */\n edit(payload: MessagePayloadLike, options?: { signal?: AbortSignal }): Promise<Message> {\n return this.client.messages\n .edit(this.channelId, this.id, payload, options)\n .then((m) => new Message(this.client, m));\n }\n\n /** Apaga a mensagem (a do bot sempre; de outros, com `MANAGE_MESSAGES`). */\n delete(options?: { signal?: AbortSignal }): Promise<void> {\n return this.client.messages.delete(this.channelId, this.id, options);\n }\n\n /** Reage com um emoji Unicode ou `<:nome:id>`. */\n react(emoji: string, options?: { signal?: AbortSignal }): Promise<void> {\n return this.client.messages.react(this.channelId, this.id, emoji, options);\n }\n\n /** Remove a reação do bot. */\n removeReaction(emoji: string, options?: { signal?: AbortSignal }): Promise<void> {\n return this.client.messages.removeReaction(this.channelId, this.id, emoji, options);\n }\n\n /** Fixa a mensagem no canal (`PIN_MESSAGES`). */\n pin(options?: { signal?: AbortSignal }): Promise<void> {\n return this.client.messages.pin(this.channelId, this.id, options);\n }\n\n /** Desafixa a mensagem. */\n unpin(options?: { signal?: AbortSignal }): Promise<void> {\n return this.client.messages.unpin(this.channelId, this.id, options);\n }\n\n /** Cria uma thread a partir desta mensagem (canais de texto e anúncios). */\n startThread(body: { name: string; autoArchiveMinutes?: ThreadAutoArchiveMinutes }): Promise<Thread> {\n return this.client.channels\n .createThreadFromMessage(this.channelId, this.id, body)\n .then((t) => new Thread(this.client, t));\n }\n}\n","/**\n * Estruturas de canal e thread.\n *\n * Uma thread também é canal: use o `id` dela como `channelId` nas rotas\n * de mensagem. Threads não têm overwrites: vale o canal pai.\n */\n\nimport type {\n APIChannel,\n APIThread,\n ChannelType,\n Snowflake,\n ThreadAutoArchiveMinutes,\n} from \"../types/api\";\nimport type { ISODate } from \"../types/common\";\nimport type { MessagePayloadLike } from \"../builders/message\";\nimport { Structure } from \"./base\";\nimport type { ClientLike } from \"./base\";\nimport { Message } from \"./Message\";\nimport type { APIMessage } from \"../types/api\";\nimport type { APIThreadCreateBody } from \"../types/api\";\n\n/** Um canal de texto, anúncios, categoria, fórum, voz ou palco. */\nexport class Channel extends Structure {\n constructor(client: ClientLike, raw: APIChannel) {\n super(client, raw as unknown as Record<string, unknown>);\n }\n\n get data(): APIChannel {\n return this.raw as unknown as APIChannel;\n }\n\n get id(): Snowflake {\n return this.data.id;\n }\n get guildId(): Snowflake {\n return this.data.guildId;\n }\n get name(): string {\n return this.data.name;\n }\n get type(): ChannelType {\n return this.data.type;\n }\n get topic(): string | null {\n return this.data.topic;\n }\n get categoryId(): Snowflake | null {\n return this.data.categoryId;\n }\n get isPrivate(): boolean {\n return this.data.isPrivate;\n }\n /** Modo lento em segundos (0 desligado). */\n get rateLimitPerUser(): number {\n return this.data.rateLimitPerUser;\n }\n get chatEnabled(): boolean {\n return this.data.chatEnabled;\n }\n get lastMessageId(): Snowflake | null {\n return this.data.lastMessageId;\n }\n /** Menção `<#id>`. */\n get mention(): string {\n return `<#${this.id}>`;\n }\n\n get isText(): boolean {\n return this.data.type === \"TEXT\" || this.data.type === \"ANNOUNCEMENT\";\n }\n get isVoice(): boolean {\n return this.data.type === \"VOICE\" || this.data.type === \"STAGE\";\n }\n get isForum(): boolean {\n return this.data.type === \"FORUM\";\n }\n\n /** Recarrega o canal. */\n fetch(): Promise<Channel> {\n return this.client.channels\n .fetch(this.id)\n .then((c) => new Channel(this.client, c));\n }\n\n /** Envia uma mensagem no canal (idempotente por `nonce`). */\n send(payload: MessagePayloadLike, options?: { signal?: AbortSignal; nonce?: string }): Promise<Message> {\n return this.client.messages\n .send(this.id, payload, options)\n .then((m) => new Message(this.client, m));\n }\n\n /** Envia um arquivo como anexo do canal (fluxo completo de upload). */\n sendFile(\n options: { path?: string; data?: Buffer | Uint8Array; filename?: string; contentType?: string },\n content?: string,\n ): Promise<Message> {\n return this.client.uploads\n .uploadForAttachment({ guildId: this.guildId, ...options })\n .then((attachmentId) =>\n this.send({\n content: content || undefined,\n attachmentIds: [attachmentId],\n }),\n );\n }\n\n /** Busca uma mensagem do canal pelo id. */\n fetchMessage(messageId: Snowflake): Promise<Message> {\n return this.client.messages\n .fetch(this.id, messageId)\n .then((m) => new Message(this.client, m));\n }\n\n /** Lista uma página do histórico (use `client.paginate` para iterar tudo). */\n fetchMessages(params?: { limit?: number; before?: string; after?: string }): Promise<{ items: Message[]; hasMore: boolean; prevCursor: string | null; nextCursor: string | null }> {\n return this.client.messages\n .list(this.id, params ?? {})\n .then((page) => ({\n ...page,\n items: page.items.map((m) => new Message(this.client, m)),\n }));\n }\n\n /** Mensagens fixadas do canal. */\n fetchPins(): Promise<Message[]> {\n return this.client.messages\n .listPins(this.id)\n .then((msgs) => msgs.map((m) => new Message(this.client, m)));\n }\n\n /** Cria uma thread neste canal (texto/anúncios) ou um post (fórum). */\n createThread(body: APIThreadCreateBody): Promise<Thread> {\n return this.client.channels\n .createThread(this.id, body)\n .then((t) => new Thread(this.client, t));\n }\n\n /** Lista as threads do canal (`cursor` = `nextCursor` da página anterior). */\n fetchThreads(params?: { limit?: number; cursor?: string; archived?: \"true\" | \"false\"; tagId?: Snowflake }): Promise<{ items: Thread[]; hasMore: boolean; nextCursor: string | null }> {\n return this.client.channels\n .listThreads(this.id, { limit: params?.limit, after: params?.cursor, archived: params?.archived, tagId: params?.tagId })\n .then((page) => ({\n ...page,\n items: page.items.map((t) => new Thread(this.client, t)),\n }));\n }\n}\n\n/** Uma thread ou post de fórum. */\nexport class Thread extends Structure {\n constructor(client: ClientLike, raw: APIThread) {\n super(client, raw as unknown as Record<string, unknown>);\n }\n\n get data(): APIThread {\n return this.raw as unknown as APIThread;\n }\n\n get id(): Snowflake {\n return this.data.id;\n }\n get guildId(): Snowflake {\n return this.data.guildId;\n }\n get parentId(): Snowflake {\n return this.data.parentId;\n }\n get name(): string {\n return this.data.name;\n }\n get ownerId(): Snowflake {\n return this.data.ownerId;\n }\n get isForumPost(): boolean {\n return this.data.isForumPost;\n }\n get archived(): boolean {\n return this.data.archived;\n }\n get locked(): boolean {\n return this.data.locked;\n }\n get autoArchiveMinutes(): ThreadAutoArchiveMinutes {\n return this.data.autoArchiveMinutes;\n }\n get messageCount(): number {\n return this.data.messageCount;\n }\n get lastMessageId(): Snowflake | null {\n return this.data.lastMessageId;\n }\n get lastMessageAt(): ISODate {\n return this.data.lastMessageAt;\n }\n get appliedTagIds(): Snowflake[] {\n return this.data.appliedTagIds;\n }\n get mention(): string {\n return `<#${this.id}>`;\n }\n\n /** Envia uma mensagem na thread (usa o id dela como channelId). */\n send(payload: MessagePayloadLike, options?: { signal?: AbortSignal; nonce?: string }): Promise<Message> {\n return this.client.messages\n .send(this.id, payload, options)\n .then((m) => new Message(this.client, m));\n }\n\n /** Busca uma mensagem da thread. */\n fetchMessage(messageId: Snowflake): Promise<Message> {\n return this.client.messages\n .fetch(this.id, messageId)\n .then((m: APIMessage) => new Message(this.client, m));\n }\n}\n","/**\n * Estrutura de interação: um comando de barra usado ou um clique em\n * componente de mensagem do bot.\n *\n * O bot responde em até ~10 segundos (o app avisa \"não respondeu\" depois\n * disso); use `defer()` e follow-ups para trabalho demorado. A janela total\n * de resposta é de 15 minutos, e o limite é de 5 respostas a cada 5 segundos\n * por interação.\n */\n\nimport type {\n APIInteraction,\n APIInteractionCommandData,\n APIInteractionComponentData,\n CommandOptionType,\n Snowflake,\n} from \"../types/api\";\nimport type { MessagePayloadLike } from \"../builders/message\";\nimport { Structure } from \"./base\";\nimport type { ClientLike } from \"./base\";\nimport { Member, User } from \"./User\";\nimport { Message } from \"./Message\";\n\nexport class Interaction extends Structure {\n constructor(client: ClientLike, raw: APIInteraction) {\n super(client, raw as unknown as Record<string, unknown>);\n }\n\n get data(): APIInteraction {\n return this.raw as unknown as APIInteraction;\n }\n\n get id(): string {\n return this.data.id;\n }\n /** Credencial da interação (15 minutos de validade). Trate como segredo. */\n get token(): string {\n return this.data.token;\n }\n get type(): \"COMMAND\" | \"COMPONENT\" {\n return this.data.type;\n }\n get guildId(): Snowflake {\n return this.data.guildId;\n }\n get channelId(): Snowflake {\n return this.data.channelId;\n }\n /** Quem invocou o comando ou clicou no componente. */\n get user(): User {\n return new User(this.client, this.data.user);\n }\n\n /** O membro que invocou (com cargos do Space), quando disponível. */\n get member(): Member | null {\n return this.data.member ? new Member(this.client, this.data.member) : null;\n }\n\n get createdAt(): string {\n return this.data.createdAt;\n }\n\n get isCommand(): boolean {\n return this.data.type === \"COMMAND\" && this.data.command !== undefined;\n }\n get isComponent(): boolean {\n return this.data.type === \"COMPONENT\" && this.data.component !== undefined;\n }\n\n /** Dados do comando (presentes quando `isCommand`). */\n get command(): APIInteractionCommandData | null {\n return this.data.command ?? null;\n }\n\n /** Dados do componente (presentes quando `isComponent`). */\n get component(): APIInteractionComponentData | null {\n return this.data.component ?? null;\n }\n\n /** O `customId` do componente clicado (ou `null`). */\n get customId(): string | null {\n return this.component?.customId ?? null;\n }\n\n /** Os valores escolhidos em um menu (vazio em botões). */\n get values(): string[] {\n return this.component?.values ?? [];\n }\n\n // ------------------------------------------------------------------\n // Acesso às opções do comando\n // ------------------------------------------------------------------\n\n /** Lista as opções preenchidas da invocação (já validadas pelo Squord). */\n get options(): Array<{ name: string; type: CommandOptionType; value: string | number | boolean }> {\n return this.command?.options ?? [];\n }\n\n /** Valor bruto de uma opção pelo nome. */\n getOption(name: string): string | number | boolean | undefined {\n return this.options.find((option) => option.name === name)?.value;\n }\n\n /** Opção `STRING`. */\n getString(name: string, required = false): string | undefined {\n const value = this.getOption(name);\n if (typeof value === \"string\") return value;\n if (required) throw new Error(`A opção obrigatória \"${name}\" não veio como STRING`);\n return undefined;\n }\n\n /** Opção `INTEGER`. */\n getInteger(name: string, required = false): number | undefined {\n const value = this.getOption(name);\n if (typeof value === \"number\") return value;\n if (required) throw new Error(`A opção obrigatória \"${name}\" não veio como INTEGER`);\n return undefined;\n }\n\n /** Opção `BOOLEAN`. */\n getBoolean(name: string, required = false): boolean | undefined {\n const value = this.getOption(name);\n if (typeof value === \"boolean\") return value;\n if (required) throw new Error(`A opção obrigatória \"${name}\" não veio como BOOLEAN`);\n return undefined;\n }\n\n /** Opção `USER`/`CHANNEL`/`ROLE`: o valor é o id (string). */\n getId(name: string, required = false): Snowflake | undefined {\n const value = this.getOption(name);\n if (typeof value === \"string\") return value;\n if (required) throw new Error(`A opção obrigatória \"${name}\" não veio como USER/CHANNEL/ROLE`);\n return undefined;\n }\n\n // ------------------------------------------------------------------\n // Respostas\n // ------------------------------------------------------------------\n\n /** Primeira resposta como mensagem. `ephemeral: true` mostra só para quem invocou. */\n reply(\n payload: MessagePayloadLike,\n options: { ephemeral?: boolean; signal?: AbortSignal } = {},\n ): Promise<void> {\n return this.client.interactions.reply(this.id, this.token, payload, options);\n }\n\n /** Resposta efêmera: só quem invocou vê; não é salva; só botões de link. */\n replyEphemeral(payload: MessagePayloadLike, options?: { signal?: AbortSignal }): Promise<void> {\n return this.client.interactions.reply(this.id, this.token, payload, {\n ...options,\n ephemeral: true,\n });\n }\n\n /** `DEFERRED`: mostra o bot \"pensando\" enquanto o trabalho roda. */\n defer(options?: { signal?: AbortSignal }): Promise<void> {\n return this.client.interactions.defer(this.id, this.token, options);\n }\n\n /**\n * `UPDATE` (só componente): edita a mensagem que tinha o componente.\n * O caso típico: marcar a escolha, mudar de página.\n */\n update(payload: MessagePayloadLike, options?: { signal?: AbortSignal }): Promise<void> {\n return this.client.interactions.update(this.id, this.token, payload, options);\n }\n\n /** `DEFERRED_UPDATE` (só componente): confirma o clique sem mudar nada. */\n acknowledge(options?: { signal?: AbortSignal }): Promise<void> {\n return this.client.interactions.acknowledgeComponent(this.id, this.token, options);\n }\n\n /**\n * Follow-up: mensagem extra depois da primeira resposta\n * (o padrão para trabalho demorado é `defer()` + follow-up).\n */\n followup(\n payload: MessagePayloadLike,\n options: { ephemeral?: boolean; signal?: AbortSignal } = {},\n ): Promise<void> {\n const source = typeof payload === \"string\" ? { content: payload } : payload;\n if (options.ephemeral) (source as { ephemeral?: boolean }).ephemeral = true;\n return this.client.interactions.followup(\n this.id,\n this.token,\n source as never,\n options.signal,\n );\n }\n\n /** Busca a mensagem do componente clicado (quando `isComponent`). */\n fetchComponentMessage(): Promise<Message | null> {\n const messageId = this.component?.messageId;\n if (!messageId) return Promise.resolve(null);\n return this.client.messages\n .fetch(this.channelId, messageId)\n .then((m) => new Message(this.client, m))\n .catch(() => null);\n }\n}\n","/**\n * Validação e manipulação de ids do Squord.\n *\n * Ids são strings opacas: Snowflakes decimais de até 20 dígitos, ou o formato\n * antigo de 24 caracteres hexadecimais. Nunca converta para `number`.\n */\n\nimport { SquordTypeError } from \"../errors\";\n\nconst SNOWFLAKE_RE = /^\\d{1,20}$/;\nconst LEGACY_ID_RE = /^[0-9a-f]{24}$/i;\n\n/** Verifica se um valor parece um id válido do Squord. */\nexport function isValidSnowflake(id: string): boolean {\n return typeof id === \"string\" && (SNOWFLAKE_RE.test(id) || LEGACY_ID_RE.test(id));\n}\n\n/** Lança `SquordTypeError` se o id não tiver o formato de id do Squord. */\nexport function assertSnowflake(id: string, label = \"id\"): string {\n if (!isValidSnowflake(id)) {\n throw new SquordTypeError(\n `${label} inválido: ${JSON.stringify(id)} — ids do Squord são strings (Snowflake decimal ou hex de 24 caracteres)`,\n );\n }\n return id;\n}\n\n/** Compara dois ids por ordem numérica (seguro com ids grandes, via BigInt). */\nexport function compareSnowflakes(a: string, b: string): number {\n if (!SNOWFLAKE_RE.test(a) || !SNOWFLAKE_RE.test(b)) {\n return a < b ? -1 : a > b ? 1 : 0;\n }\n try {\n const ba = BigInt(a);\n const bb = BigInt(b);\n return ba < bb ? -1 : ba > bb ? 1 : 0;\n } catch {\n return a.localeCompare(b);\n }\n}\n","/**\n * Cache em memória opcional: TTL por item, limite de itens e invalidação.\n *\n * O padrão do SDK é armazenar apenas o necessário, com acesso sob demanda\n * aos demais dados. O cache **nunca** substitui a API: um item pode estar\n * defasado, e o backend continua sendo a autoridade.\n */\n\nexport interface CacheOptions {\n /** Tempo de vida por item, em milissegundos. Padrão: 300000 (5 min). */\n ttlMs?: number;\n /** Máximo de itens guardados; os mais antigos são descartados. Padrão: 1000. */\n maxSize?: number;\n /** Função de agora, injetável para testes. */\n now?: () => number;\n}\n\ninterface Entry<V> {\n value: V;\n expiresAt: number;\n insertedAt: number;\n}\n\nexport class Cache<K, V> {\n private readonly store = new Map<K, Entry<V>>();\n private readonly ttlMs: number;\n private readonly maxSize: number;\n private readonly now: () => number;\n\n constructor(options: CacheOptions = {}) {\n this.ttlMs = options.ttlMs ?? 300_000;\n this.maxSize = options.maxSize ?? 1_000;\n this.now = options.now ?? (() => Date.now());\n }\n\n get(key: K): V | undefined {\n const entry = this.store.get(key);\n if (!entry) return undefined;\n if (this.now() >= entry.expiresAt) {\n this.store.delete(key);\n return undefined;\n }\n // Map preserva ordem de inserção: re-inserir promove o item a \"mais recente\".\n this.store.delete(key);\n this.store.set(key, entry);\n return entry.value;\n }\n\n set(key: K, value: V, ttlMs?: number): void {\n if (this.maxSize <= 0) return;\n const ttl = ttlMs ?? this.ttlMs;\n this.store.delete(key);\n this.store.set(key, { value, expiresAt: ttl === Infinity ? Number.MAX_SAFE_INTEGER : this.now() + ttl, insertedAt: this.now() });\n this.evictIfNeeded();\n }\n\n has(key: K): boolean {\n return this.get(key) !== undefined || this.peek(key) !== undefined;\n }\n\n delete(key: K): boolean {\n return this.store.delete(key);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n get size(): number {\n this.sweep();\n return this.store.size;\n }\n\n /** Itera itens vivos. */\n *entries(): IterableIterator<[K, V]> {\n for (const [key, entry] of [...this.store.entries()]) {\n if (this.now() < entry.expiresAt) yield [key, entry.value];\n else this.store.delete(key);\n }\n }\n\n private peek(key: K): V | undefined {\n return this.store.get(key)?.value;\n }\n\n private evictIfNeeded(): void {\n if (this.store.size <= this.maxSize) return;\n // Descarta os itens mais antigos (primeiros inseridos ainda vivos).\n const excess = this.store.size - this.maxSize;\n const iterator = this.store.keys();\n for (let i = 0; i < excess; i++) {\n const oldest = iterator.next();\n if (oldest.done) break;\n this.store.delete(oldest.value);\n }\n }\n\n private sweep(): void {\n const now = this.now();\n for (const [key, entry] of this.store.entries()) {\n if (now >= entry.expiresAt) this.store.delete(key);\n }\n }\n}\n","/**\n * `SquordClient`: o ponto central do SDK.\n *\n * Valida o token contra a API (`GET /bots/@me`), conecta ao gateway, entrega\n * eventos tipados e expõe os managers REST. O ciclo de vida completo —\n * reconexão, heartbeat, resume e deduplicação — fica a cargo do SDK.\n */\n\nimport { TypedEmitter } from \"../utils/TypedEmitter\";\nimport type { ClientEvents } from \"./events\";\nimport { ApplicationCommandsManager } from \"../managers/appCommands\";\nimport { BotManager, UsersManager } from \"../managers/bots\";\nimport { ChannelsManager } from \"../managers/channels\";\nimport { InteractionsManager } from \"../managers/interactions\";\nimport {\n GuildsManager,\n MembersManager,\n ModerationManager,\n RolesManager,\n} from \"../managers/members\";\nimport { MessagesManager } from \"../managers/messages\";\nimport { UploadsManager } from \"../managers/uploads\";\nimport { RestClient } from \"../rest/RestClient\";\nimport { Gateway } from \"../gateway/Gateway\";\nimport type { WebSocketFactory } from \"../gateway/WebSocketLike\";\nimport type { Logger } from \"../logger\";\nimport { createConsoleLogger, loggerFromEnv, noopLogger } from \"../logger\";\nimport { Channel, Thread } from \"../structures/Channel\";\nimport { Guild, Member, Role, User } from \"../structures/User\";\nimport { Message } from \"../structures/Message\";\nimport { Interaction } from \"../structures/Interaction\";\nimport { SquordTypeError } from \"../errors\";\nimport { assertSnowflake } from \"../utils/snowflake\";\nimport { isBotToken, stripTokenPrefix } from \"../utils/misc\";\nimport type {\n APIBot,\n APIChannel,\n APIGuild,\n APIMember,\n APIMessage,\n APIRole,\n APIThread,\n} from \"../types/api\";\nimport type { Snowflake } from \"../types/common\";\nimport type { GatewayPresenceUpdate, PresenceStatus, ServerFrame } from \"../types/gateway\";\nimport { resolveChannelPermissions, Permissions } from \"../permissions\";\nimport { Cache } from \"../cache/Cache\";\n\nexport interface ClientOptions {\n /** Token do bot (`sqb_<id>.<segredo>`), de preferência vindo do ambiente. */\n token: string;\n /** URL base da API REST. Padrão: `https://api.squord.com.br/api/v1`. */\n apiBaseURL?: string;\n /** URL do gateway. Padrão: `wss://gateway.squord.com.br/gateway`. */\n gatewayURL?: string;\n /** Timeout por requisição REST, em ms. Padrão: 15000. */\n restTimeoutMs?: number;\n /** Base do backoff de reconexão do gateway, em ms. Padrão: 1000. */\n gatewayReconnectBaseMs?: number;\n /** Retentativas REST para falhas transitórias. Padrão: 3. */\n restMaxRetries?: number;\n /** Teto global de requisições/segundo (o oficial é 50). Padrão: 45. */\n restGlobalPerSecond?: number;\n /** Implementação de fetch para testes. Padrão: `fetch` global. */\n fetchImpl?: typeof fetch;\n /** Fábrica de WebSocket para testes. Padrão: `WebSocket` global (Node 22+). */\n ws?: WebSocketFactory;\n /**\n * `true` para usar apenas o cliente REST (tarefas agendadas, CI), sem\n * gateway. Use `login()` normalmente; ele só valida o token.\n */\n restOnly?: boolean;\n /** `true` para encerrar com SIGINT/SIGTERM automaticamente. Padrão: `false`. */\n gracefulShutdown?: boolean;\n /** Logger do SDK (`debug`, `info`, `warn`, `error`); `null` silencia. */\n logger?: Logger | null;\n /** Nível do logger automático (ignorado se `logger` for informado). */\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\n /**\n * Cache em memória opcional (TTL e limite configuráveis). Desativado por\n * padrão: o cliente busca os dados sob demanda.\n */\n cache?: {\n enabled: boolean;\n /** TTL por item, em ms. Padrão: 300000 (5 min). */\n ttlMs?: number;\n /** Máximo de itens por cache. Padrão: 500. */\n maxEntries?: number;\n };\n}\n\nexport class SquordClient extends TypedEmitter<ClientEvents> {\n readonly rest: RestClient;\n readonly messages: MessagesManager;\n readonly channels: ChannelsManager;\n readonly guilds: GuildsManager;\n readonly members: MembersManager;\n readonly roles: RolesManager;\n readonly moderation: ModerationManager;\n readonly uploads: UploadsManager;\n readonly interactions: InteractionsManager;\n readonly commands: ApplicationCommandsManager;\n readonly bot: BotManager;\n readonly users: UsersManager;\n readonly logger: Logger;\n\n /** Caches opcionais, desativados por padrão (`cache.enabled`). */\n readonly caches: {\n guilds: Cache<Snowflake, APIGuild>;\n channels: Cache<Snowflake, APIChannel>;\n members: Cache<string, APIMember>;\n roles: Cache<Snowflake, APIRole[]>;\n } | null;\n\n private readonly options: ClientOptions;\n private gatewayInstance: Gateway | null = null;\n private botInfo: APIBot | null = null;\n private userIdValue: Snowflake | null = null;\n private shutdownSignalsBound = false;\n private destroyed = false;\n\n constructor(options: ClientOptions) {\n super();\n if (!options?.token || typeof options.token !== \"string\") {\n throw new SquordTypeError(\"Informe o token do bot: new SquordClient({ token: process.env.SQUORD_BOT_TOKEN })\");\n }\n const token = stripTokenPrefix(options.token);\n if (!isBotToken(token)) {\n throw new SquordTypeError(\n \"O token do bot deve começar com sqb_ (formato sqb_<id>.<segredo>), obtido em Configurações → Desenvolvedor\",\n );\n }\n this.options = { ...options, token };\n\n this.logger =\n options.logger !== undefined && options.logger !== null\n ? options.logger\n : options.logger === null\n ? noopLogger\n : options.logLevel\n ? createConsoleLogger({ level: options.logLevel })\n : loggerFromEnv();\n\n this.rest = new RestClient({\n baseURL: options.apiBaseURL,\n token,\n timeoutMs: options.restTimeoutMs,\n maxRetries: options.restMaxRetries,\n globalRequestsPerSecond: options.restGlobalPerSecond,\n fetchImpl: options.fetchImpl,\n logger: this.logger,\n });\n\n this.messages = new MessagesManager(this.rest);\n this.channels = new ChannelsManager(this.rest);\n this.guilds = new GuildsManager(this.rest);\n this.members = new MembersManager(this.rest);\n this.roles = new RolesManager(this.rest);\n this.moderation = new ModerationManager(this.rest);\n this.uploads = new UploadsManager(this.rest, this.logger);\n this.interactions = new InteractionsManager(this.rest);\n this.commands = new ApplicationCommandsManager(this.rest);\n this.bot = new BotManager(this.rest);\n this.users = new UsersManager(this.rest);\n\n const cacheOptions = options.cache?.enabled\n ? { ttlMs: options.cache.ttlMs, maxSize: options.cache.maxEntries }\n : null;\n this.caches = cacheOptions\n ? {\n guilds: new Cache<Snowflake, APIGuild>(cacheOptions),\n channels: new Cache<Snowflake, APIChannel>(cacheOptions),\n members: new Cache<string, APIMember>(cacheOptions),\n roles: new Cache<Snowflake, APIRole[]>(cacheOptions),\n }\n : null;\n }\n\n /** Opções com que o cliente foi criado (sem o token). */\n get optionsSafe(): Omit<ClientOptions, \"token\"> {\n const { token: _token, ...rest } = this.options;\n return rest;\n }\n\n /** Id da conta do bot (disponível após `login()`). */\n get userId(): Snowflake | null {\n return this.userIdValue;\n }\n\n /** A conta do bot como `User` (após `login()`). */\n get user(): User | null {\n return this.botInfo ? new User(this, this.botInfo.user) : null;\n }\n\n /** O bot na visão do dono (após `login()`). */\n get application(): APIBot | null {\n return this.botInfo;\n }\n\n /** O gateway, se conectado (ou em conexão). */\n get gateway(): Gateway | null {\n return this.gatewayInstance;\n }\n\n /** `true` quando o gateway está autenticado e recebendo eventos. */\n isReady(): boolean {\n return this.gatewayInstance?.isReady ?? false;\n }\n\n /** Latência do gateway (último heartbeat → ack), em ms. */\n get ping(): number | null {\n return this.gatewayInstance?.heartbeatLatencyMs ?? null;\n }\n\n /**\n * Autentica e conecta. Valida o token (`GET /bots/@me`), conecta ao\n * gateway (a menos que `restOnly`) e resolve no `ready`.\n */\n async login(): Promise<void> {\n if (this.destroyed) throw new SquordTypeError(\"O cliente foi destruído\");\n if (this.userIdValue) return; // já logado\n\n this.logger.info(\"validando token do bot\");\n this.botInfo = await this.bot.fetchCurrent();\n this.userIdValue = this.botInfo.user.id;\n this.logger.info(\"token validado\", { botId: this.botInfo.id, username: this.botInfo.user.username });\n\n if (this.options.restOnly) {\n this.logger.info(\"modo REST-only: sem gateway\");\n this.emit(\"ready\", {\n user: new User(this, this.botInfo.user),\n sessionId: \"\",\n guilds: [],\n ping: null,\n });\n return;\n }\n\n if (this.options.gracefulShutdown && !this.shutdownSignalsBound) {\n this.shutdownSignalsBound = true;\n const shutdown = () => {\n void this.destroy().then(() => process.exit(0));\n };\n process.once(\"SIGINT\", shutdown);\n process.once(\"SIGTERM\", shutdown);\n }\n\n const gateway = this.ensureGateway();\n const ready = await gateway.connect();\n\n this.userIdValue = ready.userId || this.userIdValue;\n this.emit(\"ready\", {\n user: this.user ?? new User(this, this.botInfo!.user),\n sessionId: ready.sessionId,\n guilds: ready.guilds,\n ping: this.ping,\n });\n }\n\n /**\n * Encerra o cliente: fecha o gateway, cancela requisições pendentes e\n * remove listeners. Seguro chamar mais de uma vez.\n */\n async destroy(): Promise<void> {\n if (this.destroyed) return;\n this.destroyed = true;\n if (this.gatewayInstance) {\n await this.gatewayInstance.destroy();\n this.gatewayInstance = null;\n }\n this.rest.destroy();\n this.removeAllListeners();\n }\n\n /** Presença do bot: `ONLINE`, `IDLE`, `DND` ou `INVISIBLE`, com status personalizado. */\n setPresence(presence: { status?: PresenceStatus; customStatus?: string | null; afk?: boolean }): void {\n if (!this.gatewayInstance) {\n throw new SquordTypeError(\"Conecte o gateway antes de mudar a presença (login())\");\n }\n const update: GatewayPresenceUpdate = {\n status: presence.status,\n customStatus: presence.customStatus === undefined ? undefined : presence.customStatus,\n afk: presence.afk,\n };\n this.gatewayInstance.setPresence(update);\n }\n\n /** Força reconexão do gateway (tenta `resume`). */\n reconnect(): void {\n this.gatewayInstance?.reconnectNow();\n }\n\n /**\n * Permissões efetivas do bot em um canal, resolvidas localmente a partir\n * dos cargos e overwrites (com o cache, quando habilitado). O backend\n * continua sendo a autoridade final.\n */\n async myPermissionsIn(channelId: Snowflake): Promise<bigint> {\n assertSnowflake(channelId, \"channelId\");\n const channel = this.caches?.channels.get(channelId) ?? (await this.channels.fetch(channelId));\n this.caches?.channels.set(channelId, channel);\n const guildId = channel.guildId;\n const guild = this.caches?.guilds.get(guildId) ?? (await this.guilds.fetch(guildId));\n this.caches?.guilds.set(guildId, guild);\n\n const roles = this.caches?.roles.get(guildId) ?? (await this.roles.list(guildId));\n this.caches?.roles.set(guildId, roles);\n\n const memberKey = `${guildId}:${this.userIdValue}`;\n const me =\n this.caches?.members.get(memberKey) ??\n (await this.members.fetch(guildId, this.userIdValue!));\n this.caches?.members.set(memberKey, me);\n\n const roleById = new Map(roles.map((role) => [role.id, role]));\n const everyonePermissions = BigInt(\n (roleById.get(guildId) ?? roles.find((r) => r.id === guildId))?.permissions ?? \"0\",\n );\n return resolveChannelPermissions({\n everyonePermissions,\n rolePermissions: me.roleIds\n .map((roleId) => roleById.get(roleId))\n .filter((role): role is APIRole => role !== undefined)\n .map((role) => BigInt(role.permissions)),\n overwrites: channel.overwrites,\n memberId: me.id,\n everyoneRoleId: guildId,\n memberRoleIds: me.roleIds,\n });\n }\n\n /** Testa se o bot tem um conjunto de permissões em um canal. */\n async hasPermissionsIn(channelId: Snowflake, ...flags: bigint[]): Promise<boolean> {\n const bits = await this.myPermissionsIn(channelId);\n return flags.every((flag) => (bits & flag) === flag);\n }\n\n /** Atalho para `Permissions` (evita import extra em código de bot). */\n get Permissions(): typeof Permissions {\n return Permissions;\n }\n\n // ------------------------------------------------------------------\n\n private ensureGateway(): Gateway {\n if (this.gatewayInstance) return this.gatewayInstance;\n\n const gateway = new Gateway({\n url: this.options.gatewayURL,\n token: this.options.token,\n ws: this.options.ws,\n logger: this.logger,\n reconnectBaseMs: this.options.gatewayReconnectBaseMs,\n });\n\n gateway.on(\"resumed\", (resumed) => {\n this.emit(\"resumed\", resumed);\n this.logger.info(\"sessão retomada\", { replayed: resumed.replayed });\n });\n\n gateway.on(\"reconnecting\", (info) => {\n this.emit(\"reconnecting\", info);\n this.logger.warn(\"reconectando ao gateway\", info);\n });\n\n gateway.on(\"disconnect\", (info) => {\n this.emit(\"disconnect\", info);\n if (!info.fatal) this.emit(\"warn\", `Conexão do gateway caiu (código ${info.code})`);\n });\n\n gateway.on(\"error\", (error) => {\n this.emit(\"error\", error);\n });\n\n gateway.on(\"invalidSession\", () => {\n this.emit(\"warn\", \"Sessão do gateway não pôde ser retomada; refazendo identify\");\n });\n\n gateway.on(\"raw\", (frame: ServerFrame) => {\n this.emit(\"raw\", frame);\n });\n\n gateway.on(\"event\", (event) => {\n this.dispatchGatewayEvent(event);\n });\n\n this.gatewayInstance = gateway;\n return gateway;\n }\n\n private dispatchGatewayEvent(event: {\n type: string;\n d: unknown;\n s?: number;\n timestamp: number;\n }): void {\n const { type, d } = event;\n const data = d as Record<string, unknown>;\n\n try {\n switch (type) {\n case \"message.created\":\n case \"message.updated\":\n this.emit(type, new Message(this, data.message as APIMessage));\n break;\n case \"member.joined\":\n case \"member.updated\":\n this.emit(type, {\n guildId: data.guildId as Snowflake,\n member: new Member(this, data.member as APIMember),\n });\n break;\n case \"guild.updated\":\n this.emit(type, new Guild(this, data.guild as APIGuild));\n break;\n case \"channel.created\":\n case \"channel.updated\":\n this.emit(type, new Channel(this, data.channel as APIChannel));\n break;\n case \"role.created\":\n case \"role.updated\":\n this.emit(type, new Role(this, data.role as APIRole));\n break;\n case \"thread.created\":\n case \"thread.updated\":\n this.emit(type, new Thread(this, data.thread as APIThread));\n break;\n case \"interaction.created\":\n this.emit(type, new Interaction(this, d as never));\n break;\n default:\n if (this.listenerCount(type as keyof ClientEvents) > 0) {\n // Evento com listener registrado: entrega o payload cru.\n this.emit(type as keyof ClientEvents, d);\n } else if (isKnownEventType(type)) {\n this.emit(type as keyof ClientEvents, d);\n } else {\n this.emit(\"unknownEvent\", event);\n }\n }\n } catch (err) {\n this.emit(\"error\", err instanceof Error ? err : new Error(String(err)));\n }\n }\n}\n\nconst KNOWN_EVENT_TYPES = new Set<string>([\n \"message.deleted\",\n \"message.bulk_deleted\",\n \"poll.vote.cast\",\n \"poll.vote.removed\",\n \"reaction.added\",\n \"reaction.removed\",\n \"member.left\",\n \"member.banned\",\n \"member.unbanned\",\n \"guild.deleted\",\n \"guild.taken_down\",\n \"guild.boost.added\",\n \"guild.boost.removed\",\n \"channel.deleted\",\n \"channel.tree.invalidated\",\n \"role.deleted\",\n \"thread.deleted\",\n \"emoji.created\",\n \"emoji.updated\",\n \"emoji.deleted\",\n \"sticker.created\",\n \"sticker.updated\",\n \"sticker.deleted\",\n \"guild_event.created\",\n \"guild_event.updated\",\n \"guild_event.deleted\",\n \"announcement.follow.created\",\n \"announcement.follow.deleted\",\n \"voice.state.updated\",\n \"voice.room.updated\",\n \"voice.member.moved\",\n \"voice.e2ee.bot_key_requested\",\n \"application_command.updated\",\n]);\n\nfunction isKnownEventType(type: string): boolean {\n return KNOWN_EVENT_TYPES.has(type);\n}\n","/**\n * Registro de comandos: texto (com prefixo), slash (comandos de aplicação)\n * e componentes (botões e menus).\n *\n * - **Texto**: o SDK ouve `message.created`, faz o parse do prefixo e dos\n * argumentos e chama o handler. Suporta aliases, cooldowns e middleware.\n * - **Slash**: handlers para `interaction.created` de comandos. O registro\n * pode sincronizar as definições com o Squord (`PUT` em bloco) na partida\n * do bot — registrar é sobrescrever, então a lista deve ser a mesma sempre.\n * - **Componentes**: handlers para cliques em botões e escolhas em menus,\n * identificados pelo `customId` (aceito prefixo com `*` no final).\n */\n\nimport { SquordTypeError } from \"../errors\";\nimport type { SquordClient } from \"../client/SquordClient\";\nimport type { Interaction } from \"../structures/Interaction\";\nimport type { Message } from \"../structures/Message\";\nimport type { APICommandInput, APICommandOptionInput, Snowflake } from \"../types/api\";\nimport { splitArguments } from \"../utils/misc\";\n\n// ---------------------------------------------------------------------\n// Comandos de texto\n// ---------------------------------------------------------------------\n\nexport interface TextCommandDefinition {\n /** Nome principal (sem o prefixo). Letras minúsculas recomendadas. */\n name: string;\n /** Nomes alternativos. */\n aliases?: string[];\n /** Descrição usada em mensagens de erro e ajuda. */\n description?: string;\n /** Deixa o comando oculto em listagens de ajuda. */\n hidden?: boolean;\n /** Cooldown por usuário, em ms. Padrão: sem cooldown. */\n cooldownMs?: number;\n /** Caso a mensagem deve ignorar bots (padrão `true`). */\n ignoreBots?: boolean;\n /** Onde o comando vale: em qualquer Space ou em Spaces específicos. */\n guildIds?: Snowflake[];\n /** Middleware antes da execução; devolve `false` para abortar. */\n beforeExecute?: (context: TextCommandContext) => boolean | Promise<boolean>;\n execute: (context: TextCommandContext) => unknown | Promise<unknown>;\n}\n\nexport interface TextCommandContext {\n /** O cliente do bot. */\n client: SquordClient;\n /** A mensagem que invocou o comando. */\n message: Message;\n /** Nome invocado (pode ser um alias). */\n name: string;\n /** Definição do comando. */\n command: TextCommandDefinition;\n /** Argumentos crus, já com aspas tratadas. */\n args: string[];\n /** A linha de argumentos como veio (sem o nome do comando). */\n rawArgs: string;\n /** Responde no canal (sem citar). */\n reply(payload: string | Parameters<Message[\"reply\"]>[0]): ReturnType<Message[\"reply\"]>;\n /** Responde citando a mensagem original. */\n replyWithMention(payload: string | Parameters<Message[\"reply\"]>[0]): ReturnType<Message[\"reply\"]>;\n /** Reage à mensagem que invocou. */\n react(emoji: string): Promise<void>;\n}\n\n// ---------------------------------------------------------------------\n// Comandos de aplicação (slash)\n// ---------------------------------------------------------------------\n\nexport interface SlashCommandDefinition {\n /** Letras minúsculas, números, `_` e `-` (até 32 caracteres). */\n name: string;\n /** Até 100 caracteres. */\n description: string;\n /** Até 25 opções; as obrigatórias vêm antes das opcionais. */\n options?: APICommandOptionInput[];\n /** Onde publicar: `\"global\"` (padrão) ou Spaces específicos. */\n scope?: { kind: \"global\" } | { kind: \"guild\"; guildIds: Snowflake[] };\n execute: (interaction: Interaction) => unknown | Promise<unknown>;\n}\n\n// ---------------------------------------------------------------------\n// Componentes\n// ---------------------------------------------------------------------\n\nexport interface ComponentHandlerDefinition {\n /** `customId` do componente. Terminando em `*`, casa por prefixo. */\n customId: string;\n execute: (interaction: Interaction) => unknown | Promise<unknown>;\n}\n\n// ---------------------------------------------------------------------\n// Opções do registro\n// ---------------------------------------------------------------------\n\nexport interface CommandRegistryOptions {\n /** Prefixo dos comandos de texto: string ou função (padrão `\"!\"`). */\n prefix?: string | ((message: Message) => string | null);\n /**\n * Sincronizar os slash commands com o Squord no login (PUT em bloco,\n * sobrescrevendo o que existir). Padrão: `true` quando houver comandos.\n */\n syncOnLogin?: boolean;\n /** Se `true`, ignora mensagens de bots nos comandos de texto (padrão). */\n ignoreBots?: boolean;\n /** Handler para erros dos comandos (texto e slash). */\n onError?: (error: unknown, context: { command?: string; message?: Message; interaction?: Interaction }) => void;\n}\n\nexport class CommandRegistry {\n private readonly textCommands = new Map<string, TextCommandDefinition>();\n private readonly slashCommands = new Map<string, SlashCommandDefinition>();\n private readonly componentHandlers = new Map<string, ComponentHandlerDefinition>();\n private readonly cooldowns = new Map<string, number>();\n private readonly prefixResolver: NonNullable<CommandRegistryOptions[\"prefix\"]>;\n private attached = false;\n\n constructor(\n private readonly client: SquordClient,\n private readonly options: CommandRegistryOptions = {},\n ) {\n this.prefixResolver = options.prefix ?? \"!\";\n }\n\n /** Registra um comando de texto. */\n text(definition: TextCommandDefinition): this {\n validateTextDefinition(definition);\n const names = [definition.name, ...(definition.aliases ?? [])];\n for (const name of names) {\n const key = name.toLowerCase();\n if (this.textCommands.has(key)) {\n throw new SquordTypeError(`Comando de texto duplicado: ${name}`);\n }\n this.textCommands.set(key, definition);\n }\n this.ensureAttached();\n return this;\n }\n\n /** Registra um comando slash. */\n slash(definition: SlashCommandDefinition): this {\n if (!/^[a-z0-9_-]{1,32}$/.test(definition.name)) {\n throw new SquordTypeError(\n `Nome de comando inválido: ${definition.name} (use letras minúsculas, números, _ e -, até 32 caracteres)`,\n );\n }\n if (this.slashCommands.has(definition.name)) {\n throw new SquordTypeError(`Comando slash duplicado: ${definition.name}`);\n }\n this.slashCommands.set(definition.name, definition);\n this.ensureAttached();\n return this;\n }\n\n /** Registra um handler de componente (botão ou menu). */\n component(definition: ComponentHandlerDefinition): this {\n if (!definition.customId) throw new SquordTypeError(\"customId é obrigatório\");\n if (this.componentHandlers.has(definition.customId)) {\n throw new SquordTypeError(`Handler de componente duplicado: ${definition.customId}`);\n }\n this.componentHandlers.set(definition.customId, definition);\n this.ensureAttached();\n return this;\n }\n\n /** Remove um handler de componente. */\n removeComponent(customId: string): this {\n this.componentHandlers.delete(customId);\n return this;\n }\n\n /** Definições slash prontas para o `PUT` em bloco. */\n toCommandsInput(): APICommandInput[] {\n return [...this.slashCommands.values()].map((command) => ({\n name: command.name,\n description: command.description,\n options: command.options ?? [],\n }));\n }\n\n /**\n * Sincroniza os slash commands com o Squord (PUT em bloco, sobrescrevendo\n * o que existir em cada escopo). Chame após `client.login()` — ou deixe o\n * registro fazer automaticamente no `ready` (`syncOnLogin`, o padrão).\n */\n async sync(): Promise<void> {\n const global: APICommandInput[] = [];\n const guildScope = new Map<Snowflake, APICommandInput[]>();\n\n for (const command of this.slashCommands.values()) {\n const input: APICommandInput = {\n name: command.name,\n description: command.description,\n options: command.options ?? [],\n };\n const scope = command.scope ?? { kind: \"global\" as const };\n if (scope.kind === \"global\") {\n global.push(input);\n } else {\n for (const guildId of scope.guildIds) {\n const list = guildScope.get(guildId) ?? [];\n list.push(input);\n guildScope.set(guildId, list);\n }\n }\n }\n\n if (global.length > 0) {\n await this.client.commands.setGlobal(global);\n }\n for (const [guildId, commands] of guildScope) {\n await this.client.commands.setGuild(guildId, commands);\n }\n }\n\n /** Limpa os cooldowns (útil em testes). */\n clearCooldowns(): void {\n this.cooldowns.clear();\n }\n\n /** Processa manualmente uma mensagem como possível comando de texto (para testes). */\n async handleTextMessage(message: Message): Promise<boolean> {\n const prefix = this.resolvePrefix(message);\n if (prefix === null) return false;\n\n const content = message.content;\n if (!content.startsWith(prefix)) return false;\n\n const line = content.slice(prefix.length).trim();\n if (!line) return false;\n\n const spaceIndex = line.search(/\\s/);\n const invokedName = (spaceIndex === -1 ? line : line.slice(0, spaceIndex)).toLowerCase();\n const rawArgs = spaceIndex === -1 ? \"\" : line.slice(spaceIndex).trim();\n\n const definition = this.textCommands.get(invokedName);\n if (!definition) return false;\n\n if (definition.guildIds && !definition.guildIds.includes(message.guildId ?? \"\")) {\n return false;\n }\n if ((definition.ignoreBots ?? this.options.ignoreBots ?? true) && message.author.isBot) {\n return false;\n }\n\n // Cooldown\n if (definition.cooldownMs && definition.cooldownMs > 0) {\n const key = `${message.authorId}:${definition.name}`;\n const until = this.cooldowns.get(key) ?? 0;\n const now = Date.now();\n if (until > now) return false;\n this.cooldowns.set(key, now + definition.cooldownMs);\n }\n\n const args = splitArguments(rawArgs);\n const context: TextCommandContext = {\n client: this.client,\n message,\n name: invokedName,\n command: definition,\n args,\n rawArgs,\n reply: (payload) => message.reply(payload),\n replyWithMention: (payload) => {\n const mention = `<@${message.authorId}>`;\n const body =\n typeof payload === \"string\" ? { content: `${mention} ${payload}` } : { ...payload };\n if (typeof payload !== \"string\" && body.content) {\n body.content = `${mention} ${body.content}`;\n }\n return message.reply(body);\n },\n react: (emoji) => message.react(emoji),\n };\n\n try {\n if (definition.beforeExecute) {\n const allowed = await definition.beforeExecute(context);\n if (allowed === false) return false;\n }\n await definition.execute(context);\n } catch (error) {\n this.reportError(error, { command: definition.name, message });\n }\n return true;\n }\n\n /** Processa manualmente uma interação (para testes). */\n async handleInteraction(interaction: Interaction): Promise<boolean> {\n try {\n if (interaction.isCommand) {\n const definition = this.slashCommands.get(interaction.command?.name ?? \"\");\n if (!definition) return false;\n await definition.execute(interaction);\n return true;\n }\n if (interaction.isComponent) {\n const handler = this.matchComponent(interaction.customId ?? \"\");\n if (!handler) return false;\n await handler.execute(interaction);\n return true;\n }\n } catch (error) {\n this.reportError(error, { interaction, command: interaction.command?.name });\n }\n return false;\n }\n\n private matchComponent(customId: string): ComponentHandlerDefinition | undefined {\n const exact = this.componentHandlers.get(customId);\n if (exact) return exact;\n for (const [pattern, handler] of this.componentHandlers) {\n if (pattern.endsWith(\"*\") && customId.startsWith(pattern.slice(0, -1))) {\n return handler;\n }\n }\n return undefined;\n }\n\n private resolvePrefix(message: Message): string | null {\n if (typeof this.prefixResolver === \"function\") {\n return this.prefixResolver(message);\n }\n return this.prefixResolver;\n }\n\n private ensureAttached(): void {\n if (this.attached) return;\n this.attached = true;\n\n this.client.on(\"message.created\", (message) => {\n void this.handleTextMessage(message);\n });\n\n this.client.on(\"interaction.created\", (interaction) => {\n void this.handleInteraction(interaction);\n });\n\n if (this.options.syncOnLogin !== false) {\n const runSync = () => {\n void this.sync().catch((error: unknown) => {\n this.reportError(error, {});\n });\n };\n if (this.client.isReady()) {\n // Comandos registrados depois do login: sincroniza na hora.\n runSync();\n } else {\n this.client.once(\"ready\", runSync);\n }\n }\n }\n\n private reportError(\n error: unknown,\n context: { command?: string; message?: Message; interaction?: Interaction },\n ): void {\n if (this.options.onError) {\n this.options.onError(error, context);\n return;\n }\n this.client.emit(\"commandError\", { error, ...context });\n }\n}\n\nfunction validateTextDefinition(definition: TextCommandDefinition): void {\n if (!definition.name || typeof definition.name !== \"string\") {\n throw new SquordTypeError(\"Comando de texto precisa de name\");\n }\n if (/\\s/.test(definition.name)) {\n throw new SquordTypeError(`Nome de comando não pode ter espaços: ${definition.name}`);\n }\n if (typeof definition.execute !== \"function\") {\n throw new SquordTypeError(`Comando ${definition.name} precisa de execute()`);\n }\n}\n","/**\n * Iteração sobre listas paginadas por cursor.\n *\n * A API devolve `{ items, prevCursor, nextCursor, hasMore }`. Este helper\n * converte uma função de página em um `AsyncGenerator` de itens, para\n * processar o histórico sem carregar tudo em memória.\n */\n\nimport type { CursorPaginationParams } from \"../types/common\";\nimport type { Page } from \"../types/common\";\n\nexport type PageFetcher<T> = (params: CursorPaginationParams) => Promise<Page<T>>;\n\n/**\n * Percorre as páginas de uma lista, emitindo os itens um a um.\n *\n * @param fetchPage função que busca uma página (`limit`, `before`, `after`).\n * @param firstParams parâmetros da primeira página.\n * @param direction percorre para trás (`before`, o padrão do histórico)\n * ou para frente (`after`).\n */\nexport async function* paginate<T>(\n fetchPage: PageFetcher<T>,\n firstParams: CursorPaginationParams = {},\n direction: \"before\" | \"after\" = \"before\",\n): AsyncGenerator<T, void, unknown> {\n let params: CursorPaginationParams = { ...firstParams };\n // Guarda contra loops de cursor defeituoso.\n const seenCursors = new Set<string>();\n\n for (;;) {\n const page = await fetchPage(params);\n for (const item of page.items) {\n yield item;\n }\n if (!page.hasMore) return;\n\n const nextCursor =\n direction === \"before\"\n ? page.prevCursor\n : page.nextCursor;\n if (!nextCursor || seenCursors.has(nextCursor)) return;\n seenCursors.add(nextCursor);\n\n params =\n direction === \"before\"\n ? { ...params, limit: params.limit, before: nextCursor, after: undefined }\n : { ...params, limit: params.limit, after: nextCursor, before: undefined };\n }\n}\n\n/** Coleta todos os itens de uma paginação em um array (use com critério). */\nexport async function collectPagination<T>(\n fetchPage: PageFetcher<T>,\n firstParams: CursorPaginationParams = {},\n direction: \"before\" | \"after\" = \"before\",\n maxItems = 10_000,\n): Promise<T[]> {\n const items: T[] = [];\n for await (const item of paginate(fetchPage, firstParams, direction)) {\n items.push(item);\n if (items.length >= maxItems) break;\n }\n return items;\n}\n","/**\n * Intents do gateway.\n *\n * As intents são configuradas por bot (Configurações → Desenvolvedor, ou\n * `PATCH /bots/{bot.id}`) e **não** vão no `identify`: o gateway lê as\n * intents do bot no momento do identify. Este módulo serve para calcular,\n * exibir e comparar valores — por exemplo, ao gerenciar o bot pela API.\n *\n * O padrão de um bot novo é `GUILDS | GUILD_MESSAGES | GUILD_MESSAGE_REACTIONS`\n * (valor `13`).\n *\n * @see https://docs.squord.com.br/gateway/intents\n */\n\nexport const Intents = {\n /** Space, canais, cargos, threads, emojis, stickers, eventos do Space. */\n GUILDS: 1 << 0,\n /** Entrada, saída, edição e ban de membros. */\n GUILD_MEMBERS: 1 << 1,\n /** `message.*` e votos de enquete. */\n GUILD_MESSAGES: 1 << 2,\n /** Reações. */\n GUILD_MESSAGE_REACTIONS: 1 << 3,\n /** Estado e salas de voz. */\n GUILD_VOICE_STATES: 1 << 4,\n /**\n * **Privilegiada.** Não liga evento nenhum: devolve o conteúdo das\n * mensagens. Sem ela, `content`, `embeds`, `attachments`, `components`\n * e `poll` chegam esvaziados — exceto mensagens do próprio bot e as que\n * o mencionam.\n */\n MESSAGE_CONTENT: 1 << 5,\n} as const;\n\nexport type IntentFlag = keyof typeof Intents;\n\n/** Intents padrão de um bot novo. */\nexport const DEFAULT_INTENTS: number =\n Intents.GUILDS | Intents.GUILD_MESSAGES | Intents.GUILD_MESSAGE_REACTIONS; // 13\n\n/** Soma flags de intent em um número (0 a 65535). */\nexport function intentsValue(...flags: number[]): number {\n const value = flags.reduce((a, b) => a | b, 0);\n if (value < 0 || value > 65_535) {\n throw new RangeError(\"As intents somam um inteiro de 0 a 65535\");\n }\n return value;\n}\n\n/** Lista as flags conhecidas presentes em um valor de intents. */\nexport function listIntents(value: number): IntentFlag[] {\n const names: IntentFlag[] = [];\n for (const [name, flag] of Object.entries(Intents) as Array<[IntentFlag, number]>) {\n if ((value & flag) === flag) names.push(name);\n }\n return names;\n}\n"],"mappings":";AAkBO,IAAM,eAAN,MAA4C;AAAA,EACzC,WAAW,oBAAI,IAA4C;AAAA;AAAA,EAGnE,GAA2B,OAAU,SAA8C;AACjF,QAAI,MAAM,KAAK,SAAS,IAAI,KAAK;AACjC,QAAI,CAAC,KAAK;AACR,YAAM,oBAAI,IAAI;AACd,WAAK,SAAS,IAAI,OAAO,GAAG;AAAA,IAC9B;AACA,QAAI,IAAI,OAA8B;AACtC,WAAO,MAAM,KAAK,IAAI,OAAO,OAAO;AAAA,EACtC;AAAA;AAAA,EAGA,KAA6B,OAAU,SAA8C;AACnF,UAAM,WAAW,IAAI,SAA4B;AAC/C,WAAK,IAAI,OAAO,OAAkC;AAClD,WAAM,QAAyC,GAAG,IAAI;AAAA,IACxD;AACA,WAAO,KAAK,GAAG,OAAO,OAAO;AAAA,EAC/B;AAAA;AAAA,EAGA,IAA4B,OAAU,SAAyC;AAC7E,QAAI,CAAC,SAAS;AACZ,WAAK,SAAS,OAAO,KAAK;AAC1B;AAAA,IACF;AACA,SAAK,SAAS,IAAI,KAAK,GAAG,OAAO,OAA8B;AAAA,EACjE;AAAA;AAAA,EAGA,qBAA2B;AACzB,SAAK,SAAS,MAAM;AAAA,EACtB;AAAA;AAAA,EAGA,KAA6B,UAAa,MAAkC;AAC1E,UAAM,MAAM,KAAK,SAAS,IAAI,KAAK;AACnC,QAAI,CAAC,OAAO,IAAI,SAAS,EAAG,QAAO;AACnC,eAAW,WAAW,CAAC,GAAG,GAAG,GAAG;AAC9B,UAAI;AACF,cAAM,SAAU,QAAyC,GAAG,IAAI;AAChE,YAAI,kBAAkB,SAAS;AAC7B,eAAK,OAAO,MAAM,CAAC,QAAiB,KAAK,iBAAiB,OAAO,GAAG,CAAC;AAAA,QACvE;AAAA,MACF,SAAS,KAAK;AACZ,aAAK,iBAAiB,OAAO,GAAG;AAAA,MAClC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,cAAsC,OAAkB;AACtD,WAAO,KAAK,SAAS,IAAI,KAAK,GAAG,QAAQ;AAAA,EAC3C;AAAA;AAAA,EAGA,aAAkC;AAChC,WAAO,CAAC,GAAG,KAAK,SAAS,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,GAAG,QAAQ,KAAK,CAAC;AAAA,EACtF;AAAA,EAEQ,iBAAiB,OAAqB,KAAoB;AAChE,QAAI,UAAU,QAAS,OAAM;AAC7B,UAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,IAAC,KAAK,KAA6D,SAAS,KAAK;AAAA,EACnF;AACF;;;ACtEO,IAAM,6BAAN,MAAiC;AAAA,EACtC,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA,EAG7B,WAAW,QAA6C;AACtD,WAAO,KAAK,KAAK,IAAkB,sBAAsB,EAAE,OAAO,CAAC;AAAA,EACrE;AAAA;AAAA,EAGA,UAAU,UAA6B,QAA6C;AAClF,WAAO,KAAK,KAAK,IAAkB,sBAAsB,UAAU,EAAE,OAAO,CAAC;AAAA,EAC/E;AAAA;AAAA,EAGA,UAAU,SAAoB,QAA6C;AACzE,WAAO,KAAK,KAAK,IAAkB,oBAAoB,OAAO,aAAa,EAAE,OAAO,CAAC;AAAA,EACvF;AAAA;AAAA,EAGA,SAAS,SAAoB,UAA6B,QAA6C;AACrG,WAAO,KAAK,KAAK,IAAkB,oBAAoB,OAAO,aAAa,UAAU;AAAA,MACnF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACjCO,IAAM,aAAN,MAAiB;AAAA,EACtB,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA,EAG7B,aAAa,QAAuC;AAClD,WAAO,KAAK,KAAK,IAAY,aAAa,EAAE,OAAO,CAAC;AAAA,EACtD;AAAA;AAAA,EAGA,MAAM,OAAkB,QAAuC;AAC7D,WAAO,KAAK,KAAK,IAAY,SAAS,KAAK,IAAI,EAAE,OAAO,CAAC;AAAA,EAC3D;AACF;AAEO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA,EAG7B,QAAQ,QAA+C;AACrD,WAAO,KAAK,KAAK,IAAoB,cAAc,EAAE,OAAO,CAAC;AAAA,EAC/D;AACF;;;ACZO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA,EAG7B,MAAM,WAAsB,QAA2C;AACrE,WAAO,KAAK,KAAK,IAAgB,aAAa,SAAS,IAAI,EAAE,OAAO,CAAC;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,SAAoB,QAAqD;AACjF,WAAO,KAAK,KAAK,IAA0B,WAAW,OAAO,aAAa,EAAE,OAAO,CAAC;AAAA,EACtF;AAAA;AAAA,EAGA,aACE,WACA,MACA,UAAoC,CAAC,GACjB;AACpB,WAAO,KAAK,KAAK,KAAgB,aAAa,SAAS,YAAY,MAAM;AAAA,MACvE,QAAQ,QAAQ;AAAA,MAChB,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,gBACE,WACA,MACA,UAAoC,CAAC,GACjB;AACpB,WAAO,KAAK,KAAK,KAAgB,aAAa,SAAS,YAAY,MAAM;AAAA,MACvE,QAAQ,QAAQ;AAAA,MAChB,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,wBACE,WACA,WACA,MACA,UAAoC,CAAC,GACjB;AACpB,WAAO,KAAK,KAAK;AAAA,MACf,aAAa,SAAS,aAAa,SAAS;AAAA,MAC5C;AAAA,MACA,EAAE,QAAQ,QAAQ,QAAQ,WAAW,MAAM;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA,EAGA,YACE,WACA,SAA8B,CAAC,GAC/B,QACwB;AACxB,WAAO,KAAK,KAAK,IAAmB,aAAa,SAAS,YAAY;AAAA,MACpE,OAAO;AAAA,QACL,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO,SAAS,OAAO;AAAA,QAC/B,UAAU,OAAO;AAAA,QACjB,OAAO,OAAO;AAAA,MAChB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACzEO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA,EAE5B;AAAA,EAET,YAAY,MAAc,SAAiB,SAA+B;AACxE,UAAM,SAAS,OAAuB;AACtC,SAAK,OAAO,WAAW;AACvB,SAAK,OAAO;AAAA,EACd;AACF;AAMO,IAAM,iBAAN,cAA6B,YAAY;AAAA;AAAA,EAErC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,MAAoB,QAAgB,WAA2B;AACzE,UAAM,KAAK,MAAM,KAAK,WAAW,+BAA+B,MAAM,GAAG;AACzE,SAAK,SAAS;AACd,SAAK,YAAY,aAAa,KAAK,aAAa;AAChD,SAAK,UAAU,KAAK;AACpB,SAAK,eAAe;AAAA,EACtB;AACF;AAGO,IAAM,sBAAN,cAAkC,eAAe;AAAC;AAGlD,IAAM,oBAAN,cAAgC,oBAAoB;AAAC;AAGrD,IAAM,kBAAN,cAA8B,eAAe;AAAA;AAAA,EAEzC;AAAA,EAET,YAAY,MAAoB,QAAgB,WAA2B;AACzE,UAAM,MAAM,QAAQ,SAAS;AAC7B,UAAM,UAAU,KAAK;AACrB,SAAK,oBAAoB,SAAS,cAAc;AAAA,EAClD;AACF;AAGO,IAAM,gBAAN,cAA4B,eAAe;AAAC;AAG5C,IAAM,kBAAN,cAA8B,eAAe;AAAA;AAAA,EAEzC;AAAA,EAET,YAAY,MAAoB,QAAgB,WAA2B;AACzE,UAAM,MAAM,QAAQ,SAAS;AAC7B,SAAK,SAAS,MAAM,QAAQ,KAAK,OAAO,IAAK,KAAK,UAAmC,CAAC;AAAA,EACxF;AACF;AAGO,IAAM,iBAAN,cAA6B,eAAe;AAAA;AAAA,EAExC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAET,YACE,MACA,QACA,SACA;AACA,UAAM,MAAM,QAAQ,SAAS,SAAS;AACtC,UAAM,UAAU,KAAK;AACrB,SAAK,aAAa,SAAS,cAAc;AACzC,SAAK,SAAS,SAAS,UAAU;AACjC,SAAK,mBAAmB,SAAS,oBAAoB;AAAA,EACvD;AACF;AAGO,IAAM,eAAN,cAA2B,YAAY;AAAA,EAC5C,YAAY,SAAiB,SAA+B;AAC1D,UAAM,iBAAiB,SAAS,OAAO;AAAA,EACzC;AACF;AAGO,IAAM,sBAAN,cAAkC,YAAY;AAAA;AAAA,EAE1C;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,QAAgB,MAAc,WAAmB,SAA+B;AAC1F;AAAA,MACE;AAAA,MACA,sBAAgB,MAAM,IAAI,IAAI,yBAAyB,SAAS;AAAA,MAChE;AAAA,IACF;AACA,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,YAAY;AAAA,EACnB;AACF;AAGO,IAAM,eAAN,cAA2B,YAAY;AAAA;AAAA,EAEnC;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,WAA0B,QAAuB,SAAkB;AAC7E;AAAA,MACE,cAAc,OAAO,0BAA0B;AAAA,MAC/C,WAAW,8BAA2B,cAAc,OAAO,eAAY,SAAS,MAAM,EAAE,GAAG,SAAS,KAAK,MAAM,KAAK,EAAE;AAAA,MACtH,EAAE,OAAO,OAAU;AAAA,IACrB;AACA,SAAK,YAAY;AACjB,SAAK,SAAS;AAAA,EAChB;AACF;AAGO,IAAM,kBAAN,cAA8B,YAAY;AAAA,EAC/C,YAAY,SAAiB;AAC3B,UAAM,wBAAwB,OAAO;AAAA,EACvC;AACF;AAMO,SAAS,aACd,MACA,QACA,WACgB;AAChB,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,KAAK,SAAS,kBACjB,IAAI,kBAAkB,MAAM,QAAQ,SAAS,IAC7C,IAAI,oBAAoB,MAAM,QAAQ,SAAS;AAAA,IACrD,KAAK;AACH,aAAO,IAAI,gBAAgB,MAAM,QAAQ,SAAS;AAAA,IACpD,KAAK;AACH,aAAO,IAAI,cAAc,MAAM,QAAQ,SAAS;AAAA,IAClD,KAAK;AACH,aAAO,IAAI,gBAAgB,MAAM,QAAQ,SAAS;AAAA,IACpD,KAAK;AACH,aAAO,IAAI,eAAe,MAAM,QAAQ,EAAE,UAAU,CAAC;AAAA,IACvD;AACE,aAAO,IAAI,eAAe,MAAM,QAAQ,SAAS;AAAA,EACrD;AACF;;;ACzKO,IAAM,kBAAkB;AAAA,EAC7B,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,UAAU;AAAA,EACV,OAAO;AAAA,EACP,gBAAgB;AAClB;AAEO,IAAM,gBAAN,MAAoB;AAAA,EAKzB,YACmB,OACT,YACR;AAFiB;AACT;AAAA,EACP;AAAA,EAFgB;AAAA,EACT;AAAA,EANF;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA;AAAA,EAQxB,YAAY,UAAwB;AAClC,mBAAe,QAAQ;AACvB,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,KAAmB;AACxB,QAAI,CAAC,cAAc,KAAK,GAAG,GAAG;AAC5B,YAAM,IAAI,gBAAgB,kDAA+C,GAAG,GAAG;AAAA,IACjF;AACA,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,UAAyB;AACnC,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,OAAqB;AAC5B,SAAK,aAAa;AAClB,WAAO;AAAA,EACT;AAAA,EAEA,QAAmB;AACjB,QAAI,KAAK,UAAU,UAAU,CAAC,KAAK,UAAU;AAC3C,YAAM,IAAI,gBAAgB,oCAAiC;AAAA,IAC7D;AACA,QAAI,KAAK,UAAU,UAAU,CAAC,KAAK,eAAe;AAChD,YAAM,IAAI,gBAAgB,sBAAmB,KAAK,KAAK,yBAAyB;AAAA,IAClF;AACA,QAAI,KAAK,WAAW,SAAS,gBAAgB,OAAO;AAClD,YAAM,IAAI,gBAAgB,4BAAyB,gBAAgB,KAAK,aAAa;AAAA,IACvF;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK,UAAU,SAAS,SAAY,KAAK;AAAA,MACnD,KAAK,KAAK,UAAU,SAAS,KAAK,WAAW;AAAA,MAC7C,UAAU,KAAK,iBAAiB;AAAA,IAClC;AAAA,EACF;AACF;AAEO,IAAM,oBAAN,MAAwB;AAAA,EAO7B,YAA6B,UAAkB;AAAlB;AAC3B,mBAAe,QAAQ;AAAA,EACzB;AAAA,EAF6B;AAAA,EANrB;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB,eAAkC,CAAC;AAAA,EAM3C,eAAe,aAA2B;AACxC,QAAI,YAAY,SAAS,KAAK;AAC5B,YAAM,IAAI,gBAAgB,2CAA2C;AAAA,IACvE;AACA,SAAK,mBAAmB;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,KAAmB;AAC9B,SAAK,iBAAiB;AACtB,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,KAAmB;AAC9B,SAAK,iBAAiB;AACtB,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,UAAyB;AACnC,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,QAA+B;AACvC,QAAI,KAAK,aAAa,UAAU,gBAAgB,gBAAgB;AAC9D,YAAM,IAAI,gBAAgB,4BAAyB,gBAAgB,cAAc,eAAS;AAAA,IAC5F;AACA,QAAI,CAAC,OAAO,SAAS,CAAC,OAAO,OAAO;AAClC,YAAM,IAAI,gBAAgB,yCAAmC;AAAA,IAC/D;AACA,QAAI,OAAO,MAAM,SAAS,gBAAgB,SAAS,OAAO,MAAM,SAAS,KAAK;AAC5E,YAAM,IAAI,gBAAgB,+DAAmD;AAAA,IAC/E;AACA,SAAK,aAAa,KAAK,MAAM;AAC7B,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,SAAkC;AAC9C,eAAW,UAAU,QAAS,MAAK,UAAU,MAAM;AACnD,WAAO;AAAA,EACT;AAAA,EAEA,QAAuB;AACrB,QAAI,KAAK,aAAa,WAAW,GAAG;AAClC,YAAM,IAAI,gBAAgB,2DAA+C;AAAA,IAC3E;AACA,UAAM,MAAM,KAAK,kBAAkB;AACnC,UAAM,MAAM,KAAK,kBAAkB,KAAK,IAAI,GAAG,KAAK,aAAa,MAAM;AACvE,QAAI,MAAM,KAAK;AACb,YAAM,IAAI,gBAAgB,cAAc,GAAG,sCAAmC,GAAG,GAAG;AAAA,IACtF;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,KAAK;AAAA,MACf,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,UAAU,KAAK,iBAAiB;AAAA,MAChC,SAAS,CAAC,GAAG,KAAK,YAAY;AAAA,IAChC;AAAA,EACF;AACF;AAEO,IAAM,mBAAN,MAAuB;AAAA,EACpB,aAA+C,CAAC;AAAA;AAAA,EAGxD,UAAU,QAAyC;AACjD,QAAI,KAAK,WAAW,UAAU,gBAAgB,iBAAiB,KAAK,WAAW,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,GAAG;AAC/G,YAAM,IAAI,gBAAgB,0EAA8D;AAAA,IAC1F;AACA,SAAK,WAAW,KAAK,kBAAkB,gBAAgB,OAAO,MAAM,IAAI,MAAM;AAC9E,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,cAAc,MAA+C;AAC3D,QAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,YAAM,IAAI,gBAAgB,6DAAuD;AAAA,IACnF;AACA,SAAK,WAAW,KAAK,gBAAgB,oBAAoB,KAAK,MAAM,IAAI,IAAI;AAC5E,WAAO;AAAA,EACT;AAAA,EAEA,iBAAiB,YAAwF;AACvG,eAAW,aAAa,YAAY;AAClC,UAAI,qBAAqB,iBAAkB,UAAU,aAAa,UAAU,SAAS,UAAW;AAC9F,aAAK,UAAU,SAAsC;AAAA,MACvD,OAAO;AACL,aAAK,cAAc,SAA8C;AAAA,MACnE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAyB;AACvB,QAAI,KAAK,WAAW,WAAW,GAAG;AAChC,YAAM,IAAI,gBAAgB,4BAA4B;AAAA,IACxD;AACA,WAAO,EAAE,MAAM,OAAO,YAAY,CAAC,GAAG,KAAK,UAAU,EAAE;AAAA,EACzD;AACF;AAGO,IAAM,UAAU;AAAA,EACrB,SAAS,CAAC,UAAkB,IAAI,cAAc,WAAW,KAAK;AAAA,EAC9D,WAAW,CAAC,UAAkB,IAAI,cAAc,aAAa,KAAK;AAAA,EAClE,QAAQ,CAAC,UAAkB,IAAI,cAAc,UAAU,KAAK;AAAA,EAC5D,MAAM,CAAC,UAAkB,IAAI,cAAc,QAAQ,KAAK;AAC1D;AAEA,SAAS,eAAe,UAAwB;AAC9C,MAAI,OAAO,aAAa,YAAY,SAAS,SAAS,KAAK,SAAS,SAAS,gBAAgB,UAAU;AACrG,UAAM,IAAI;AAAA,MACR,+BAA+B,gBAAgB,QAAQ;AAAA,IACzD;AAAA,EACF;AACF;;;AChMO,IAAM,cAAc;AAAA,EACzB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,aAAa;AAAA,EACb,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,qBAAqB;AACvB;AAoBO,SAAS,oBAAoB,OAAgC;AAClE,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,UAAY;AAC/D,YAAM,IAAI;AAAA,QACR,6BAA0B,KAAK;AAAA,MACjC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,KAAK;AAC3B,QAAM,MAAM,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;AACzD,MAAI,CAAC,mBAAmB,KAAK,GAAG,GAAG;AACjC,UAAM,IAAI,gBAAgB,6BAA0B,KAAK,UAAU,KAAK,CAAC,uBAAkB;AAAA,EAC7F;AACA,SAAO,OAAO,SAAS,KAAK,EAAE;AAChC;AAEO,IAAM,eAAN,MAAM,cAAa;AAAA,EAChB,aAA4B;AAAA,EAC5B,mBAAkC;AAAA,EAClC,WAA0B;AAAA,EAC1B,aAA4B;AAAA,EAC5B,iBAAgC;AAAA,EAChC,cAAuC;AAAA,EACvC,cAAuC;AAAA,EACvC,aAA4B;AAAA,EAC5B,iBAAgC;AAAA,EAChC,cAAiC,CAAC;AAAA;AAAA,EAG1C,SAAS,OAAqB;AAC5B,iBAAa,SAAS,OAAO,YAAY,KAAK;AAC9C,SAAK,aAAa;AAClB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,eAAe,aAA2B;AACxC,iBAAa,eAAe,aAAa,YAAY,WAAW;AAChE,SAAK,mBAAmB;AACxB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,KAAmB;AACxB,kBAAc,OAAO,GAAG;AACxB,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,SAAS,OAA8B;AACrC,SAAK,aAAa,oBAAoB,KAAK;AAC3C,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,YAA2B,oBAAI,KAAK,GAAS;AACxD,SAAK,iBACH,qBAAqB,OAAO,UAAU,YAAY,IAAI;AACxD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,UAAU,QAAuC;AAC/C,QAAI,QAAQ;AACV,mBAAa,eAAe,OAAO,MAAM,YAAY,UAAU;AAC/D,UAAI,OAAO,IAAK,eAAc,cAAc,OAAO,GAAG;AAAA,IACxD;AACA,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,UAAU,QAAuC;AAC/C,QAAI,QAAQ;AACV,mBAAa,eAAe,OAAO,MAAM,YAAY,UAAU;AAAA,IACjE;AACA,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,SAAS,KAAmB;AAC1B,SAAK,aAAa;AAClB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,KAAmB;AAC9B,SAAK,iBAAiB;AACtB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,SAAS,MAAc,OAAe,SAAS,OAAa;AAC1D,WAAO,KAAK,UAAU,EAAE,MAAM,OAAO,OAAO,CAAC;AAAA,EAC/C;AAAA;AAAA,EAGA,aAAa,QAAiC;AAC5C,QAAI,KAAK,YAAY,SAAS,OAAO,SAAS,YAAY,gBAAgB;AACxE,YAAM,IAAI;AAAA,QACR,gCAA6B,YAAY,cAAc;AAAA,MACzD;AAAA,IACF;AACA,eAAW,SAAS,QAAQ;AAC1B,mBAAa,cAAc,MAAM,MAAM,YAAY,SAAS;AAC5D,mBAAa,eAAe,MAAM,OAAO,YAAY,UAAU;AAC/D,WAAK,YAAY,KAAK,KAAK;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,cAAoB;AAClB,SAAK,cAAc,CAAC;AACpB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,QAAuB;AACrB,QACE,CAAC,KAAK,cACN,CAAC,KAAK,oBACN,CAAC,KAAK,cACN,CAAC,KAAK,kBACN,KAAK,YAAY,WAAW,KAC5B,CAAC,KAAK,eACN,CAAC,KAAK,aACN;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,QAAuB,CAAC;AAC9B,QAAI,KAAK,WAAY,OAAM,QAAQ,KAAK;AACxC,QAAI,KAAK,iBAAkB,OAAM,cAAc,KAAK;AACpD,QAAI,KAAK,SAAU,OAAM,MAAM,KAAK;AACpC,QAAI,KAAK,eAAe,KAAM,OAAM,QAAQ,KAAK;AACjD,QAAI,KAAK,eAAgB,OAAM,YAAY,KAAK;AAChD,QAAI,KAAK,aAAa;AACpB,YAAM,SAA+C,EAAE,MAAM,KAAK,YAAY,KAAK;AACnF,UAAI,KAAK,YAAY,IAAK,QAAO,MAAM,KAAK,YAAY;AACxD,UAAI,KAAK,YAAY,QAAS,QAAO,WAAW,KAAK,YAAY;AACjE,YAAM,SAAS;AAAA,IACjB;AACA,QAAI,KAAK,aAAa;AACpB,YAAM,SAA+C,EAAE,MAAM,KAAK,YAAY,KAAK;AACnF,UAAI,KAAK,YAAY,QAAS,QAAO,WAAW,KAAK,YAAY;AACjE,YAAM,SAAS;AAAA,IACjB;AACA,QAAI,KAAK,WAAY,OAAM,QAAQ,EAAE,KAAK,KAAK,WAAW;AAC1D,QAAI,KAAK,eAAgB,OAAM,YAAY,EAAE,KAAK,KAAK,eAAe;AACtE,QAAI,KAAK,YAAY,SAAS,EAAG,OAAM,SAAS,CAAC,GAAG,KAAK,WAAW;AACpE,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,IAAI,aAAqB;AACvB,QAAI,QAAQ;AACZ,QAAI,KAAK,WAAY,UAAS,KAAK,WAAW;AAC9C,QAAI,KAAK,iBAAkB,UAAS,KAAK,iBAAiB;AAC1D,QAAI,KAAK,YAAa,UAAS,KAAK,YAAY,KAAK;AACrD,QAAI,KAAK,YAAa,UAAS,KAAK,YAAY,KAAK;AACrD,eAAW,SAAS,KAAK,aAAa;AACpC,eAAS,MAAM,KAAK,SAAS,MAAM,MAAM;AAAA,IAC3C;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,KAAK,OAA+C;AACzD,UAAM,UAAU,IAAI,cAAa;AACjC,QAAI,MAAM,MAAO,SAAQ,SAAS,MAAM,KAAK;AAC7C,QAAI,MAAM,YAAa,SAAQ,eAAe,MAAM,WAAW;AAC/D,QAAI,MAAM,IAAK,SAAQ,OAAO,MAAM,GAAG;AACvC,QAAI,MAAM,SAAS,KAAM,SAAQ,SAAS,MAAM,KAAK;AACrD,QAAI,MAAM,UAAW,SAAQ,aAAa,MAAM,SAAS;AACzD,QAAI,YAAY,SAAS,MAAM,QAAQ;AACrC,cAAQ,UAAU;AAAA,QAChB,MAAM,MAAM,OAAO;AAAA,QACnB,KAAK,SAAS,MAAM,SAAU,MAAM,OAAO,OAAO,SAAa;AAAA,QAC/D,SAAS,aAAa,MAAM,SAAU,MAAM,OAAO,WAAW,SAAa;AAAA,MAC7E,CAAC;AAAA,IACH;AACA,QAAI,YAAY,SAAS,MAAM,QAAQ;AACrC,cAAQ,UAAU;AAAA,QAChB,MAAM,MAAM,OAAO;AAAA,QACnB,SAAS,aAAa,MAAM,SAAU,MAAM,OAAO,WAAW,SAAa;AAAA,MAC7E,CAAC;AAAA,IACH;AACA,QAAI,YAAY,SAAS,MAAM,QAAQ,MAAM,MAAM,KAAK,MAAM,OAAO,SAAS,GAAG;AAC/E,cAAQ,UAAU,GAAG,MAAM,MAAM;AAAA,IACnC;AACA,UAAM,QAAQ,WAAW,QAAQ,MAAM,QAAQ;AAC/C,QAAI,SAAS,SAAS,MAAO,SAAQ,SAAS,MAAM,GAAG;AACvD,UAAM,YAAY,eAAe,QAAS,MAAwB,YAAY;AAC9E,QAAI,aAAa,SAAS,UAAW,SAAQ,aAAa,UAAU,GAAG;AACvE,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,OAAe,OAAe,KAAmB;AACrE,MAAI,MAAM,SAAS,KAAK;AACtB,UAAM,IAAI,gBAAgB,SAAS,KAAK,WAAW,GAAG,gBAAgB,MAAM,MAAM,GAAG;AAAA,EACvF;AACF;AAEA,SAAS,cAAc,OAAe,KAAmB;AACvD,MAAI,CAAC,eAAe,KAAK,GAAG,GAAG;AAC7B,UAAM,IAAI,gBAAgB,SAAS,KAAK,+CAA+C,GAAG,GAAG;AAAA,EAC/F;AACF;;;AC5NA,IAAM,wBAAyC,EAAE,OAAO,MAAM,OAAO,OAAO,UAAU,MAAM;AAGrF,SAAS,sBACd,SACgD;AAChD,QAAM,SACJ,OAAO,YAAY,WAAW,EAAE,SAAS,QAAQ,IAAI;AAEvD,QAAM,OAAuD,CAAC;AAC9D,MAAI,oBAAoB;AAExB,MAAI,OAAO,YAAY,QAAW;AAChC,QAAI,OAAO,OAAO,YAAY,UAAU;AACtC,YAAM,IAAI,gBAAgB,4BAA4B;AAAA,IACxD;AACA,QAAI,OAAO,QAAQ,SAAS,KAAM;AAChC,YAAM,IAAI,gBAAgB,mCAAmC,OAAO,QAAQ,MAAM,GAAG;AAAA,IACvF;AACA,SAAK,UAAU,OAAO;AACtB,QAAI,OAAO,QAAQ,SAAS,EAAG,qBAAoB;AAAA,EACrD;AAEA,MAAI,OAAO,WAAW,QAAW;AAC/B,QAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,SAAS,IAAI;AAC9D,YAAM,IAAI,gBAAgB,+BAA4B;AAAA,IACxD;AACA,SAAK,SAAS,OAAO,OAAO;AAAA,MAAI,CAAC,UAC/B,iBAAiB,eAAe,MAAM,MAAM,IAAK;AAAA,IACnD;AACA,QAAI,KAAK,OAAO,SAAS,EAAG,qBAAoB;AAAA,EAClD;AAEA,MAAI,OAAO,eAAe,QAAW;AACnC,QAAI,CAAC,MAAM,QAAQ,OAAO,UAAU,KAAK,OAAO,WAAW,SAAS,GAAG;AACrE,YAAM,IAAI,gBAAgB,mCAAgC;AAAA,IAC5D;AACA,SAAK,aAAa,OAAO,WAAW;AAAA,MAAI,CAAC,QACvC,eAAe,mBAAmB,IAAI,MAAM,IAAK;AAAA,IACnD;AACA,QAAI,KAAK,WAAW,SAAS,EAAG,qBAAoB;AAAA,EACtD;AAKA,OAAK,kBAAkB,OAAO,mBAAmB;AAEjD,MAAI,OAAO,cAAc,QAAW;AAClC,SAAK,YAAY,OAAO;AAAA,EAC1B;AAEA,MAAI,OAAO,kBAAkB,QAAW;AACtC,QAAI,CAAC,MAAM,QAAQ,OAAO,aAAa,KAAK,OAAO,cAAc,SAAS,IAAI;AAC5E,YAAM,IAAI,gBAAgB,sCAAmC;AAAA,IAC/D;AACA,SAAK,gBAAgB,OAAO;AAC5B,QAAI,KAAK,cAAc,SAAS,EAAG,qBAAoB;AAAA,EACzD;AAEA,MAAI,OAAO,UAAU,QAAW;AAC9B,QAAI,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,SAAS,IAAI;AAChE,YAAM,IAAI,gBAAgB,kDAA+C;AAAA,IAC3E;AACA,SAAK,QAAQ,OAAO;AAAA,EACtB;AAEA,MAAI,OAAO,cAAc,QAAW;AAClC,SAAK,YAAY,OAAO;AAAA,EAC1B;AAEA,MAAI,CAAC,mBAAmB;AACtB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAGO,SAAS,0BAA0B,SAAiD;AACzF,QAAM,SACJ,OAAO,YAAY,WAAW,EAAE,SAAS,QAAQ,IAAI;AACvD,QAAM,OAA2B,CAAC;AAClC,MAAI,WAAW;AAEf,MAAI,OAAO,YAAY,QAAW;AAChC,QAAI,OAAO,QAAQ,SAAS,KAAM;AAChC,YAAM,IAAI,gBAAgB,mCAAmC,OAAO,QAAQ,MAAM,GAAG;AAAA,IACvF;AACA,SAAK,UAAU,OAAO;AACtB,eAAW;AAAA,EACb;AACA,MAAI,OAAO,WAAW,QAAW;AAC/B,SAAK,SAAS,OAAO,OAAO;AAAA,MAAI,CAAC,UAC/B,iBAAiB,eAAe,MAAM,MAAM,IAAK;AAAA,IACnD;AACA,eAAW;AAAA,EACb;AACA,MAAI,OAAO,eAAe,QAAW;AACnC,SAAK,aAAa,OAAO,WAAW;AAAA,MAAI,CAAC,QACvC,eAAe,mBAAmB,IAAI,MAAM,IAAK;AAAA,IACnD;AACA,eAAW;AAAA,EACb;AACA,MAAI,OAAO,oBAAoB,QAAW;AACxC,SAAK,kBAAkB,OAAO;AAAA,EAChC;AACA,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,oBAAoB,SAA4C;AAC9E,SAAO,WAAW;AACpB;;;ACrIO,IAAM,sBAAN,MAA0B;AAAA,EAC/B,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU7B,SACE,eACA,kBACA,MACA,QACe;AACf,WAAO,KAAK,KACT,KAAW,iBAAiB,aAAa,IAAI,gBAAgB,aAAa,MAAM;AAAA,MAC/E,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,IACb,CAAC,EACA,KAAK,MAAM,MAAS;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SACE,eACA,kBACA,MACA,QACe;AACf,WAAO,KAAK,KACT,KAAW,iBAAiB,aAAa,IAAI,gBAAgB,cAAc,MAAM;AAAA,MAChF,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,IACb,CAAC,EACA,KAAK,MAAM,MAAS;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MACJ,eACA,kBACA,SACA,UAAyD,CAAC,GAC3C;AACf,UAAM,OAAO,sBAAsB,OAAO;AAC1C,QAAI,QAAQ,UAAW,MAAK,YAAY;AACxC,QAAI;AACF,YAAM,KAAK,SAAS,eAAe,kBAAkB,EAAE,MAAM,WAAW,KAAK,GAAG,QAAQ,MAAM;AAAA,IAChG,SAAS,KAAK;AACZ,UAAI,sBAAsB,GAAG,EAAG;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,MACJ,eACA,kBACA,UAAoC,CAAC,GACtB;AACf,QAAI;AACF,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,QACA,EAAE,MAAM,WAAW;AAAA,QACnB,QAAQ;AAAA,MACV;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,sBAAsB,GAAG,EAAG;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,OACJ,eACA,kBACA,SACA,UAAoC,CAAC,GACtB;AACf,UAAM,OAAO,sBAAsB,OAAO;AAC1C,QAAI;AACF,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,QACA,EAAE,MAAM,UAAU,KAAK;AAAA,QACvB,QAAQ;AAAA,MACV;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,sBAAsB,GAAG,EAAG;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,qBACJ,eACA,kBACA,UAAoC,CAAC,GACtB;AACf,QAAI;AACF,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,QACA,EAAE,MAAM,kBAAkB;AAAA,QAC1B,QAAQ;AAAA,MACV;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,sBAAsB,GAAG,EAAG;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,SAAS,sBAAsB,KAAuB;AACpD,SACE,OAAO,QAAQ,YACf,QAAQ,QACP,IAA2C,WAAW,OACtD,IAA0B,SAAS;AAExC;;;ACzIO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA,EAG7B,MAAM,SAAoB,QAAyC;AACjE,WAAO,KAAK,KAAK,IAAc,WAAW,OAAO,IAAI,EAAE,OAAO,CAAC;AAAA,EACjE;AACF;AAWO,IAAM,iBAAN,MAAqB;AAAA,EAC1B,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA,EAG7B,MAAM,SAAoB,QAAmB,QAA0C;AACrF,WAAO,KAAK,KAAK,IAAe,WAAW,OAAO,YAAY,MAAM,IAAI,EAAE,OAAO,CAAC;AAAA,EACpF;AAAA;AAAA,EAGA,KAAK,SAAoB,SAA2B,CAAC,GAAG,QAA8C;AACpG,WAAO,KAAK,KAAK,IAAmB,WAAW,OAAO,YAAY;AAAA,MAChE,OAAO;AAAA,QACL,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,MACpB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KACE,SACA,QACA,MACA,UAAoC,CAAC,GACjB;AACpB,WAAO,KAAK,KAAK,MAAiB,WAAW,OAAO,YAAY,MAAM,IAAI,MAAM;AAAA,MAC9E,QAAQ,QAAQ;AAAA;AAAA,MAEhB,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,QAAQ,SAAoB,QAAmB,OAAgB,SAAwD;AACrH,WAAO,KAAK,KAAK,SAAS,QAAQ,EAAE,cAAc,MAAM,GAAG,OAAO;AAAA,EACpE;AAAA;AAAA,EAGA,cAAc,SAAoB,QAAmB,SAAwD;AAC3G,WAAO,KAAK,KAAK,SAAS,QAAQ,EAAE,cAAc,KAAK,GAAG,OAAO;AAAA,EACnE;AAAA;AAAA,EAGA,KACE,SACA,QACA,QACA,UAAoC,CAAC,GACtB;AACf,WAAO,KAAK,KACT,OAAa,WAAW,OAAO,YAAY,MAAM,IAAI;AAAA,MACpD,MAAM,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC7B,QAAQ,QAAQ;AAAA,IAClB,CAAC,EACA,KAAK,MAAM,MAAS;AAAA,EACzB;AAAA;AAAA,EAGA,QAAQ,SAAoB,QAAmB,QAAmB,UAAoC,CAAC,GAAkB;AACvH,WAAO,KAAK,KACT,IAAU,WAAW,OAAO,YAAY,MAAM,UAAU,MAAM,IAAI,QAAW;AAAA,MAC5E,QAAQ,QAAQ;AAAA,IAClB,CAAC,EACA,KAAK,MAAM,MAAS;AAAA,EACzB;AAAA;AAAA,EAGA,WAAW,SAAoB,QAAmB,QAAmB,UAAoC,CAAC,GAAkB;AAC1H,WAAO,KAAK,KACT,OAAa,WAAW,OAAO,YAAY,MAAM,UAAU,MAAM,IAAI;AAAA,MACpE,QAAQ,QAAQ;AAAA,IAClB,CAAC,EACA,KAAK,MAAM,MAAS;AAAA,EACzB;AACF;AAEO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA,EAG7B,KAAK,SAAoB,QAA0C;AACjE,WAAO,KAAK,KAAK,IAAe,WAAW,OAAO,UAAU,EAAE,OAAO,CAAC;AAAA,EACxE;AACF;AAGO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAM7B,IACE,SACA,QACA,OAAyB,CAAC,GAC1B,UAAoC,CAAC,GACd;AACvB,WAAO,KAAK,KAAK,IAAkB,WAAW,OAAO,SAAS,MAAM,IAAI,MAAM;AAAA,MAC5E,QAAQ,QAAQ;AAAA,MAChB,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,SAAoB,QAAmB,UAAoC,CAAC,GAAkB;AAClG,WAAO,KAAK,KACT,OAAa,WAAW,OAAO,SAAS,MAAM,IAAI,EAAE,QAAQ,QAAQ,OAAO,CAAC,EAC5E,KAAK,MAAM,MAAS;AAAA,EACzB;AACF;;;AC1JA,SAAS,kBAAkB;AAGpB,SAAS,eAAuB;AACrC,SAAO,WAAW;AACpB;AAGO,SAAS,WAAmB;AACjC,SAAO,WAAW,EAAE,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,EAAE;AACnD;AAGO,SAAS,WAAW,OAAwB;AACjD,SAAO,OAAO,UAAU,YAAY,cAAc,KAAK,KAAK;AAC9D;AAGO,SAAS,iBAAiB,OAAuB;AACtD,SAAO,MAAM,WAAW,MAAM,IAAI,MAAM,MAAM,CAAC,IAAI;AACrD;AAGO,SAAS,eAAe,OAAyB;AACtD,QAAM,OAAiB,CAAC;AACxB,MAAI,UAAU;AACd,MAAI,WAA6B;AAEjC,aAAW,QAAQ,OAAO;AACxB,QAAI,UAAU;AACZ,UAAI,SAAS,UAAU;AACrB,mBAAW;AAAA,MACb,OAAO;AACL,mBAAW;AAAA,MACb;AACA;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,iBAAW;AACX;AAAA,IACF;AACA,QAAI,KAAK,KAAK,IAAI,GAAG;AACnB,UAAI,SAAS;AACX,aAAK,KAAK,OAAO;AACjB,kBAAU;AAAA,MACZ;AACA;AAAA,IACF;AACA,eAAW;AAAA,EACb;AACA,MAAI,QAAS,MAAK,KAAK,OAAO;AAC9B,SAAO;AACT;;;AC1BO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA,EAG7B,MAAM,WAAsB,WAA2C;AACrE,WAAO,KAAK,KAAK;AAAA,MACf,aAAa,SAAS,aAAa,SAAS;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA,EAGA,KACE,WACA,SAA+B,CAAC,GAChC,QACyB;AACzB,WAAO,KAAK,KAAK,IAAoB,aAAa,SAAS,aAAa;AAAA,MACtE,OAAO,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,QAAQ,OAAO,OAAO,MAAM;AAAA,MACzE;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KACE,WACA,SACA,UAAuB,CAAC,GACH;AACrB,UAAM,OAAO,sBAAsB,OAAO;AAC1C,UAAM,QAAQ,KAAK,SAAS,QAAQ,SAAS,SAAS;AACtD,UAAM,aAAmC;AAAA,MACvC,GAAG;AAAA,MACH;AAAA,MACA,iBAAiB,oBAAoB,KAAK,eAAe;AAAA,IAC3D;AACA,WAAO,KAAK,KAAK,KAAiB,aAAa,SAAS,aAAa,YAAY;AAAA,MAC/E,QAAQ,QAAQ;AAAA;AAAA,MAEhB,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,KACE,WACA,WACA,SACA,UAAoC,CAAC,GAChB;AACrB,UAAM,OAA2B,0BAA0B,OAAO;AAClE,WAAO,KAAK,KAAK;AAAA,MACf,aAAa,SAAS,aAAa,SAAS;AAAA,MAC5C;AAAA,MACA,EAAE,QAAQ,QAAQ,OAAO;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,WAAsB,WAAsB,UAAoC,CAAC,GAAkB;AACxG,WAAO,KAAK,KACT,OAAa,aAAa,SAAS,aAAa,SAAS,IAAI,EAAE,QAAQ,QAAQ,OAAO,CAAC,EACvF,KAAK,MAAM,MAAS;AAAA,EACzB;AAAA;AAAA,EAGA,MAAM,WAAsB,WAAsB,OAAe,UAAoC,CAAC,GAAkB;AACtH,WAAO,KAAK,KACT;AAAA,MACC,aAAa,SAAS,aAAa,SAAS,cAAc,mBAAmB,KAAK,CAAC;AAAA,MACnF;AAAA,MACA,EAAE,QAAQ,QAAQ,OAAO;AAAA,IAC3B,EACC,KAAK,MAAM,MAAS;AAAA,EACzB;AAAA;AAAA,EAGA,eAAe,WAAsB,WAAsB,OAAe,UAAoC,CAAC,GAAkB;AAC/H,WAAO,KAAK,KACT;AAAA,MACC,aAAa,SAAS,aAAa,SAAS,cAAc,mBAAmB,KAAK,CAAC;AAAA,MACnF,EAAE,QAAQ,QAAQ,OAAO;AAAA,IAC3B,EACC,KAAK,MAAM,MAAS;AAAA,EACzB;AAAA;AAAA,EAGA,cAAc,WAAsB,WAAsB,QAA8C;AACtG,WAAO,KAAK,KAAK;AAAA,MACf,aAAa,SAAS,aAAa,SAAS;AAAA,MAC5C,EAAE,OAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA,EAGA,IAAI,WAAsB,WAAsB,UAAoC,CAAC,GAAkB;AACrG,WAAO,KAAK,KACT,IAAU,aAAa,SAAS,SAAS,SAAS,IAAI,QAAW,EAAE,QAAQ,QAAQ,OAAO,CAAC,EAC3F,KAAK,MAAM,MAAS;AAAA,EACzB;AAAA;AAAA,EAGA,MAAM,WAAsB,WAAsB,UAAoC,CAAC,GAAkB;AACvG,WAAO,KAAK,KACT,OAAa,aAAa,SAAS,SAAS,SAAS,IAAI,EAAE,QAAQ,QAAQ,OAAO,CAAC,EACnF,KAAK,MAAM,MAAS;AAAA,EACzB;AAAA;AAAA,EAGA,SAAS,WAAsB,QAA6C;AAC1E,WAAO,KAAK,KAAK,IAAkB,aAAa,SAAS,SAAS,EAAE,OAAO,CAAC;AAAA,EAC9E;AACF;;;AC5HA,SAAS,gBAAgB;;;ACRzB,IAAM,cAAwC;AAAA,EAC5C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AACV;AAYO,SAAS,OAAO,OAAuB;AAC5C,SACE,MAEG,QAAQ,wBAAwB,gBAAgB,EAEhD,QAAQ,+BAA+B,gBAAgB,EAEvD,QAAQ,0BAA0B,sBAAsB;AAE/D;AASO,SAAS,oBAAoB,UAAgC,CAAC,GAAW;AAC9E,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,QAAQ,QAAQ,UAAU,CAAC,SAAiB,QAAQ,IAAI,IAAI;AAElE,QAAM,MACJ,CAAC,KAAkC,WACnC,CAAC,SAAiB,SAAmC;AACnD,QAAI,YAAY,GAAG,IAAI,YAAY,KAAK,EAAG;AAC3C,UAAM,QAAQ;AAAA,MACZ,IAAG,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC1B,OAAO;AAAA,MACP,OAAO,UAAU;AAAA,MACjB,KAAK,OAAO,OAAO;AAAA,MACnB,GAAG;AAAA,IACL;AACA,UAAM,OAAO,KAAK,UAAU,KAAK,CAAC,CAAC;AAAA,EACrC;AAEF,QAAM,OAAO,CAAC,YAA4B;AAAA,IACxC,OAAO,IAAI,SAAS,MAAM;AAAA,IAC1B,MAAM,IAAI,QAAQ,MAAM;AAAA,IACxB,MAAM,IAAI,QAAQ,MAAM;AAAA,IACxB,OAAO,IAAI,SAAS,MAAM;AAAA,IAC1B,OAAO,CAAC,gBAAwB,KAAK,SAAS,GAAG,MAAM,IAAI,WAAW,KAAK,WAAW;AAAA,EACxF;AAEA,SAAO,KAAK,EAAE;AAChB;AAGO,IAAM,aAAqB;AAAA,EAChC,QAAQ;AAAA,EAAC;AAAA,EACT,OAAO;AAAA,EAAC;AAAA,EACR,OAAO;AAAA,EAAC;AAAA,EACR,QAAQ;AAAA,EAAC;AAAA,EACT,OAAO,MAAM;AACf;AAMO,SAAS,gBAAwB;AACtC,QAAM,WAAW,QAAQ,IAAI,cAAc,IAAI,YAAY;AAC3D,MAAI,WAAW,aAAa;AAC1B,WAAO,oBAAoB,EAAE,OAAO,QAAoB,CAAC;AAAA,EAC3D;AACA,MAAI,QAAQ,IAAI,iBAAiB,OAAO,QAAQ,IAAI,iBAAiB,QAAQ;AAC3E,WAAO,oBAAoB,EAAE,OAAO,QAAQ,CAAC;AAAA,EAC/C;AACA,SAAO;AACT;;;AD/CO,IAAM,iBAAN,MAAqB;AAAA,EAG1B,YACmB,MACjB,QACA;AAFiB;AAGjB,SAAK,UAAU,UAAU,YAAY,MAAM,SAAS;AAAA,EACtD;AAAA,EAJmB;AAAA,EAHF;AAAA;AAAA,EAUjB,QAAQ,MAA2B,QAAqD;AACtF,WAAO,KAAK,KAAK,KAA2B,YAAY,MAAM;AAAA,MAC5D;AAAA,MACA,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,QAAQ,UAAqB,OAA6B,CAAC,GAAG,QAA0C;AACtG,WAAO,KAAK,KAAK,KAAgB,YAAY,QAAQ,YAAY,MAAM;AAAA,MACrE;AAAA,MACA,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAO,SAA4C;AACvD,UAAM,EAAE,MAAM,MAAM,OAAO,IAAI;AAE/B,QAAI;AACJ,QAAI,WAAW,QAAQ;AACvB,QAAI,OAAO,QAAQ;AAEnB,QAAI,SAAS,QAAW;AACtB,cAAQ,MAAM,SAAS,IAAI,EAAE,MAAM,MAAM;AACvC,cAAM,IAAI,gBAAgB,yCAAmC,IAAI,EAAE;AAAA,MACrE,CAAC;AACD,mBAAa,SAAS,IAAI;AAC1B,eAAS,MAAM;AAAA,IACjB,WAAW,SAAS,QAAW;AAC7B,UAAI,OAAO,SAAS,UAAU;AAC5B,gBAAQ,OAAO,KAAK,MAAM,MAAM;AAAA,MAClC,WAAW,OAAO,SAAS,IAAI,KAAK,gBAAgB,YAAY;AAC9D,gBAAQ,OAAO,SAAS,IAAI,IAAI,OAAO,OAAO,KAAK,IAAI;AAAA,MACzD,WAAW,OAAQ,KAAkB,SAAS,YAAY;AACxD,gBAAQ,MAAM,KAAK,cAAc,MAAkB,MAAM;AAAA,MAC3D,OAAO;AACL,cAAM,IAAI,gBAAgB,yDAAyD;AAAA,MACrF;AACA,mBAAa;AACb,eAAS,MAAM;AAAA,IACjB,OAAO;AACL,YAAM,IAAI,gBAAgB,oCAAoC;AAAA,IAChE;AAEA,QAAI,SAAS,UAAa,OAAO,MAAM,IAAI,GAAG;AAC5C,YAAM,IAAI,gBAAgB,oCAAoC;AAAA,IAChE;AACA,QAAI,QAAQ,GAAG;AACb,YAAM,IAAI,gBAAgB,kCAA+B;AAAA,IAC3D;AACA,QAAI,OAAO,UAAa;AACtB,YAAM,IAAI;AAAA,QACR,8BAA8B,IAAI;AAAA,MACpC;AAAA,IACF;AACA,UAAM,cAAc,QAAQ,eAAe,iBAAiB,YAAY,SAAS;AAEjF,UAAM,cAAc,MAAM,KAAK;AAAA,MAC7B,EAAE,OAAO,eAAe,UAAU,YAAY,WAAW,aAAa,MAAM,SAAS,QAAQ,QAAQ;AAAA,MACrG;AAAA,IACF;AAIA,UAAM,SAAS,YAAY;AAC3B,UAAM,WAAW,MAAM,KAAK,KAAK,MAAM,OAAO,WAAW;AAAA,MACvD,QAAQ;AAAA,MACR,SAAS,EAAE,GAAG,OAAO,QAAQ;AAAA,MAC7B,MAAM,IAAI,WAAW,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,YAAM,IAAI;AAAA,QACR,kCAAkC,SAAS,MAAM,IAAI,OAAO,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE;AAAA,MAC5F;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,KAAK,QAAQ,YAAY,OAAO,IAAI,CAAC,GAAG,MAAM;AACnE,QAAI,OAAO,WAAW,SAAS;AAC7B,WAAK,OAAO,KAAK,sCAAsC;AAAA,QACrD,IAAI,OAAO;AAAA,QACX,QAAQ,OAAO;AAAA,QACf,YAAY,OAAO;AAAA,MACrB,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,oBAAoB,SAA4C;AACpE,UAAM,SAAS,MAAM,KAAK,OAAO,OAAO;AACxC,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAc,cAAc,QAAkB,QAAuC;AACnF,UAAM,SAAmB,CAAC;AAC1B,QAAI;AACF,uBAAiB,SAAS,QAAQ;AAChC,YAAI,QAAQ,QAAS,OAAM,IAAI,aAAa,oBAAoB,YAAY;AAC5E,eAAO,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAmB,CAAC;AAAA,MAC/E;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,QAAQ;AACf,YAAM;AAAA,IACR;AACA,WAAO,OAAO,OAAO,MAAM;AAAA,EAC7B;AACF;AAEA,SAAS,SAAS,MAAsB;AACtC,QAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,SAAO,MAAM,MAAM,SAAS,CAAC,KAAK;AACpC;AAEA,SAAS,iBAAiB,UAA0B;AAClD,QAAM,MAAM,SAAS,YAAY,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK;AACvD,QAAM,QAAgC;AAAA,IACpC,KAAK;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AACA,SAAO,MAAM,GAAG,KAAK;AACvB;;;AE5LO,SAAS,aAAa,SAAiB,UAA0B,CAAC,GAAW;AAClF,QAAM,EAAE,SAAS,KAAM,SAAS,GAAG,QAAQ,KAAQ,SAAS,KAAK,IAAI;AACrE,QAAM,UAAU,KAAK,IAAI,SAAS,EAAE;AACpC,QAAM,MAAM,KAAK,IAAI,SAAS,UAAU,SAAS,KAAK;AACtD,QAAM,eAAe,MAAM,UAAU,KAAK,OAAO,IAAI,IAAI;AACzD,SAAO,KAAK,IAAI,KAAK,KAAK,MAAM,MAAM,YAAY,CAAC;AACrD;AASO,SAAS,MAAM,IAAY,QAAqC;AACrE,MAAI,MAAM,EAAG,QAAO,QAAQ,QAAQ;AACpC,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,QAAQ,WAAW,MAAM;AAC7B,cAAQ,oBAAoB,SAAS,OAAO;AAC5C,cAAQ;AAAA,IACV,GAAG,EAAE;AACL,UAAM,UAAU,MAAM;AACpB,mBAAa,KAAK;AAClB,aAAO,IAAI,aAAa,iBAAiB,YAAY,CAAC;AAAA,IACxD;AACA,YAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC3D,CAAC;AACH;;;AC+CA,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAErB,IAAM,aAAN,MAAiB;AAAA,EACb;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe,oBAAI,IAA4B;AAAA,EAC/C,qBAAqB,oBAAI,IAAoB;AAAA,EAC7C,eAAyB,CAAC;AAAA,EAC1B;AAAA,EACT,YAAY;AAAA,EAEpB,YAAY,SAA4B;AACtC,SAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AACvE,SAAK,QAAQ,QAAQ;AACrB,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,UAAU,QAAQ,UAAU,YAAY,MAAM,MAAM;AACzD,UAAM,MAAM,QAAQ,2BAA2B;AAC/C,SAAK,cAAc,MAAM,IAAI,MAAM,OAAO;AAAA,EAC5C;AAAA;AAAA,EAGA,IAAO,MAAc,UAA0B,CAAC,GAAe;AAC7D,WAAO,KAAK,QAAW,OAAO,MAAM,OAAO;AAAA,EAC7C;AAAA;AAAA,EAGA,IAAI,QAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,KAAQ,MAAc,MAAgB,UAA0B,CAAC,GAAe;AAC9E,WAAO,KAAK,QAAW,QAAQ,MAAM,EAAE,GAAG,SAAS,KAAK,CAAC;AAAA,EAC3D;AAAA;AAAA,EAGA,IAAO,MAAc,MAAgB,UAA0B,CAAC,GAAe;AAC7E,WAAO,KAAK,QAAW,OAAO,MAAM,EAAE,GAAG,SAAS,KAAK,CAAC;AAAA,EAC1D;AAAA;AAAA,EAGA,MAAS,MAAc,MAAgB,UAA0B,CAAC,GAAe;AAC/E,WAAO,KAAK,QAAW,SAAS,MAAM,EAAE,GAAG,SAAS,KAAK,CAAC;AAAA,EAC5D;AAAA;AAAA,EAGA,OAAiB,MAAc,UAA0B,CAAC,GAAsB;AAC9E,WAAO,KAAK,QAAkB,UAAU,MAAM,OAAO;AAAA,EACvD;AAAA;AAAA,EAGA,MAAM,QACJ,QACA,MACA,UAA0B,CAAC,GACf;AACZ,UAAM,WAAW,MAAM,KAAK,WAAc,QAAQ,MAAM,OAAO;AAC/D,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA,EAGA,MAAM,WACJ,QACA,MACA,UAA0B,CAAC,GACD;AAC1B,QAAI,KAAK,WAAW;AAClB,YAAM,IAAI;AAAA,QACR,EAAE,YAAY,GAAG,MAAM,iBAAiB,SAAS,6BAA0B;AAAA,QAC3E;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,QAAQ,aAAa,WAAW;AAClD,UAAM,MAAM,KAAK,SAAS,MAAM,QAAQ,KAAK;AAC7C,UAAM,YAAY,QAAQ,aAAa,aAAa;AACpD,UAAM,WAAW,WAAW,QAAQ,IAAI;AAExC,QAAI;AAEJ,aAAS,UAAU,GAAG,WAAW,KAAK,YAAY,WAAW;AAC3D,UAAI,QAAQ,QAAQ,QAAS,OAAM,IAAI,aAAa,8BAAwB,YAAY;AAExF,YAAM,KAAK,mBAAmB,UAAU,QAAQ,MAAM;AACtD,YAAM,KAAK,kBAAkB,QAAQ,MAAM;AAE3C,YAAM,UAAkC;AAAA,QACtC,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,MAClB;AACA,UAAI,QAAQ,SAAS,OAAO;AAC1B,gBAAQ,gBAAgB,OAAO,KAAK,KAAK;AAAA,MAC3C;AACA,YAAM,UAAU,IAAI,QAAQ,KAAK;AAAA,QAC/B;AAAA,QACA;AAAA,QACA,MAAM,QAAQ,SAAS,SAAY,SAAY,KAAK,UAAU,QAAQ,IAAI;AAAA,MAC5E,CAAC;AAGD,YAAM,UAAyB,CAAC;AAChC,YAAM,oBAAoB,IAAI,gBAAgB;AAC9C,YAAM,QAAQ,WAAW,MAAM;AAC7B,0BAAkB,MAAM,IAAI,aAAa,qBAAqB,cAAc,CAAC;AAAA,MAC/E,GAAG,KAAK,SAAS;AACjB,cAAQ,KAAK,kBAAkB,MAAM;AACrC,UAAI,QAAQ,OAAQ,SAAQ,KAAK,QAAQ,MAAM;AAC/C,YAAM,kBACJ,QAAQ,WAAW,IAAI,QAAQ,CAAC,IAAK,YAAY,IAAI,OAAO;AAE9D,UAAI;AACJ,UAAI;AACF,mBAAW,MAAM,KAAK,UAAU,SAAS,EAAE,QAAQ,gBAAgB,CAAC;AAAA,MACtE,SAAS,KAAK;AACZ,oBAAY,KAAK,eAAe,KAAK,QAAQ,IAAI;AACjD,cAAM,WAAW,aAAa,UAAU,KAAK;AAC7C,aAAK,OAAO,MAAM,mBAAmB,EAAE,QAAQ,MAAM,SAAS,WAAW,SAAS,CAAC;AACnF,YAAI,CAAC,SAAU,OAAM;AACrB,cAAM,MAAM,aAAa,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAM,CAAC,GAAG,QAAQ,MAAM;AAChF;AAAA,MACF,UAAE;AACA,qBAAa,KAAK;AAAA,MACpB;AAEA,WAAK,kBAAkB,UAAU,SAAS,OAAO;AAEjD,UAAI,SAAS,IAAI;AACf,cAAM,OAAQ,MAAM,KAAK,UAAa,QAAQ;AAC9C,eAAO;AAAA,UACL;AAAA,UACA,QAAQ,SAAS;AAAA,UACjB,SAAS,SAAS;AAAA,UAClB,WAAW,SAAS,QAAQ,IAAI,cAAc,KAAK;AAAA,UACnD;AAAA,QACF;AAAA,MACF;AAGA,YAAM,WAAW,MAAM,KAAK,WAAW,QAAQ;AAC/C,kBAAY;AAEZ,UAAI,SAAS,WAAW,OAAO,oBAAoB,gBAAgB;AACjE,YAAI,UAAU,KAAK,YAAY;AAC7B,gBAAM,SAAS,SAAS,aAAa;AACrC,eAAK,OAAO,KAAK,0BAA0B;AAAA,YACzC,QAAQ,SAAS;AAAA,YACjB,YAAY,SAAS;AAAA,UACvB,CAAC;AACD,gBAAM,MAAM,QAAQ,QAAQ,MAAM;AAClC;AAAA,QACF;AACA,cAAM,IAAI,eAAe,SAAS,cAAe,KAAK;AAAA,UACpD,WAAW,SAAS;AAAA,UACpB,kBAAkB;AAAA,QACpB,CAAC;AAAA,MACH;AAEA,UACE,SAAS,UAAU,OACnB,aACA,UAAU,KAAK,YACf;AACA,cAAM,SAAS,aAAa,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAM,CAAC;AAClE,aAAK,OAAO,KAAK,uBAAuB,EAAE,QAAQ,SAAS,QAAQ,SAAS,OAAO,CAAC;AACpF,cAAM,MAAM,QAAQ,QAAQ,MAAM;AAClC;AAAA,MACF;AAEA,UACE,SAAS,WAAW,QACnB,SAAS,SAAS,uBAAuB,SAAS,SAAS,qBAC5D,UAAU,KAAK,YACf;AACA,cAAM,MAAM,MAAM,aAAa,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAM,CAAC,GAAG,QAAQ,MAAM;AACtF;AAAA,MACF;AAEA,YAAM;AAAA,IACR;AAEA,UAAM;AAAA,EACR;AAAA;AAAA,EAGA,UAAgB;AACd,SAAK,YAAY;AACjB,SAAK,aAAa,MAAM;AACxB,SAAK,mBAAmB,MAAM;AAAA,EAChC;AAAA;AAAA,EAGA,YAAY,QAAoB,MAA0C;AACxE,WAAO,KAAK,aAAa,IAAI,WAAW,QAAQ,IAAI,CAAC;AAAA,EACvD;AAAA;AAAA,EAIQ,SACN,MACA,OACQ;AACR,QAAI,MAAM,GAAG,KAAK,OAAO,GAAG,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI,EAAE;AACpE,UAAM,SAAS,IAAI,gBAAgB;AACnC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,CAAC,CAAC,GAAG;AACtD,UAAI,UAAU,UAAa,UAAU,KAAM;AAC3C,aAAO,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,IAC/B;AACA,UAAM,KAAK,OAAO,SAAS;AAC3B,QAAI,GAAI,QAAO,IAAI,EAAE;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,UAAa,UAAuC;AAChE,QAAI,SAAS,WAAW,IAAK,QAAO;AACpC,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,WAAW,UAA6C;AACpE,QAAI,OAMA,CAAC;AACL,QAAI;AACF,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,QAAQ;AAAA,IAER;AACA,UAAM,WAAW;AAAA,MACf,YAAY,SAAS;AAAA,MACrB,MAAM,KAAK,QAAQ,QAAQ,SAAS,MAAM;AAAA,MAC1C,SAAS,KAAK,WAAW,SAAS;AAAA,MAClC,SAAS,KAAK;AAAA,MACd,WAAW,KAAK,aAAa,SAAS,QAAQ,IAAI,cAAc,KAAK;AAAA,IACvE;AACA,WAAO,aAAa,UAAgD,SAAS,QAAQ,SAAS,SAAS;AAAA,EACzG;AAAA,EAEQ,eAAe,KAAc,QAAgB,MAAuB;AAC1E,QAAI,eAAe,gBAAgB,IAAI,SAAS,gBAAgB;AAC9D,aAAO,IAAI,oBAAoB,QAAQ,MAAM,KAAK,WAAW,EAAE,OAAO,IAAI,CAAC;AAAA,IAC7E;AACA,QAAI,eAAe,gBAAgB,IAAI,SAAS,cAAc;AAC5D,aAAO;AAAA,IACT;AACA,UAAM,SAAU,KAA8B;AAC9C,QAAI,kBAAkB,gBAAgB,OAAO,SAAS,gBAAgB;AACpE,aAAO,IAAI,oBAAoB,QAAQ,MAAM,KAAK,WAAW,EAAE,OAAO,IAAI,CAAC;AAAA,IAC7E;AACA,WAAO,IAAI,aAAa,oBAAoB,MAAM,IAAI,IAAI,KAAK,OAAQ,KAAe,WAAW,GAAG,CAAC,IAAI;AAAA,MACvG,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEQ,kBAAkB,UAAkB,SAAwB;AAClE,UAAM,QAAQ,QAAQ,IAAI,mBAAmB;AAC7C,UAAM,YAAY,QAAQ,IAAI,uBAAuB;AACrD,UAAM,QAAQ,QAAQ,IAAI,mBAAmB;AAC7C,QAAI,UAAU,QAAQ,cAAc,QAAQ,UAAU,KAAM;AAC5D,UAAM,QAAwB;AAAA,MAC5B,OAAO,UAAU,OAAO,OAAO,KAAK,IAAI;AAAA,MACxC,WAAW,cAAc,OAAO,OAAO,SAAS,IAAI;AAAA,MACpD,OAAO,UAAU,OAAO,OAAO,KAAK,IAAI;AAAA,IAC1C;AACA,SAAK,aAAa,IAAI,UAAU,KAAK;AACrC,QAAI,MAAM,cAAc,KAAK,MAAM,UAAU,MAAM;AACjD,YAAM,eAAe,MAAM,QAAQ;AACnC,WAAK,mBAAmB,IAAI,UAAU,YAAY;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB,UAAkB,QAAqC;AACtF,eAAS;AACP,YAAM,eAAe,KAAK,mBAAmB,IAAI,QAAQ;AACzD,UAAI,iBAAiB,OAAW;AAChC,YAAM,SAAS,eAAe,KAAK,IAAI;AACvC,UAAI,UAAU,GAAG;AACf,aAAK,mBAAmB,OAAO,QAAQ;AACvC;AAAA,MACF;AACA,YAAM,MAAM,QAAQ,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAC1C,UAAI,QAAQ,QAAS;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAc,kBAAkB,QAAqC;AACnE,QAAI,KAAK,gBAAgB,OAAO,kBAAmB;AACnD,eAAS;AACP,YAAM,MAAM,KAAK,IAAI;AACrB,aAAO,KAAK,aAAa,SAAS,KAAK,MAAM,KAAK,aAAa,CAAC,KAAM,KAAM;AAC1E,aAAK,aAAa,MAAM;AAAA,MAC1B;AACA,UAAI,KAAK,aAAa,SAAS,KAAK,aAAa;AAC/C,aAAK,aAAa,KAAK,GAAG;AAC1B;AAAA,MACF;AACA,YAAM,SAAS,OAAQ,MAAM,KAAK,aAAa,CAAC,KAAM;AACtD,YAAM,MAAM,QAAQ,MAAM;AAAA,IAC5B;AAAA,EACF;AACF;AAMO,SAAS,WAAW,QAAgB,MAAsB;AAC/D,QAAM,aAAa,KAChB,QAAQ,iBAAiB,OAAO,EAChC,QAAQ,sBAAsB,OAAO;AACxC,SAAO,GAAG,MAAM,IAAI,UAAU;AAChC;;;ACtYO,SAAS,gBAAgB,IAAa,UAA4C;AACvF,QAAM,SAAS;AAQf,MAAI,OAAO,OAAO,qBAAqB,YAAY;AACjD,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,UAAMA,aAAY,CAAC,UAA8B;AAC/C,YAAM,OAAO,MAAM;AACnB,UAAI,OAAO,SAAS,SAAU,UAAS,QAAQ,IAAI;AAAA,eAC1C,gBAAgB,YAAa,UAAS,QAAQ,IAAI,YAAY,EAAE,OAAO,IAAI,CAAC;AAAA,eAC5E,QAAQ,OAAO,SAAS,YAAY,cAAc,MAAM;AAC/D,iBAAS,QAAQ,OAAO,IAAI,CAAC;AAAA,MAC/B;AAAA,IACF;AACA,UAAMC,WAAU,CAAC,UAAkE;AACjF,eAAS,MAAM;AAAA,QACb,MAAM,MAAM,QAAQ;AAAA,QACpB,QAAQ,MAAM,UAAU;AAAA,QACxB,UAAU,MAAM,YAAY;AAAA,MAC9B,CAAC;AAAA,IACH;AACA,UAAMC,WAAU,CAAC,UAAmB,SAAS,MAAM,KAAK;AAExD,WAAO,iBAAiB,QAAQ,MAAgC;AAChE,WAAO,iBAAiB,WAAWF,UAAmC;AACtE,WAAO,iBAAiB,SAASC,QAAiC;AAClE,WAAO,iBAAiB,SAASC,QAAiC;AAElE,WAAO;AAAA,MACL,MAAM,CAAC,SAAiB,OAAO,OAAO,IAAI;AAAA,MAC1C,OAAO,CAAC,MAAe,WAAoB,OAAO,QAAQ,MAAM,MAAM;AAAA,MACtE,IAAI,aAAqB;AACvB,eAAO,OAAO,cAAc;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,CAAC,SAAkB;AACnC,QAAI,OAAO,SAAS,SAAU,UAAS,QAAQ,IAAI;AAAA,aAC1C,OAAO,SAAS,IAAI,EAAG,UAAS,QAAQ,KAAK,SAAS,MAAM,CAAC;AAAA,QACjE,UAAS,QAAQ,OAAO,IAAI,CAAC;AAAA,EACpC;AACA,QAAM,UAAU,CAAC,MAAc,WAC7B,SAAS,MAAM,EAAE,MAAM,QAAQ,UAAU,KAAK,CAAC;AACjD,QAAM,UAAU,CAAC,UAAmB,SAAS,MAAM,KAAK;AAExD,SAAO,KAAK,QAAQ,SAAS,IAAqC;AAClE,SAAO,KAAK,WAAW,SAA0C;AACjE,SAAO,KAAK,SAAS,OAAwC;AAC7D,SAAO,KAAK,SAAS,OAAwC;AAE7D,SAAO;AAAA,IACL,MAAM,CAAC,SAAiB,OAAO,OAAO,IAAI;AAAA,IAC1C,OAAO,CAAC,MAAe,WAAoB,OAAO,QAAQ,MAAM,MAAM;AAAA,IACtE,IAAI,aAAqB;AACvB,aAAO,OAAO,cAAc;AAAA,IAC9B;AAAA,EACF;AACF;AAMO,IAAM,yBAA2C,CAAC,QAAQ,IAAI,UAAU,GAAG;;;ACuD3E,IAAM,oBAAoB;AAAA,EAC/B,cAAc;AAAA,EACd,eAAe;AAAA,EACf,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,wBAAwB;AAAA,EACxB,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;;;ACxFA,IAAM,cAAc;AACpB,IAAM,mBAAmB;AAGzB,IAAM,oBAAoB,oBAAI,IAAY;AAAA,EACxC,kBAAkB;AAAA;AAAA,EAClB,kBAAkB;AAAA;AAAA,EAClB,kBAAkB;AAAA;AACpB,CAAC;AAGD,IAAM,sBAAsB,oBAAI,IAAY;AAAA,EAC1C,kBAAkB;AAAA;AAAA,EAClB,kBAAkB;AAAA;AAAA,EAClB,kBAAkB;AAAA;AAAA,EAClB,kBAAkB;AAAA;AACpB,CAAC;AAOM,IAAM,UAAN,cAAsB,aAA4B;AAAA,EAC9C;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,KAA2B;AAAA,EAC3B,cAA6B;AAAA,EAC7B,oBAAoB;AAAA,EACpB,cAA4C;AAAA;AAAA,EAG5C,YAA2B;AAAA,EAC3B,YAA2B;AAAA,EAC3B,eAA8B;AAAA,EAC9B,cAAc;AAAA;AAAA,EAGd,YAAqC;AAAA,EACrC,iBAAwC;AAAA;AAAA,EAGxC,sBAAqC;AAAA,EACrC,iBAAwC;AAAA,EACxC,cAAc;AAAA,EACd,sBAAqC;AAAA,EAErC,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,qBAAqB;AAAA;AAAA,EAG7B,qBAAoC;AAAA;AAAA,EAEpC,iBAAiB;AAAA;AAAA,EAEjB,iBAAiB;AAAA;AAAA,EAEjB,gBAAgB;AAAA,EAEhB,IAAI,WAA0B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAI,UAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAI,SAAwB;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAI,UAAmB;AACrB,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA,EAEA,YAAY,SAAyB;AACnC,UAAM;AACN,SAAK,MAAM,QAAQ,OAAO;AAC1B,SAAK,QAAQ,QAAQ;AACrB,SAAK,YAAY,QAAQ,MAAM;AAC/B,SAAK,qBAAqB,QAAQ,sBAAsB;AACxD,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,UAAU,QAAQ,UAAU,YAAY,MAAM,SAAS;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,UAAiC;AACrC,QAAI,KAAK,UAAW,OAAM,IAAI,aAAa,MAAM,MAAM,4BAAyB;AAChF,QAAI,KAAK,SAAS;AAChB,YAAM,IAAI,aAAa,MAAM,MAAM,mCAA6B;AAAA,IAClE;AACA,QAAI,KAAK,YAAa,QAAO,KAAK;AAElC,SAAK,kBAAkB;AACvB,SAAK,cAAc,KAAK,eAAe,EAAE,QAAQ,MAAM;AACrD,WAAK,cAAc;AAAA,IACrB,CAAC;AACD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,YAAY,UAAuC;AACjD,QAAI,CAAC,KAAK,IAAI;AACZ,WAAK,KAAK,SAAS,IAAI,aAAa,MAAM,MAAM,6CAAuC,CAAC;AACxF;AAAA,IACF;AACA,SAAK,UAAU,mBAAmB,QAAQ;AAAA,EAC5C;AAAA;AAAA,EAGA,MAAM,UAAyB;AAC7B,QAAI,KAAK,UAAW;AACpB,SAAK,YAAY;AACjB,SAAK,kBAAkB;AACvB,SAAK,cAAc;AACnB,SAAK,cAAc,IAAI,aAAa,MAAM,MAAM,sBAAmB,CAAC;AACpE,SAAK,UAAU,WAAW;AAC1B,UAAM,KAAK,KAAK;AAChB,SAAK,KAAK;AACV,QAAI,MAAM,GAAG,cAAc,GAAG;AAC5B,UAAI;AACF,WAAG,MAAM,KAAM,iBAAiB;AAAA,MAClC,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,oBAA0B;AACxB,SAAK,YAAY;AACjB,SAAK,YAAY;AACjB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA,EAGA,eAAqB;AACnB,QAAI,CAAC,KAAK,GAAI;AACd,SAAK,qBAAqB;AAC1B,QAAI;AACF,WAAK,GAAG,MAAM,KAAM,kBAAkB;AAAA,IACxC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,iBAAwC;AACpD,SAAK,UAAU,KAAK,YAAY,iBAAiB,YAAY;AAC7D,eAAS;AACP,UAAI;AACF,cAAM,QAAQ,MAAM,KAAK,eAAe,KAAK,aAAa,KAAK,GAAG;AAClE,aAAK,oBAAoB;AACzB,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,YAAI,KAAK,UAAW,OAAM;AAC1B,cAAM,aAAa;AACnB,cAAM,OAAO,YAAY,aAAa;AACtC,YACE,SAAS,SACR,kBAAkB,IAAI,IAAI,KAAK,oBAAoB,IAAI,IAAI,IAC5D;AACA,eAAK,UAAU,cAAc;AAC7B,eAAK,KAAK,SAAS,UAAU;AAC7B,gBAAM;AAAA,QACR;AAEA,YAAI,CAAC,KAAK,eAAe;AACvB,eAAK,UAAU,cAAc;AAC7B,gBAAM;AAAA,QACR;AAEA,cAAM,UAAU,KAAK;AACrB,cAAM,UAAU,aAAa,SAAS,EAAE,QAAQ,KAAK,gBAAgB,CAAC;AACtE,aAAK;AACL,aAAK,UAAU,cAAc;AAC7B,aAAK,KAAK,gBAAgB;AAAA,UACxB;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,QAAQ,YAAY,UAAU,OAAQ,KAAe,WAAW,GAAG;AAAA,QACrE,CAAC;AACD,aAAK,OAAO,KAAK,gBAAgB,EAAE,SAAS,QAAQ,CAAC;AACrD,cAAM,MAAM,OAAO;AACnB,aAAK,UAAU,KAAK,YAAY,iBAAiB,YAAY;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGQ,eAAe,KAAoC;AACzD,WAAO,IAAI,QAAsB,CAAC,SAAS,WAAW;AACpD,UAAI;AACJ,UAAI;AACF,iBAAS,KAAK,UAAU,GAAG;AAAA,MAC7B,SAAS,KAAK;AACZ;AAAA,UACE,IAAI;AAAA,YACF;AAAA,YACA;AAAA,YACA,iDAA2C,GAAG,KAAK,OAAQ,KAAe,WAAW,GAAG,CAAC;AAAA,UAC3F;AAAA,QACF;AACA;AAAA,MACF;AAEA,WAAK,YAAY,EAAE,SAAS,OAAO;AACnC,WAAK,cAAc;AAEnB,WAAK,iBAAiB,WAAW,MAAM;AACrC,aAAK;AAAA,UACH,IAAI;AAAA,YACF;AAAA,YACA;AAAA,YACA,gCAAgC,KAAK,kBAAkB;AAAA,UACzD;AAAA,QACF;AAAA,MACF,GAAG,KAAK,kBAAkB;AAE1B,WAAK,KAAK,gBAAgB,QAAQ;AAAA,QAChC,MAAM,MAAM,KAAK,OAAO,MAAM,iCAAiC;AAAA,QAC/D,SAAS,CAAC,SAAS,KAAK,cAAc,IAAI;AAAA,QAC1C,OAAO,CAAC,UAAU,KAAK,YAAY,MAAM,MAAM,MAAM,MAAM;AAAA,QAC3D,OAAO,CAAC,QACN,KAAK,OAAO,MAAM,kBAAkB;AAAA,UAClC,KAAK,OAAQ,KAAe,WAAW,GAAG;AAAA,QAC5C,CAAC;AAAA,MACL,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,iBAAiB,OAA2B;AAClD,UAAM,YAAY,KAAK;AACvB,QAAI,CAAC,UAAW;AAChB,SAAK,oBAAoB;AACzB,SAAK,YAAY;AACjB,cAAU,QAAQ,KAAK;AAAA,EACzB;AAAA,EAEQ,cAAc,OAAoB;AACxC,UAAM,YAAY,KAAK;AACvB,SAAK,oBAAoB;AACzB,QAAI,CAAC,UAAW;AAChB,SAAK,YAAY;AACjB,cAAU,OAAO,KAAK;AAAA,EACxB;AAAA,EAEQ,sBAA4B;AAClC,QAAI,KAAK,gBAAgB;AACvB,mBAAa,KAAK,cAAc;AAChC,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAc,MAAoB;AACxC,QAAI;AACJ,QAAI;AACF,cAAQ,KAAK,MAAM,IAAI;AAAA,IACzB,QAAQ;AACN,WAAK,OAAO,KAAK,sCAAmC;AACpD;AAAA,IACF;AAEA,SAAK,KAAK,OAAO,KAAK;AAEtB,YAAQ,MAAM,IAAI;AAAA,MAChB,KAAK;AACH,aAAK,YAAY,MAAM,CAAiB;AACxC;AAAA,MACF,KAAK;AACH,aAAK,YAAY,MAAM,CAAiB;AACxC;AAAA,MACF,KAAK;AACH,aAAK,cAAc,MAAM,CAAmB;AAC5C;AAAA,MACF,KAAK;AACH,aAAK,mBAAmB,MAAM,CAAyB;AACvD;AAAA,MACF,KAAK;AACH,aAAK,qBAAqB,MAAM,CAA0B;AAC1D;AAAA,MACF,KAAK;AACH,aAAK,uBAAuB,MAAM,CAAqB;AACvD;AAAA,MACF,KAAK;AACH,aAAK,kBAAkB,MAAM,CAAsB;AACnD;AAAA,MACF,KAAK;AACH,aAAK,YAAY,KAA0B;AAC3C;AAAA,MACF;AACE,aAAK,OAAO,MAAM,uBAAuB;AAAA,UACvC,IAAK,MAA0B;AAAA,QACjC,CAAC;AAAA,IACL;AAAA,EACF;AAAA,EAEQ,YAAY,OAA2B;AAC7C,SAAK,sBAAsB,MAAM;AACjC,SAAK,OAAO,MAAM,SAAS,EAAE,qBAAqB,MAAM,oBAAoB,CAAC;AAE7E,QAAI,KAAK,cAAc,MAAM;AAI3B,WAAK,UAAU,UAAU;AAAA,QACvB,OAAO,KAAK;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,cAAc,KAAK,gBAAgB;AAAA,MACrC,CAAC;AAAA,IACH,OAAO;AACL,WAAK,UAAU,YAAY;AAAA,QACzB,OAAO,KAAK;AAAA,QACZ,iBAAiB;AAAA,MACnB,CAAC;AAAA,IACH;AACA,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,YAAY,OAA2B;AAC7C,SAAK,YAAY,MAAM;AACvB,SAAK,YAAY,MAAM,oBAAoB,KAAK;AAChD,SAAK,eAAe;AACpB,SAAK,cAAc;AACnB,SAAK,UAAU,OAAO;AACtB,SAAK,OAAO,KAAK,oBAAiB;AAAA,MAChC,WAAW,MAAM;AAAA,MACjB,QAAQ,MAAM,OAAO;AAAA,IACvB,CAAC;AACD,SAAK,KAAK,SAAS,KAAK;AACxB,SAAK,iBAAiB,KAAK;AAAA,EAC7B;AAAA,EAEQ,cAAc,SAA+B;AACnD,SAAK,YAAY,QAAQ;AACzB,SAAK,cAAc;AACnB,SAAK,UAAU,OAAO;AACtB,SAAK,OAAO,KAAK,sBAAmB;AAAA,MAClC,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IACpB,CAAC;AACD,SAAK,KAAK,WAAW,OAAO;AAC5B,SAAK,iBAAiB;AAAA,MACpB,WAAW,QAAQ;AAAA,MACnB,QAAQ;AAAA,MACR,QAAQ,CAAC;AAAA,MACT,kBAAkB,KAAK,aAAa,KAAK;AAAA,IAC3C,CAAC;AAAA,EACH;AAAA,EAEQ,mBAAmB,KAAiC;AAC1D,SAAK,cAAc;AACnB,QAAI,KAAK,wBAAwB,MAAM;AACrC,WAAK,qBAAqB,KAAK,IAAI,IAAI,KAAK;AAAA,IAC9C;AACA,SAAK,OAAO,MAAM,iBAAiB,EAAE,UAAU,IAAI,SAAS,CAAC;AAAA,EAC/D;AAAA,EAEQ,qBAAqB,SAAsC;AACjE,SAAK,OAAO,KAAK,qCAAqC,EAAE,QAAQ,CAAC;AACjE,SAAK,KAAK,kBAAkB,OAAO;AACnC,SAAK,kBAAkB;AAEvB,SAAK,UAAU,YAAY;AAAA,MACzB,OAAO,KAAK;AAAA,MACZ,iBAAiB;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEQ,uBAAuB,SAAiC;AAC9D,SAAK,OAAO,KAAK,+BAA4B,EAAE,QAAQ,CAAC;AAExD,UAAM,WAAW,WAAW,MAAM;AAChC,UAAI,CAAC,KAAK,aAAa,KAAK,IAAI;AAC9B,aAAK,OAAO,KAAK,oCAAoC;AACrD,YAAI;AACF,eAAK,GAAG,MAAM,KAAM,oBAAoB;AAAA,QAC1C,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,GAAG,GAAK;AACR,aAAS,QAAQ;AAAA,EACnB;AAAA,EAEQ,kBAAkB,YAAqC;AAE7D,SAAK,KAAK,eAAe,UAAU;AACnC,SAAK,OAAO,KAAK,2BAA2B,EAAE,OAAO,WAAiD,CAAC;AAAA,EACzG;AAAA,EAEQ,YAAY,OAAgC;AAClD,SAAK;AACL,QAAI,OAAO,MAAM,MAAM,UAAU;AAC/B,UAAI,KAAK,iBAAiB,QAAQ,MAAM,KAAK,KAAK,cAAc;AAC9D,aAAK;AACL,aAAK,OAAO,MAAM,+BAA+B;AAAA,UAC/C,MAAM,MAAM;AAAA,UACZ,GAAG,MAAM;AAAA,QACX,CAAC;AACD;AAAA,MACF;AACA,WAAK,eAAe,MAAM;AAAA,IAC5B;AACA,SAAK,KAAK,SAAS;AAAA,MACjB,MAAM,MAAM;AAAA,MACZ,GAAG,MAAM;AAAA,MACT,GAAG,MAAM;AAAA,MACT,WAAW,MAAM;AAAA,IACnB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAY,MAAc,QAAsB;AACtD,SAAK,cAAc;AACnB,SAAK,KAAK;AACV,UAAM,iBAAiB,KAAK;AAC5B,SAAK,cAAc;AAEnB,QAAI,KAAK,oBAAoB;AAC3B,WAAK,qBAAqB;AAC1B,WAAK,KAAK,cAAc,EAAE,MAAM,QAAQ,OAAO,MAAM,CAAC;AACtD,WAAK,KAAK,uBAAuB,MAAM,MAAM;AAC7C;AAAA,IACF;AAEA,QAAI,KAAK,aAAa,KAAK,iBAAiB;AAC1C,WAAK,kBAAkB;AACvB,WAAK,KAAK,cAAc,EAAE,MAAM,QAAQ,OAAO,MAAM,CAAC;AACtD,WAAK,cAAc,IAAI,aAAa,MAAM,QAAQ,sBAAmB,CAAC;AACtE;AAAA,IACF;AAEA,UAAM,QAAQ,kBAAkB,IAAI,IAAI;AACxC,UAAM,SAAS,oBAAoB,IAAI,IAAI;AAE3C,UAAM,QAAQ,IAAI;AAAA,MAChB;AAAA,MACA;AAAA,MACA,cAAc,MAAM,QAAQ,OAAO,MAAM;AAAA,IAC3C;AAEA,SAAK,KAAK,cAAc,EAAE,MAAM,QAAQ,OAAO,SAAS,OAAO,CAAC;AAEhE,QAAI,SAAS,QAAQ;AACnB,WAAK,OAAO,MAAM,qCAAkC,EAAE,MAAM,OAAO,CAAC;AACpE,WAAK,UAAU,cAAc;AAC7B,WAAK,cAAc,KAAK;AACxB;AAAA,IACF;AAEA,QAAI,gBAAgB;AAGlB,WAAK,KAAK,SAAS,KAAK;AACxB,WAAK,KAAK,uBAAuB,MAAM,MAAM;AAAA,IAC/C,OAAO;AAEL,WAAK,cAAc,KAAK;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAc,uBAAuB,MAAc,QAA+B;AAChF,QAAI,CAAC,KAAK,iBAAiB,KAAK,WAAW;AACzC,WAAK,UAAU,cAAc;AAC7B;AAAA,IACF;AACA,UAAM,UAAU,KAAK;AACrB,UAAM,UAAU,aAAa,SAAS,EAAE,QAAQ,KAAK,gBAAgB,CAAC;AACtE,SAAK;AACL,SAAK,UAAU,cAAc;AAC7B,SAAK,KAAK,gBAAgB,EAAE,SAAS,SAAS,WAAW,MAAM,OAAO,CAAC;AACvE,SAAK,OAAO,KAAK,8BAA2B,EAAE,SAAS,SAAS,KAAK,CAAC;AACtE,UAAM,MAAM,OAAO;AACnB,QAAI,KAAK,UAAW;AACpB,SAAK,UAAU,KAAK,YAAY,iBAAiB,YAAY;AAC7D,QAAI;AACF,YAAM,KAAK,eAAe,KAAK,aAAa,KAAK,GAAG;AACpD,WAAK,oBAAoB;AAAA,IAC3B,QAAQ;AAGN,UAAI,CAAC,KAAK,UAAW,MAAK,KAAK,uBAAuB,MAAM,MAAM;AAAA,IACpE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAuB;AAC7B,SAAK,cAAc;AACnB,QAAI,CAAC,KAAK,oBAAqB;AAI/B,UAAM,aAAa,KAAK,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,mBAAmB;AACzE,SAAK,iBAAiB,WAAW,MAAM;AACrC,WAAK,cAAc;AACnB,UAAI,KAAK,qBAAqB;AAC5B,aAAK,iBAAiB;AAAA,UACpB,MAAM,KAAK,cAAc;AAAA,UACzB,KAAK;AAAA,QACP;AAAA,MACF;AAAA,IACF,GAAG,UAAU;AAAA,EACf;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,gBAAgB;AACvB,mBAAa,KAAK,cAAc;AAChC,oBAAc,KAAK,cAAc;AACjC,WAAK,iBAAiB;AAAA,IACxB;AACA,SAAK,cAAc;AAAA,EACrB;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,aAAa,CAAC,KAAK,GAAI;AAKhC,QAAI,KAAK,aAAa;AACpB,WAAK,OAAO,KAAK,+EAAyE;AAC1F,UAAI;AACF,aAAK,GAAG,MAAM,KAAM,mBAAmB;AAAA,MACzC,QAAQ;AAAA,MAER;AACA;AAAA,IACF;AAEA,SAAK,sBAAsB,KAAK,IAAI;AACpC,SAAK,UAAU,aAAa,EAAE,GAAG,KAAK,gBAAgB,OAAU,CAAC;AACjE,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA,EAIQ,UAAU,IAAkB,GAAkB;AACpD,UAAM,KAAK,KAAK;AAChB,QAAI,CAAC,IAAI;AACP,WAAK,OAAO,MAAM,gCAAgC,EAAE,GAAG,CAAC;AACxD;AAAA,IACF;AACA,UAAM,UAAU,KAAK,UAAU,EAAE,IAAI,GAAG,WAAW,aAAa,EAAE,CAAC;AACnE,QAAI,OAAO,WAAW,SAAS,MAAM,IAAI,OAAQ;AAC/C,WAAK;AAAA,QACH;AAAA,QACA,IAAI,aAAa,MAAM,MAAM,SAAS,EAAE,0CAAuC;AAAA,MACjF;AACA;AAAA,IACF;AACA,QAAI;AACF,SAAG,KAAK,OAAO;AAAA,IACjB,SAAS,KAAK;AACZ,WAAK;AAAA,QACH;AAAA,QACA,IAAI,aAAa,MAAM,MAAM,yBAAyB,EAAE,KAAK,OAAQ,KAAe,WAAW,GAAG,CAAC,EAAE;AAAA,MACvG;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,UAAU,QAA6B;AAC7C,QAAI,KAAK,gBAAgB,OAAQ;AACjC,SAAK,cAAc;AACnB,SAAK,KAAK,gBAAgB,MAAM;AAAA,EAClC;AACF;AAEA,SAAS,cAAc,MAAc,QAAgB,OAAgB,QAAyB;AAC5F,MAAI,OAAO;AACT,QAAI,SAAS,kBAAkB,sBAAsB;AACnD,aAAO,6BAA6B,SAAS,KAAK,MAAM,KAAK,EAAE;AAAA,IACjE;AACA,QAAI,SAAS,kBAAkB,iBAAiB;AAC9C,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACA,MAAI,QAAQ;AACV,WAAO,uCAAoC,IAAI,GAAG,SAAS,KAAK,MAAM,KAAK,EAAE;AAAA,EAC/E;AACA,SAAO,2CAAqC,IAAI,GAAG,SAAS,KAAK,MAAM,KAAK,EAAE;AAChF;;;AC1oBO,IAAM,YAAN,MAAgB;AAAA,EACrB,YACqB,QAEV,KACT;AAHmB;AAEV;AAAA,EACR;AAAA,EAHkB;AAAA,EAEV;AAEb;;;AChCO,IAAM,cAAc;AAAA,EACzB,cAAc,MAAM;AAAA,EACpB,iBAAiB,MAAM;AAAA,EACvB,cAAc,MAAM;AAAA,EACpB,cAAc,MAAM;AAAA,EACpB,gBAAgB,MAAM;AAAA,EACtB,gBAAgB,MAAM;AAAA,EACtB,eAAe,MAAM;AAAA,EACrB,iBAAiB,MAAM;AAAA,EACvB,cAAc,MAAM;AAAA,EACpB,aAAa,MAAM;AAAA,EACnB,iBAAiB,MAAM;AAAA,EACvB,iBAAiB,MAAM;AAAA,EACvB,kBAAkB,MAAM;AAAA,EACxB,eAAe,MAAM;AAAA,EACrB,sBAAsB,MAAM;AAAA,EAC5B,iBAAiB,MAAM;AAAA,EACvB,cAAc,MAAM;AAAA,EACpB,aAAa,MAAM;AAAA,EACnB,eAAe,MAAM;AAAA,EACrB,kBAAkB,MAAM;AAAA,EACxB,qBAAqB,MAAM;AAAA,EAC3B,cAAc,MAAM;AAAA,EACpB,SAAS,MAAM;AAAA,EACf,OAAO,MAAM;AAAA,EACb,OAAO,MAAM;AAAA,EACb,QAAQ,MAAM;AAAA,EACd,cAAc,MAAM;AAAA,EACpB,gBAAgB,MAAM;AAAA,EACtB,cAAc,MAAM;AAAA,EACpB,kBAAkB,MAAM;AAAA,EACxB,eAAe,MAAM;AAAA,EACrB,YAAY,MAAM;AAAA;AAAA,EAElB,eAAe,MAAM;AAAA,EACrB,uBAAuB,MAAM;AAAA,EAC7B,kBAAkB,MAAM;AAAA,EACxB,gBAAgB,MAAM;AAAA,EACtB,uBAAuB,MAAM;AAAA,EAC7B,iBAAiB,MAAM;AAAA,EACvB,gBAAgB,MAAM;AAAA,EACtB,0BAA0B,MAAM;AAAA,EAChC,gBAAgB,MAAM;AAAA,EACtB,eAAe,MAAM;AACvB;AAKO,IAAM,kBAA0B,OAAO,OAAO,WAAW,EAAE,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE;AAGrF,SAAS,oBAAoB,MAA8B;AAChE,SAAO,KAAK,SAAS;AACvB;AAGO,SAAS,iBAAiB,OAAwC;AACvE,SAAO,OAAO,KAAK;AACrB;AAGO,SAAS,eACd,SACG,OACM;AACT,QAAM,IAAI,OAAO,SAAS,WAAW,OAAO,IAAI,IAAI;AACpD,SAAO,MAAM,MAAM,CAAC,UAAU,IAAI,UAAU,IAAI;AAClD;AAGO,SAAS,iBACd,SACG,OACM;AACT,QAAM,IAAI,OAAO,SAAS,WAAW,OAAO,IAAI,IAAI;AACpD,SAAO,MAAM,KAAK,CAAC,UAAU,IAAI,UAAU,IAAI;AACjD;AAWO,SAAS,0BAA0B,SAa/B;AACT,MAAI,OAAO,QAAQ;AACnB,aAAW,QAAQ,QAAQ,gBAAiB,SAAQ;AAEpD,OAAK,OAAO,YAAY,mBAAmB,YAAY,eAAe;AACpE,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,CAAC,KAAa,eAA8C;AACxE,UAAM,WAAW,WAAW,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ,cAAc;AAC7E,QAAI,UAAU;AACZ,aAAO,CAAC,OAAO,SAAS,IAAI;AAC5B,aAAO,OAAO,SAAS,KAAK;AAAA,IAC9B;AACA,UAAM,iBAAiB,WAAW;AAAA,MAChC,CAAC,MAAM,EAAE,eAAe,UAAU,QAAQ,cAAc,SAAS,EAAE,QAAQ;AAAA,IAC7E;AACA,UAAM,OAAO,eAAe,OAAO,CAAC,MAAM,MAAM,OAAO,OAAO,EAAE,IAAI,GAAG,EAAE;AACzE,UAAM,QAAQ,eAAe,OAAO,CAAC,MAAM,MAAM,OAAO,OAAO,EAAE,KAAK,GAAG,EAAE;AAC3E,WAAO,CAAC;AACR,WAAO;AACP,UAAM,SAAS,WAAW,KAAK,CAAC,MAAM,EAAE,eAAe,YAAY,EAAE,aAAa,QAAQ,QAAQ;AAClG,QAAI,QAAQ;AACV,aAAO,CAAC,OAAO,OAAO,IAAI;AAC1B,aAAO,OAAO,OAAO,KAAK;AAAA,IAC5B;AACA,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,MAAM,MAAM,QAAQ,UAAU;AAC3C,OAAK,SAAS,YAAY,kBAAkB,YAAY,aAAc,QAAO;AAC7E,SAAO;AACT;AAMO,IAAM,iCACX,YAAY,eACZ,YAAY,gBACZ,YAAY,uBACZ,YAAY,cACZ,YAAY,eACZ,YAAY;AAGP,IAAM,mCACX,YAAY,eACZ,YAAY,cACZ,YAAY,kBACZ,YAAY;;;ACrJP,IAAM,YAAY;AAAA,EACvB,OAAO,KAAK;AAAA,EACZ,iBAAiB,KAAK;AAAA,EACtB,cAAc,KAAK;AAAA,EACnB,QAAQ,KAAK;AAAA,EACb,UAAU,KAAK;AAAA,EACf,KAAK,KAAK;AACZ;AAyDO,IAAM,aAAa;AAAA,EACxB,UAAU,KAAK;AAAA,EACf,SAAS,KAAK;AAAA,EACd,mBAAmB,KAAK;AAAA,EACxB,UAAU,KAAK;AAAA,EACf,sBAAsB,KAAK;AAC7B;AAmsBO,SAAS,YAAY,IAAuB;AACjD,SAAO,KAAK,EAAE;AAChB;AAGO,SAAS,YAAY,IAAuB;AACjD,SAAO,MAAM,EAAE;AACjB;AAGO,SAAS,eAAe,IAAuB;AACpD,SAAO,KAAK,EAAE;AAChB;;;ACpxBO,IAAM,OAAN,cAAmB,UAAU;AAAA,EAClC,YAAY,QAAoB,KAAc;AAC5C,UAAM,QAAQ,GAAyC;AAAA,EACzD;AAAA,EAEA,IAAI,OAAgB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAgB;AAClB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,WAAmB;AACrB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,cAAsB;AACxB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,YAA2B;AAC7B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,QAAiB;AACnB,YAAQ,KAAK,KAAK,QAAQ,UAAU,SAAS;AAAA,EAC/C;AAAA;AAAA,EAEA,IAAI,gBAAyB;AAC3B,YAAQ,KAAK,KAAK,QAAQ,UAAU,kBAAkB;AAAA,EACxD;AAAA,EACA,IAAI,UAAmB;AACrB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,YAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAGA,IAAI,UAAkB;AACpB,WAAO,KAAK,KAAK,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAO,SAA4C;AACjD,WAAO,KAAK,OAAO,QAChB,MAAM,SAAS,KAAK,EAAE,EACtB,KAAK,CAAC,MAAM,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC,EACtC,MAAM,MAAM,IAAI;AAAA,EACrB;AACF;AAGO,IAAM,SAAN,MAAM,gBAAe,UAAU;AAAA,EACpC,YAAY,QAAoB,KAAgB;AAC9C,UAAM,QAAQ,GAAyC;AAAA,EACzD;AAAA,EAEA,IAAI,OAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,KAAgB;AAClB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,SAAoB;AACtB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,OAAa;AACf,WAAO,IAAI,KAAK,KAAK,QAAQ,KAAK,KAAK,IAAI;AAAA,EAC7C;AAAA,EACA,IAAI,WAA0B;AAC5B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,cAAsB;AACxB,WAAO,KAAK,KAAK,YAAY,KAAK,KAAK,KAAK;AAAA,EAC9C;AAAA,EACA,IAAI,UAAuB;AACzB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,WAAoB;AACtB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,eAA+B;AACjC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,aAAsB;AACxB,WAAO,KAAK,iBAAiB,QAAQ,KAAK,MAAM,KAAK,YAAY,IAAI,KAAK,IAAI;AAAA,EAChF;AAAA,EACA,IAAI,QAAiB;AACnB,WAAO,KAAK,KAAK,SAAS;AAAA,EAC5B;AAAA,EACA,IAAI,UAAkB;AACpB,WAAO,KAAK,KAAK,MAAM;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,sBAA8B;AAChC,WAAO,MAAM,KAAK,MAAM;AAAA,EAC1B;AAAA;AAAA,EAGA,QAAyB;AACvB,WAAO,KAAK,OAAO,QAChB,MAAM,KAAK,SAAS,KAAK,MAAM,EAC/B,KAAK,CAAC,MAAM,IAAI,QAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC3C;AAAA;AAAA,EAGA,aAA8B;AAC5B,WAAO,KAAK,OAAO,MAChB,KAAK,KAAK,OAAO,EACjB;AAAA,MAAK,CAAC,UACL,MACG,OAAO,CAAC,MAAM,KAAK,QAAQ,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,EAClE,IAAI,CAAC,MAAM,IAAI,KAAK,KAAK,QAAQ,CAAC,CAAC;AAAA,IACxC;AAAA,EACJ;AAAA;AAAA,EAGA,QAAQ,QAAkC;AACxC,WAAO,KAAK,OAAO,QAAQ,QAAQ,KAAK,SAAS,KAAK,QAAQ,MAAM;AAAA,EACtE;AAAA;AAAA,EAGA,WAAW,QAAkC;AAC3C,WAAO,KAAK,OAAO,QAAQ,WAAW,KAAK,SAAS,KAAK,QAAQ,MAAM;AAAA,EACzE;AAAA;AAAA,EAGA,YAAY,UAA0C;AACpD,WAAO,KAAK,OAAO,QAChB,KAAK,KAAK,SAAS,KAAK,QAAQ,EAAE,SAAS,CAAC,EAC5C,KAAK,CAAC,MAAM,IAAI,QAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC3C;AAAA;AAAA,EAGA,QAAQ,OAAwC;AAC9C,UAAM,MAAM,iBAAiB,OAAO,MAAM,YAAY,IAAI;AAC1D,WAAO,KAAK,OAAO,QAChB,KAAK,KAAK,SAAS,KAAK,QAAQ,EAAE,cAAc,IAAI,CAAC,EACrD,KAAK,CAAC,MAAM,IAAI,QAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC3C;AAAA;AAAA,EAGA,gBAAiC;AAC/B,WAAO,KAAK,OAAO,QAChB,KAAK,KAAK,SAAS,KAAK,QAAQ,EAAE,cAAc,KAAK,CAAC,EACtD,KAAK,CAAC,MAAM,IAAI,QAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC3C;AAAA;AAAA,EAGA,KAAK,QAAgC;AACnC,WAAO,KAAK,OAAO,QAAQ,KAAK,KAAK,SAAS,KAAK,QAAQ,MAAM;AAAA,EACnE;AAAA;AAAA,EAGA,IAAI,UAA8D,CAAC,GAAkB;AACnF,WAAO,KAAK,OAAO,WAChB,IAAI,KAAK,SAAS,KAAK,QAAQ,OAAO,EACtC,KAAK,MAAM,MAAS;AAAA,EACzB;AACF;AAGO,IAAM,OAAN,cAAmB,UAAU;AAAA,EAClC,YAAY,QAAoB,KAAc;AAC5C,UAAM,QAAQ,GAAyC;AAAA,EACzD;AAAA,EAEA,IAAI,OAAgB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAgB;AAClB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,OAAe;AACjB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,QAAuB;AACzB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,WAAmB;AACrB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,cAAsB;AACxB,WAAO,iBAAiB,KAAK,KAAK,WAAW;AAAA,EAC/C;AAAA;AAAA,EAEA,OAAO,OAA0B;AAC/B,WAAO,eAAe,KAAK,aAAa,GAAG,KAAK;AAAA,EAClD;AAAA,EACA,IAAI,UAAmB;AACrB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,cAA6B;AAC/B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,cAAuB;AACzB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,MAAM,KAAK,EAAE;AAAA,EACtB;AAAA;AAAA,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK,OAAO,KAAK;AAAA,EAC1B;AACF;AAGO,IAAM,QAAN,MAAM,eAAc,UAAU;AAAA,EACnC,YAAY,QAAoB,KAAe;AAC7C,UAAM,QAAQ,GAAyC;AAAA,EACzD;AAAA,EAEA,IAAI,OAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAgB;AAClB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,OAAe;AACjB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,OAAe;AACjB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,cAAsB;AACxB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAyB;AAC3B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,aAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAGA,IAAI,OAA6F;AAC/F,UAAM,OAAO,KAAK,KAAK;AACvB,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,SAAS,KAAK;AAAA,MACd,aAAa,iBAAiB,KAAK,WAAW;AAAA,MAC9C,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAAA;AAAA,EAGA,UAAU,OAA0B;AAClC,WAAO,eAAe,KAAK,KAAK,aAAa,GAAG,KAAK;AAAA,EACvD;AAAA;AAAA,EAGA,QAAwB;AACtB,WAAO,KAAK,OAAO,OAChB,MAAM,KAAK,EAAE,EACb,KAAK,CAAC,MAAM,IAAI,OAAM,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC1C;AAAA;AAAA,EAGA,mBAAgD;AAC9C,WAAO,KAAK,OAAO,SAChB,UAAU,KAAK,EAAE,EACjB;AAAA,MAAK,CAAC,UACL,MAAM,IAAI,CAAC,UAAU;AAAA,QACnB,UAAU,KAAK,WAAW,IAAI,QAAQ,KAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,QACpE,UAAU,KAAK,SAAS,IAAI,CAAC,MAAM,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,MAChE,EAAE;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA,EAGA,aAA8B;AAC5B,WAAO,KAAK,OAAO,MAChB,KAAK,KAAK,EAAE,EACZ,KAAK,CAAC,UAAU,MAAM,IAAI,CAAC,MAAM,IAAI,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC;AAAA,EAC/D;AAAA;AAAA,EAGA,YAAY,QAAoC;AAC9C,WAAO,KAAK,OAAO,QAChB,MAAM,KAAK,IAAI,MAAM,EACrB,KAAK,CAAC,MAAM,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC3C;AACF;;;AC3SO,IAAM,UAAN,MAAM,iBAAgB,UAAU;AAAA,EACrC,YAAY,QAAoB,KAAiB;AAC/C,UAAM,QAAQ,GAAyC;AAAA,EACzD;AAAA,EAEA,IAAI,OAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAgB;AAClB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAA4B;AAC9B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,YAAuB;AACzB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,WAAsB;AACxB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,SAAe;AACjB,WAAO,IAAI,KAAK,KAAK,QAAQ,KAAK,KAAK,MAAM;AAAA,EAC/C;AAAA,EACA,IAAI,OAAoB;AACtB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAkB;AACpB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,YAA8B;AAChC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,SAAkB;AACpB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,WAA2B;AAC7B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,YAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,cAAyC;AAC3C,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,SAA+B;AACjC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,aAAuC;AACzC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,YAA2B;AAC7B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,YAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,iBAAgC;AAClC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,oBAA4B;AAC9B,WAAO,KAAK,KAAK,kBAAkB,KAAK,KAAK,OAAO;AAAA,EACtD;AAAA;AAAA,EAGA,IAAI,SAAkB;AACpB,WAAO,KAAK,OAAO,WAAW,QAAQ,KAAK,aAAa,KAAK,OAAO;AAAA,EACtE;AAAA;AAAA,EAGA,IAAI,aAAsB;AACxB,WAAO,KAAK,OAAO,WAAW,QAAQ,KAAK,KAAK,SAAS,QAAQ,SAAS,KAAK,OAAO,MAAM;AAAA,EAC9F;AAAA;AAAA,EAGA,IAAI,mBAAgC;AAClC,WAAO,KAAK,KAAK,SAAS;AAAA,EAC5B;AAAA,EACA,IAAI,mBAAgC;AAClC,WAAO,KAAK,KAAK,SAAS;AAAA,EAC5B;AAAA,EACA,IAAI,mBAA4B;AAC9B,WAAO,KAAK,KAAK,SAAS;AAAA,EAC5B;AAAA;AAAA,EAGA,QAA0B;AACxB,WAAO,KAAK,OAAO,SAChB,MAAM,KAAK,WAAW,KAAK,EAAE,EAC7B,KAAK,CAAC,MAAM,IAAI,SAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,eAAiD;AAC/C,WAAO,KAAK,OAAO,SAChB,MAAM,KAAK,SAAS,EACpB;AAAA,MAAK,CAAC,YACL,QAAQ,SAAS,WACb,IAAI,OAAO,KAAK,QAAQ,OAAgB,IACxC,IAAI,QAAQ,KAAK,QAAQ,OAAO;AAAA,IACtC,EACC,MAAM,MAAM,IAAI;AAAA,EACrB;AAAA;AAAA,EAGA,MAAM,SAA6B,SAAsE;AACvG,UAAM,SAAS,OAAO,YAAY,WAAW,EAAE,SAAS,QAAQ,IAAI;AACpE,WAAO,KAAK,OAAO,SAChB,KAAK,KAAK,WAAW,EAAE,GAAG,QAAQ,WAAW,KAAK,GAAG,GAAG,OAAO,EAC/D,KAAK,CAAC,MAAM,IAAI,SAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,KAAK,SAA6B,SAAsD;AACtF,WAAO,KAAK,OAAO,SAChB,KAAK,KAAK,WAAW,KAAK,IAAI,SAAS,OAAO,EAC9C,KAAK,CAAC,MAAM,IAAI,SAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,OAAO,SAAmD;AACxD,WAAO,KAAK,OAAO,SAAS,OAAO,KAAK,WAAW,KAAK,IAAI,OAAO;AAAA,EACrE;AAAA;AAAA,EAGA,MAAM,OAAe,SAAmD;AACtE,WAAO,KAAK,OAAO,SAAS,MAAM,KAAK,WAAW,KAAK,IAAI,OAAO,OAAO;AAAA,EAC3E;AAAA;AAAA,EAGA,eAAe,OAAe,SAAmD;AAC/E,WAAO,KAAK,OAAO,SAAS,eAAe,KAAK,WAAW,KAAK,IAAI,OAAO,OAAO;AAAA,EACpF;AAAA;AAAA,EAGA,IAAI,SAAmD;AACrD,WAAO,KAAK,OAAO,SAAS,IAAI,KAAK,WAAW,KAAK,IAAI,OAAO;AAAA,EAClE;AAAA;AAAA,EAGA,MAAM,SAAmD;AACvD,WAAO,KAAK,OAAO,SAAS,MAAM,KAAK,WAAW,KAAK,IAAI,OAAO;AAAA,EACpE;AAAA;AAAA,EAGA,YAAY,MAAwF;AAClG,WAAO,KAAK,OAAO,SAChB,wBAAwB,KAAK,WAAW,KAAK,IAAI,IAAI,EACrD,KAAK,CAAC,MAAM,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC3C;AACF;;;ACpJO,IAAM,UAAN,MAAM,iBAAgB,UAAU;AAAA,EACrC,YAAY,QAAoB,KAAiB;AAC/C,UAAM,QAAQ,GAAyC;AAAA,EACzD;AAAA,EAEA,IAAI,OAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAgB;AAClB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,OAAe;AACjB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,OAAoB;AACtB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,QAAuB;AACzB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,aAA+B;AACjC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,YAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,mBAA2B;AAC7B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,cAAuB;AACzB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,gBAAkC;AACpC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,KAAK,KAAK,EAAE;AAAA,EACrB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS;AAAA,EACzD;AAAA,EACA,IAAI,UAAmB;AACrB,WAAO,KAAK,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS;AAAA,EAC1D;AAAA,EACA,IAAI,UAAmB;AACrB,WAAO,KAAK,KAAK,SAAS;AAAA,EAC5B;AAAA;AAAA,EAGA,QAA0B;AACxB,WAAO,KAAK,OAAO,SAChB,MAAM,KAAK,EAAE,EACb,KAAK,CAAC,MAAM,IAAI,SAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,KAAK,SAA6B,SAAsE;AACtG,WAAO,KAAK,OAAO,SAChB,KAAK,KAAK,IAAI,SAAS,OAAO,EAC9B,KAAK,CAAC,MAAM,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,SACE,SACA,SACkB;AAClB,WAAO,KAAK,OAAO,QAChB,oBAAoB,EAAE,SAAS,KAAK,SAAS,GAAG,QAAQ,CAAC,EACzD;AAAA,MAAK,CAAC,iBACL,KAAK,KAAK;AAAA,QACR,SAAS,WAAW;AAAA,QACpB,eAAe,CAAC,YAAY;AAAA,MAC9B,CAAC;AAAA,IACH;AAAA,EACJ;AAAA;AAAA,EAGA,aAAa,WAAwC;AACnD,WAAO,KAAK,OAAO,SAChB,MAAM,KAAK,IAAI,SAAS,EACxB,KAAK,CAAC,MAAM,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,cAAc,QAAqK;AACjL,WAAO,KAAK,OAAO,SAChB,KAAK,KAAK,IAAI,UAAU,CAAC,CAAC,EAC1B,KAAK,CAAC,UAAU;AAAA,MACf,GAAG;AAAA,MACH,OAAO,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,IAC1D,EAAE;AAAA,EACN;AAAA;AAAA,EAGA,YAAgC;AAC9B,WAAO,KAAK,OAAO,SAChB,SAAS,KAAK,EAAE,EAChB,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,MAAM,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC;AAAA,EAChE;AAAA;AAAA,EAGA,aAAa,MAA4C;AACvD,WAAO,KAAK,OAAO,SAChB,aAAa,KAAK,IAAI,IAAI,EAC1B,KAAK,CAAC,MAAM,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC3C;AAAA;AAAA,EAGA,aAAa,QAAyK;AACpL,WAAO,KAAK,OAAO,SAChB,YAAY,KAAK,IAAI,EAAE,OAAO,QAAQ,OAAO,OAAO,QAAQ,QAAQ,UAAU,QAAQ,UAAU,OAAO,QAAQ,MAAM,CAAC,EACtH,KAAK,CAAC,UAAU;AAAA,MACf,GAAG;AAAA,MACH,OAAO,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,IACzD,EAAE;AAAA,EACN;AACF;AAGO,IAAM,SAAN,cAAqB,UAAU;AAAA,EACpC,YAAY,QAAoB,KAAgB;AAC9C,UAAM,QAAQ,GAAyC;AAAA,EACzD;AAAA,EAEA,IAAI,OAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAgB;AAClB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,WAAsB;AACxB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,OAAe;AACjB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,cAAuB;AACzB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,WAAoB;AACtB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,SAAkB;AACpB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,qBAA+C;AACjD,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,eAAuB;AACzB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,gBAAkC;AACpC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,gBAAyB;AAC3B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,gBAA6B;AAC/B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAkB;AACpB,WAAO,KAAK,KAAK,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,KAAK,SAA6B,SAAsE;AACtG,WAAO,KAAK,OAAO,SAChB,KAAK,KAAK,IAAI,SAAS,OAAO,EAC9B,KAAK,CAAC,MAAM,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,aAAa,WAAwC;AACnD,WAAO,KAAK,OAAO,SAChB,MAAM,KAAK,IAAI,SAAS,EACxB,KAAK,CAAC,MAAkB,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,EACxD;AACF;;;AChMO,IAAM,cAAN,cAA0B,UAAU;AAAA,EACzC,YAAY,QAAoB,KAAqB;AACnD,UAAM,QAAQ,GAAyC;AAAA,EACzD;AAAA,EAEA,IAAI,OAAuB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAa;AACf,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,QAAgB;AAClB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,OAAgC;AAClC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,UAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACA,IAAI,YAAuB;AACzB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAEA,IAAI,OAAa;AACf,WAAO,IAAI,KAAK,KAAK,QAAQ,KAAK,KAAK,IAAI;AAAA,EAC7C;AAAA;AAAA,EAGA,IAAI,SAAwB;AAC1B,WAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,QAAQ,KAAK,KAAK,MAAM,IAAI;AAAA,EACxE;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EAEA,IAAI,YAAqB;AACvB,WAAO,KAAK,KAAK,SAAS,aAAa,KAAK,KAAK,YAAY;AAAA,EAC/D;AAAA,EACA,IAAI,cAAuB;AACzB,WAAO,KAAK,KAAK,SAAS,eAAe,KAAK,KAAK,cAAc;AAAA,EACnE;AAAA;AAAA,EAGA,IAAI,UAA4C;AAC9C,WAAO,KAAK,KAAK,WAAW;AAAA,EAC9B;AAAA;AAAA,EAGA,IAAI,YAAgD;AAClD,WAAO,KAAK,KAAK,aAAa;AAAA,EAChC;AAAA;AAAA,EAGA,IAAI,WAA0B;AAC5B,WAAO,KAAK,WAAW,YAAY;AAAA,EACrC;AAAA;AAAA,EAGA,IAAI,SAAmB;AACrB,WAAO,KAAK,WAAW,UAAU,CAAC;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,UAA8F;AAChG,WAAO,KAAK,SAAS,WAAW,CAAC;AAAA,EACnC;AAAA;AAAA,EAGA,UAAU,MAAqD;AAC7D,WAAO,KAAK,QAAQ,KAAK,CAAC,WAAW,OAAO,SAAS,IAAI,GAAG;AAAA,EAC9D;AAAA;AAAA,EAGA,UAAU,MAAc,WAAW,OAA2B;AAC5D,UAAM,QAAQ,KAAK,UAAU,IAAI;AACjC,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAI,SAAU,OAAM,IAAI,MAAM,iCAAwB,IAAI,2BAAwB;AAClF,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,WAAW,MAAc,WAAW,OAA2B;AAC7D,UAAM,QAAQ,KAAK,UAAU,IAAI;AACjC,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAI,SAAU,OAAM,IAAI,MAAM,iCAAwB,IAAI,4BAAyB;AACnF,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,WAAW,MAAc,WAAW,OAA4B;AAC9D,UAAM,QAAQ,KAAK,UAAU,IAAI;AACjC,QAAI,OAAO,UAAU,UAAW,QAAO;AACvC,QAAI,SAAU,OAAM,IAAI,MAAM,iCAAwB,IAAI,4BAAyB;AACnF,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,MAAc,WAAW,OAA8B;AAC3D,UAAM,QAAQ,KAAK,UAAU,IAAI;AACjC,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAI,SAAU,OAAM,IAAI,MAAM,iCAAwB,IAAI,sCAAmC;AAC7F,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MACE,SACA,UAAyD,CAAC,GAC3C;AACf,WAAO,KAAK,OAAO,aAAa,MAAM,KAAK,IAAI,KAAK,OAAO,SAAS,OAAO;AAAA,EAC7E;AAAA;AAAA,EAGA,eAAe,SAA6B,SAAmD;AAC7F,WAAO,KAAK,OAAO,aAAa,MAAM,KAAK,IAAI,KAAK,OAAO,SAAS;AAAA,MAClE,GAAG;AAAA,MACH,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,SAAmD;AACvD,WAAO,KAAK,OAAO,aAAa,MAAM,KAAK,IAAI,KAAK,OAAO,OAAO;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,SAA6B,SAAmD;AACrF,WAAO,KAAK,OAAO,aAAa,OAAO,KAAK,IAAI,KAAK,OAAO,SAAS,OAAO;AAAA,EAC9E;AAAA;AAAA,EAGA,YAAY,SAAmD;AAC7D,WAAO,KAAK,OAAO,aAAa,qBAAqB,KAAK,IAAI,KAAK,OAAO,OAAO;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SACE,SACA,UAAyD,CAAC,GAC3C;AACf,UAAM,SAAS,OAAO,YAAY,WAAW,EAAE,SAAS,QAAQ,IAAI;AACpE,QAAI,QAAQ,UAAW,CAAC,OAAmC,YAAY;AACvE,WAAO,KAAK,OAAO,aAAa;AAAA,MAC9B,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA,EAGA,wBAAiD;AAC/C,UAAM,YAAY,KAAK,WAAW;AAClC,QAAI,CAAC,UAAW,QAAO,QAAQ,QAAQ,IAAI;AAC3C,WAAO,KAAK,OAAO,SAChB,MAAM,KAAK,WAAW,SAAS,EAC/B,KAAK,CAAC,MAAM,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC,EACvC,MAAM,MAAM,IAAI;AAAA,EACrB;AACF;;;AC/LA,IAAM,eAAe;AACrB,IAAM,eAAe;AAGd,SAAS,iBAAiB,IAAqB;AACpD,SAAO,OAAO,OAAO,aAAa,aAAa,KAAK,EAAE,KAAK,aAAa,KAAK,EAAE;AACjF;AAGO,SAAS,gBAAgB,IAAY,QAAQ,MAAc;AAChE,MAAI,CAAC,iBAAiB,EAAE,GAAG;AACzB,UAAM,IAAI;AAAA,MACR,GAAG,KAAK,iBAAc,KAAK,UAAU,EAAE,CAAC;AAAA,IAC1C;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,kBAAkB,GAAW,GAAmB;AAC9D,MAAI,CAAC,aAAa,KAAK,CAAC,KAAK,CAAC,aAAa,KAAK,CAAC,GAAG;AAClD,WAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,EAClC;AACA,MAAI;AACF,UAAM,KAAK,OAAO,CAAC;AACnB,UAAM,KAAK,OAAO,CAAC;AACnB,WAAO,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI;AAAA,EACtC,QAAQ;AACN,WAAO,EAAE,cAAc,CAAC;AAAA,EAC1B;AACF;;;AChBO,IAAM,QAAN,MAAkB;AAAA,EACN,QAAQ,oBAAI,IAAiB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,UAAwB,CAAC,GAAG;AACtC,SAAK,QAAQ,QAAQ,SAAS;AAC9B,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,MAAM,QAAQ,QAAQ,MAAM,KAAK,IAAI;AAAA,EAC5C;AAAA,EAEA,IAAI,KAAuB;AACzB,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,KAAK,IAAI,KAAK,MAAM,WAAW;AACjC,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACT;AAEA,SAAK,MAAM,OAAO,GAAG;AACrB,SAAK,MAAM,IAAI,KAAK,KAAK;AACzB,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,IAAI,KAAQ,OAAU,OAAsB;AAC1C,QAAI,KAAK,WAAW,EAAG;AACvB,UAAM,MAAM,SAAS,KAAK;AAC1B,SAAK,MAAM,OAAO,GAAG;AACrB,SAAK,MAAM,IAAI,KAAK,EAAE,OAAO,WAAW,QAAQ,WAAW,OAAO,mBAAmB,KAAK,IAAI,IAAI,KAAK,YAAY,KAAK,IAAI,EAAE,CAAC;AAC/H,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,IAAI,KAAiB;AACnB,WAAO,KAAK,IAAI,GAAG,MAAM,UAAa,KAAK,KAAK,GAAG,MAAM;AAAA,EAC3D;AAAA,EAEA,OAAO,KAAiB;AACtB,WAAO,KAAK,MAAM,OAAO,GAAG;AAAA,EAC9B;AAAA,EAEA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA,EAEA,IAAI,OAAe;AACjB,SAAK,MAAM;AACX,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA,EAGA,CAAC,UAAoC;AACnC,eAAW,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,KAAK,MAAM,QAAQ,CAAC,GAAG;AACpD,UAAI,KAAK,IAAI,IAAI,MAAM,UAAW,OAAM,CAAC,KAAK,MAAM,KAAK;AAAA,UACpD,MAAK,MAAM,OAAO,GAAG;AAAA,IAC5B;AAAA,EACF;AAAA,EAEQ,KAAK,KAAuB;AAClC,WAAO,KAAK,MAAM,IAAI,GAAG,GAAG;AAAA,EAC9B;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,MAAM,QAAQ,KAAK,QAAS;AAErC,UAAM,SAAS,KAAK,MAAM,OAAO,KAAK;AACtC,UAAM,WAAW,KAAK,MAAM,KAAK;AACjC,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,YAAM,SAAS,SAAS,KAAK;AAC7B,UAAI,OAAO,KAAM;AACjB,WAAK,MAAM,OAAO,OAAO,KAAK;AAAA,IAChC;AAAA,EACF;AAAA,EAEQ,QAAc;AACpB,UAAM,MAAM,KAAK,IAAI;AACrB,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,MAAM,QAAQ,GAAG;AAC/C,UAAI,OAAO,MAAM,UAAW,MAAK,MAAM,OAAO,GAAG;AAAA,IACnD;AAAA,EACF;AACF;;;ACZO,IAAM,eAAN,cAA2B,aAA2B;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EAOQ;AAAA,EACT,kBAAkC;AAAA,EAClC,UAAyB;AAAA,EACzB,cAAgC;AAAA,EAChC,uBAAuB;AAAA,EACvB,YAAY;AAAA,EAEpB,YAAY,SAAwB;AAClC,UAAM;AACN,QAAI,CAAC,SAAS,SAAS,OAAO,QAAQ,UAAU,UAAU;AACxD,YAAM,IAAI,gBAAgB,mFAAmF;AAAA,IAC/G;AACA,UAAM,QAAQ,iBAAiB,QAAQ,KAAK;AAC5C,QAAI,CAAC,WAAW,KAAK,GAAG;AACtB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,SAAK,UAAU,EAAE,GAAG,SAAS,MAAM;AAEnC,SAAK,SACH,QAAQ,WAAW,UAAa,QAAQ,WAAW,OAC/C,QAAQ,SACR,QAAQ,WAAW,OACjB,aACA,QAAQ,WACN,oBAAoB,EAAE,OAAO,QAAQ,SAAS,CAAC,IAC/C,cAAc;AAExB,SAAK,OAAO,IAAI,WAAW;AAAA,MACzB,SAAS,QAAQ;AAAA,MACjB;AAAA,MACA,WAAW,QAAQ;AAAA,MACnB,YAAY,QAAQ;AAAA,MACpB,yBAAyB,QAAQ;AAAA,MACjC,WAAW,QAAQ;AAAA,MACnB,QAAQ,KAAK;AAAA,IACf,CAAC;AAED,SAAK,WAAW,IAAI,gBAAgB,KAAK,IAAI;AAC7C,SAAK,WAAW,IAAI,gBAAgB,KAAK,IAAI;AAC7C,SAAK,SAAS,IAAI,cAAc,KAAK,IAAI;AACzC,SAAK,UAAU,IAAI,eAAe,KAAK,IAAI;AAC3C,SAAK,QAAQ,IAAI,aAAa,KAAK,IAAI;AACvC,SAAK,aAAa,IAAI,kBAAkB,KAAK,IAAI;AACjD,SAAK,UAAU,IAAI,eAAe,KAAK,MAAM,KAAK,MAAM;AACxD,SAAK,eAAe,IAAI,oBAAoB,KAAK,IAAI;AACrD,SAAK,WAAW,IAAI,2BAA2B,KAAK,IAAI;AACxD,SAAK,MAAM,IAAI,WAAW,KAAK,IAAI;AACnC,SAAK,QAAQ,IAAI,aAAa,KAAK,IAAI;AAEvC,UAAM,eAAe,QAAQ,OAAO,UAChC,EAAE,OAAO,QAAQ,MAAM,OAAO,SAAS,QAAQ,MAAM,WAAW,IAChE;AACJ,SAAK,SAAS,eACV;AAAA,MACE,QAAQ,IAAI,MAA2B,YAAY;AAAA,MACnD,UAAU,IAAI,MAA6B,YAAY;AAAA,MACvD,SAAS,IAAI,MAAyB,YAAY;AAAA,MAClD,OAAO,IAAI,MAA4B,YAAY;AAAA,IACrD,IACA;AAAA,EACN;AAAA;AAAA,EAGA,IAAI,cAA4C;AAC9C,UAAM,EAAE,OAAO,QAAQ,GAAG,KAAK,IAAI,KAAK;AACxC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,IAAI,SAA2B;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,OAAoB;AACtB,WAAO,KAAK,UAAU,IAAI,KAAK,MAAM,KAAK,QAAQ,IAAI,IAAI;AAAA,EAC5D;AAAA;AAAA,EAGA,IAAI,cAA6B;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,UAA0B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,UAAmB;AACjB,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AAAA;AAAA,EAGA,IAAI,OAAsB;AACxB,WAAO,KAAK,iBAAiB,sBAAsB;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAuB;AAC3B,QAAI,KAAK,UAAW,OAAM,IAAI,gBAAgB,4BAAyB;AACvE,QAAI,KAAK,YAAa;AAEtB,SAAK,OAAO,KAAK,wBAAwB;AACzC,SAAK,UAAU,MAAM,KAAK,IAAI,aAAa;AAC3C,SAAK,cAAc,KAAK,QAAQ,KAAK;AACrC,SAAK,OAAO,KAAK,kBAAkB,EAAE,OAAO,KAAK,QAAQ,IAAI,UAAU,KAAK,QAAQ,KAAK,SAAS,CAAC;AAEnG,QAAI,KAAK,QAAQ,UAAU;AACzB,WAAK,OAAO,KAAK,6BAA6B;AAC9C,WAAK,KAAK,SAAS;AAAA,QACjB,MAAM,IAAI,KAAK,MAAM,KAAK,QAAQ,IAAI;AAAA,QACtC,WAAW;AAAA,QACX,QAAQ,CAAC;AAAA,QACT,MAAM;AAAA,MACR,CAAC;AACD;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ,oBAAoB,CAAC,KAAK,sBAAsB;AAC/D,WAAK,uBAAuB;AAC5B,YAAM,WAAW,MAAM;AACrB,aAAK,KAAK,QAAQ,EAAE,KAAK,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,MAChD;AACA,cAAQ,KAAK,UAAU,QAAQ;AAC/B,cAAQ,KAAK,WAAW,QAAQ;AAAA,IAClC;AAEA,UAAM,UAAU,KAAK,cAAc;AACnC,UAAM,QAAQ,MAAM,QAAQ,QAAQ;AAEpC,SAAK,cAAc,MAAM,UAAU,KAAK;AACxC,SAAK,KAAK,SAAS;AAAA,MACjB,MAAM,KAAK,QAAQ,IAAI,KAAK,MAAM,KAAK,QAAS,IAAI;AAAA,MACpD,WAAW,MAAM;AAAA,MACjB,QAAQ,MAAM;AAAA,MACd,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAyB;AAC7B,QAAI,KAAK,UAAW;AACpB,SAAK,YAAY;AACjB,QAAI,KAAK,iBAAiB;AACxB,YAAM,KAAK,gBAAgB,QAAQ;AACnC,WAAK,kBAAkB;AAAA,IACzB;AACA,SAAK,KAAK,QAAQ;AAClB,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA,EAGA,YAAY,UAA0F;AACpG,QAAI,CAAC,KAAK,iBAAiB;AACzB,YAAM,IAAI,gBAAgB,0DAAuD;AAAA,IACnF;AACA,UAAM,SAAgC;AAAA,MACpC,QAAQ,SAAS;AAAA,MACjB,cAAc,SAAS,iBAAiB,SAAY,SAAY,SAAS;AAAA,MACzE,KAAK,SAAS;AAAA,IAChB;AACA,SAAK,gBAAgB,YAAY,MAAM;AAAA,EACzC;AAAA;AAAA,EAGA,YAAkB;AAChB,SAAK,iBAAiB,aAAa;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,gBAAgB,WAAuC;AAC3D,oBAAgB,WAAW,WAAW;AACtC,UAAM,UAAU,KAAK,QAAQ,SAAS,IAAI,SAAS,KAAM,MAAM,KAAK,SAAS,MAAM,SAAS;AAC5F,SAAK,QAAQ,SAAS,IAAI,WAAW,OAAO;AAC5C,UAAM,UAAU,QAAQ;AACxB,UAAM,QAAQ,KAAK,QAAQ,OAAO,IAAI,OAAO,KAAM,MAAM,KAAK,OAAO,MAAM,OAAO;AAClF,SAAK,QAAQ,OAAO,IAAI,SAAS,KAAK;AAEtC,UAAM,QAAQ,KAAK,QAAQ,MAAM,IAAI,OAAO,KAAM,MAAM,KAAK,MAAM,KAAK,OAAO;AAC/E,SAAK,QAAQ,MAAM,IAAI,SAAS,KAAK;AAErC,UAAM,YAAY,GAAG,OAAO,IAAI,KAAK,WAAW;AAChD,UAAM,KACJ,KAAK,QAAQ,QAAQ,IAAI,SAAS,KACjC,MAAM,KAAK,QAAQ,MAAM,SAAS,KAAK,WAAY;AACtD,SAAK,QAAQ,QAAQ,IAAI,WAAW,EAAE;AAEtC,UAAM,WAAW,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC7D,UAAM,sBAAsB;AAAA,OACzB,SAAS,IAAI,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO,IAAI,eAAe;AAAA,IACjF;AACA,WAAO,0BAA0B;AAAA,MAC/B;AAAA,MACA,iBAAiB,GAAG,QACjB,IAAI,CAAC,WAAW,SAAS,IAAI,MAAM,CAAC,EACpC,OAAO,CAAC,SAA0B,SAAS,MAAS,EACpD,IAAI,CAAC,SAAS,OAAO,KAAK,WAAW,CAAC;AAAA,MACzC,YAAY,QAAQ;AAAA,MACpB,UAAU,GAAG;AAAA,MACb,gBAAgB;AAAA,MAChB,eAAe,GAAG;AAAA,IACpB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,iBAAiB,cAAyB,OAAmC;AACjF,UAAM,OAAO,MAAM,KAAK,gBAAgB,SAAS;AACjD,WAAO,MAAM,MAAM,CAAC,UAAU,OAAO,UAAU,IAAI;AAAA,EACrD;AAAA;AAAA,EAGA,IAAI,cAAkC;AACpC,WAAO;AAAA,EACT;AAAA;AAAA,EAIQ,gBAAyB;AAC/B,QAAI,KAAK,gBAAiB,QAAO,KAAK;AAEtC,UAAM,UAAU,IAAI,QAAQ;AAAA,MAC1B,KAAK,KAAK,QAAQ;AAAA,MAClB,OAAO,KAAK,QAAQ;AAAA,MACpB,IAAI,KAAK,QAAQ;AAAA,MACjB,QAAQ,KAAK;AAAA,MACb,iBAAiB,KAAK,QAAQ;AAAA,IAChC,CAAC;AAED,YAAQ,GAAG,WAAW,CAAC,YAAY;AACjC,WAAK,KAAK,WAAW,OAAO;AAC5B,WAAK,OAAO,KAAK,sBAAmB,EAAE,UAAU,QAAQ,SAAS,CAAC;AAAA,IACpE,CAAC;AAED,YAAQ,GAAG,gBAAgB,CAAC,SAAS;AACnC,WAAK,KAAK,gBAAgB,IAAI;AAC9B,WAAK,OAAO,KAAK,2BAA2B,IAAI;AAAA,IAClD,CAAC;AAED,YAAQ,GAAG,cAAc,CAAC,SAAS;AACjC,WAAK,KAAK,cAAc,IAAI;AAC5B,UAAI,CAAC,KAAK,MAAO,MAAK,KAAK,QAAQ,yCAAmC,KAAK,IAAI,GAAG;AAAA,IACpF,CAAC;AAED,YAAQ,GAAG,SAAS,CAAC,UAAU;AAC7B,WAAK,KAAK,SAAS,KAAK;AAAA,IAC1B,CAAC;AAED,YAAQ,GAAG,kBAAkB,MAAM;AACjC,WAAK,KAAK,QAAQ,sEAA6D;AAAA,IACjF,CAAC;AAED,YAAQ,GAAG,OAAO,CAAC,UAAuB;AACxC,WAAK,KAAK,OAAO,KAAK;AAAA,IACxB,CAAC;AAED,YAAQ,GAAG,SAAS,CAAC,UAAU;AAC7B,WAAK,qBAAqB,KAAK;AAAA,IACjC,CAAC;AAED,SAAK,kBAAkB;AACvB,WAAO;AAAA,EACT;AAAA,EAEQ,qBAAqB,OAKpB;AACP,UAAM,EAAE,MAAM,EAAE,IAAI;AACpB,UAAM,OAAO;AAEb,QAAI;AACF,cAAQ,MAAM;AAAA,QACZ,KAAK;AAAA,QACL,KAAK;AACH,eAAK,KAAK,MAAM,IAAI,QAAQ,MAAM,KAAK,OAAqB,CAAC;AAC7D;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AACH,eAAK,KAAK,MAAM;AAAA,YACd,SAAS,KAAK;AAAA,YACd,QAAQ,IAAI,OAAO,MAAM,KAAK,MAAmB;AAAA,UACnD,CAAC;AACD;AAAA,QACF,KAAK;AACH,eAAK,KAAK,MAAM,IAAI,MAAM,MAAM,KAAK,KAAiB,CAAC;AACvD;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AACH,eAAK,KAAK,MAAM,IAAI,QAAQ,MAAM,KAAK,OAAqB,CAAC;AAC7D;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AACH,eAAK,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK,IAAe,CAAC;AACpD;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AACH,eAAK,KAAK,MAAM,IAAI,OAAO,MAAM,KAAK,MAAmB,CAAC;AAC1D;AAAA,QACF,KAAK;AACH,eAAK,KAAK,MAAM,IAAI,YAAY,MAAM,CAAU,CAAC;AACjD;AAAA,QACF;AACE,cAAI,KAAK,cAAc,IAA0B,IAAI,GAAG;AAEtD,iBAAK,KAAK,MAA4B,CAAC;AAAA,UACzC,WAAW,iBAAiB,IAAI,GAAG;AACjC,iBAAK,KAAK,MAA4B,CAAC;AAAA,UACzC,OAAO;AACL,iBAAK,KAAK,gBAAgB,KAAK;AAAA,UACjC;AAAA,MACJ;AAAA,IACF,SAAS,KAAK;AACZ,WAAK,KAAK,SAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,IACxE;AAAA,EACF;AACF;AAEA,IAAM,oBAAoB,oBAAI,IAAY;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,iBAAiB,MAAuB;AAC/C,SAAO,kBAAkB,IAAI,IAAI;AACnC;;;ACvXO,IAAM,kBAAN,MAAsB;AAAA,EAQ3B,YACmB,QACA,UAAkC,CAAC,GACpD;AAFiB;AACA;AAEjB,SAAK,iBAAiB,QAAQ,UAAU;AAAA,EAC1C;AAAA,EAJmB;AAAA,EACA;AAAA,EATF,eAAe,oBAAI,IAAmC;AAAA,EACtD,gBAAgB,oBAAI,IAAoC;AAAA,EACxD,oBAAoB,oBAAI,IAAwC;AAAA,EAChE,YAAY,oBAAI,IAAoB;AAAA,EACpC;AAAA,EACT,WAAW;AAAA;AAAA,EAUnB,KAAK,YAAyC;AAC5C,2BAAuB,UAAU;AACjC,UAAM,QAAQ,CAAC,WAAW,MAAM,GAAI,WAAW,WAAW,CAAC,CAAE;AAC7D,eAAW,QAAQ,OAAO;AACxB,YAAM,MAAM,KAAK,YAAY;AAC7B,UAAI,KAAK,aAAa,IAAI,GAAG,GAAG;AAC9B,cAAM,IAAI,gBAAgB,+BAA+B,IAAI,EAAE;AAAA,MACjE;AACA,WAAK,aAAa,IAAI,KAAK,UAAU;AAAA,IACvC;AACA,SAAK,eAAe;AACpB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,YAA0C;AAC9C,QAAI,CAAC,qBAAqB,KAAK,WAAW,IAAI,GAAG;AAC/C,YAAM,IAAI;AAAA,QACR,gCAA6B,WAAW,IAAI;AAAA,MAC9C;AAAA,IACF;AACA,QAAI,KAAK,cAAc,IAAI,WAAW,IAAI,GAAG;AAC3C,YAAM,IAAI,gBAAgB,4BAA4B,WAAW,IAAI,EAAE;AAAA,IACzE;AACA,SAAK,cAAc,IAAI,WAAW,MAAM,UAAU;AAClD,SAAK,eAAe;AACpB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,UAAU,YAA8C;AACtD,QAAI,CAAC,WAAW,SAAU,OAAM,IAAI,gBAAgB,8BAAwB;AAC5E,QAAI,KAAK,kBAAkB,IAAI,WAAW,QAAQ,GAAG;AACnD,YAAM,IAAI,gBAAgB,oCAAoC,WAAW,QAAQ,EAAE;AAAA,IACrF;AACA,SAAK,kBAAkB,IAAI,WAAW,UAAU,UAAU;AAC1D,SAAK,eAAe;AACpB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,gBAAgB,UAAwB;AACtC,SAAK,kBAAkB,OAAO,QAAQ;AACtC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,kBAAqC;AACnC,WAAO,CAAC,GAAG,KAAK,cAAc,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa;AAAA,MACxD,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,SAAS,QAAQ,WAAW,CAAC;AAAA,IAC/B,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAsB;AAC1B,UAAM,SAA4B,CAAC;AACnC,UAAM,aAAa,oBAAI,IAAkC;AAEzD,eAAW,WAAW,KAAK,cAAc,OAAO,GAAG;AACjD,YAAM,QAAyB;AAAA,QAC7B,MAAM,QAAQ;AAAA,QACd,aAAa,QAAQ;AAAA,QACrB,SAAS,QAAQ,WAAW,CAAC;AAAA,MAC/B;AACA,YAAM,QAAQ,QAAQ,SAAS,EAAE,MAAM,SAAkB;AACzD,UAAI,MAAM,SAAS,UAAU;AAC3B,eAAO,KAAK,KAAK;AAAA,MACnB,OAAO;AACL,mBAAW,WAAW,MAAM,UAAU;AACpC,gBAAM,OAAO,WAAW,IAAI,OAAO,KAAK,CAAC;AACzC,eAAK,KAAK,KAAK;AACf,qBAAW,IAAI,SAAS,IAAI;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,KAAK,OAAO,SAAS,UAAU,MAAM;AAAA,IAC7C;AACA,eAAW,CAAC,SAAS,QAAQ,KAAK,YAAY;AAC5C,YAAM,KAAK,OAAO,SAAS,SAAS,SAAS,QAAQ;AAAA,IACvD;AAAA,EACF;AAAA;AAAA,EAGA,iBAAuB;AACrB,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,kBAAkB,SAAoC;AAC1D,UAAM,SAAS,KAAK,cAAc,OAAO;AACzC,QAAI,WAAW,KAAM,QAAO;AAE5B,UAAM,UAAU,QAAQ;AACxB,QAAI,CAAC,QAAQ,WAAW,MAAM,EAAG,QAAO;AAExC,UAAM,OAAO,QAAQ,MAAM,OAAO,MAAM,EAAE,KAAK;AAC/C,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,aAAa,KAAK,OAAO,IAAI;AACnC,UAAM,eAAe,eAAe,KAAK,OAAO,KAAK,MAAM,GAAG,UAAU,GAAG,YAAY;AACvF,UAAM,UAAU,eAAe,KAAK,KAAK,KAAK,MAAM,UAAU,EAAE,KAAK;AAErE,UAAM,aAAa,KAAK,aAAa,IAAI,WAAW;AACpD,QAAI,CAAC,WAAY,QAAO;AAExB,QAAI,WAAW,YAAY,CAAC,WAAW,SAAS,SAAS,QAAQ,WAAW,EAAE,GAAG;AAC/E,aAAO;AAAA,IACT;AACA,SAAK,WAAW,cAAc,KAAK,QAAQ,cAAc,SAAS,QAAQ,OAAO,OAAO;AACtF,aAAO;AAAA,IACT;AAGA,QAAI,WAAW,cAAc,WAAW,aAAa,GAAG;AACtD,YAAM,MAAM,GAAG,QAAQ,QAAQ,IAAI,WAAW,IAAI;AAClD,YAAM,QAAQ,KAAK,UAAU,IAAI,GAAG,KAAK;AACzC,YAAM,MAAM,KAAK,IAAI;AACrB,UAAI,QAAQ,IAAK,QAAO;AACxB,WAAK,UAAU,IAAI,KAAK,MAAM,WAAW,UAAU;AAAA,IACrD;AAEA,UAAM,OAAO,eAAe,OAAO;AACnC,UAAM,UAA8B;AAAA,MAClC,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,OAAO,CAAC,YAAY,QAAQ,MAAM,OAAO;AAAA,MACzC,kBAAkB,CAAC,YAAY;AAC7B,cAAM,UAAU,KAAK,QAAQ,QAAQ;AACrC,cAAM,OACJ,OAAO,YAAY,WAAW,EAAE,SAAS,GAAG,OAAO,IAAI,OAAO,GAAG,IAAI,EAAE,GAAG,QAAQ;AACpF,YAAI,OAAO,YAAY,YAAY,KAAK,SAAS;AAC/C,eAAK,UAAU,GAAG,OAAO,IAAI,KAAK,OAAO;AAAA,QAC3C;AACA,eAAO,QAAQ,MAAM,IAAI;AAAA,MAC3B;AAAA,MACA,OAAO,CAAC,UAAU,QAAQ,MAAM,KAAK;AAAA,IACvC;AAEA,QAAI;AACF,UAAI,WAAW,eAAe;AAC5B,cAAM,UAAU,MAAM,WAAW,cAAc,OAAO;AACtD,YAAI,YAAY,MAAO,QAAO;AAAA,MAChC;AACA,YAAM,WAAW,QAAQ,OAAO;AAAA,IAClC,SAAS,OAAO;AACd,WAAK,YAAY,OAAO,EAAE,SAAS,WAAW,MAAM,QAAQ,CAAC;AAAA,IAC/D;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,kBAAkB,aAA4C;AAClE,QAAI;AACF,UAAI,YAAY,WAAW;AACzB,cAAM,aAAa,KAAK,cAAc,IAAI,YAAY,SAAS,QAAQ,EAAE;AACzE,YAAI,CAAC,WAAY,QAAO;AACxB,cAAM,WAAW,QAAQ,WAAW;AACpC,eAAO;AAAA,MACT;AACA,UAAI,YAAY,aAAa;AAC3B,cAAM,UAAU,KAAK,eAAe,YAAY,YAAY,EAAE;AAC9D,YAAI,CAAC,QAAS,QAAO;AACrB,cAAM,QAAQ,QAAQ,WAAW;AACjC,eAAO;AAAA,MACT;AAAA,IACF,SAAS,OAAO;AACd,WAAK,YAAY,OAAO,EAAE,aAAa,SAAS,YAAY,SAAS,KAAK,CAAC;AAAA,IAC7E;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,UAA0D;AAC/E,UAAM,QAAQ,KAAK,kBAAkB,IAAI,QAAQ;AACjD,QAAI,MAAO,QAAO;AAClB,eAAW,CAAC,SAAS,OAAO,KAAK,KAAK,mBAAmB;AACvD,UAAI,QAAQ,SAAS,GAAG,KAAK,SAAS,WAAW,QAAQ,MAAM,GAAG,EAAE,CAAC,GAAG;AACtE,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,cAAc,SAAiC;AACrD,QAAI,OAAO,KAAK,mBAAmB,YAAY;AAC7C,aAAO,KAAK,eAAe,OAAO;AAAA,IACpC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW;AAEhB,SAAK,OAAO,GAAG,mBAAmB,CAAC,YAAY;AAC7C,WAAK,KAAK,kBAAkB,OAAO;AAAA,IACrC,CAAC;AAED,SAAK,OAAO,GAAG,uBAAuB,CAAC,gBAAgB;AACrD,WAAK,KAAK,kBAAkB,WAAW;AAAA,IACzC,CAAC;AAED,QAAI,KAAK,QAAQ,gBAAgB,OAAO;AACtC,YAAM,UAAU,MAAM;AACpB,aAAK,KAAK,KAAK,EAAE,MAAM,CAAC,UAAmB;AACzC,eAAK,YAAY,OAAO,CAAC,CAAC;AAAA,QAC5B,CAAC;AAAA,MACH;AACA,UAAI,KAAK,OAAO,QAAQ,GAAG;AAEzB,gBAAQ;AAAA,MACV,OAAO;AACL,aAAK,OAAO,KAAK,SAAS,OAAO;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YACN,OACA,SACM;AACN,QAAI,KAAK,QAAQ,SAAS;AACxB,WAAK,QAAQ,QAAQ,OAAO,OAAO;AACnC;AAAA,IACF;AACA,SAAK,OAAO,KAAK,gBAAgB,EAAE,OAAO,GAAG,QAAQ,CAAC;AAAA,EACxD;AACF;AAEA,SAAS,uBAAuB,YAAyC;AACvE,MAAI,CAAC,WAAW,QAAQ,OAAO,WAAW,SAAS,UAAU;AAC3D,UAAM,IAAI,gBAAgB,kCAAkC;AAAA,EAC9D;AACA,MAAI,KAAK,KAAK,WAAW,IAAI,GAAG;AAC9B,UAAM,IAAI,gBAAgB,+CAAyC,WAAW,IAAI,EAAE;AAAA,EACtF;AACA,MAAI,OAAO,WAAW,YAAY,YAAY;AAC5C,UAAM,IAAI,gBAAgB,WAAW,WAAW,IAAI,uBAAuB;AAAA,EAC7E;AACF;;;AClWA,gBAAuB,SACrB,WACA,cAAsC,CAAC,GACvC,YAAgC,UACE;AAClC,MAAI,SAAiC,EAAE,GAAG,YAAY;AAEtD,QAAM,cAAc,oBAAI,IAAY;AAEpC,aAAS;AACP,UAAM,OAAO,MAAM,UAAU,MAAM;AACnC,eAAW,QAAQ,KAAK,OAAO;AAC7B,YAAM;AAAA,IACR;AACA,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAM,aACJ,cAAc,WACV,KAAK,aACL,KAAK;AACX,QAAI,CAAC,cAAc,YAAY,IAAI,UAAU,EAAG;AAChD,gBAAY,IAAI,UAAU;AAE1B,aACE,cAAc,WACV,EAAE,GAAG,QAAQ,OAAO,OAAO,OAAO,QAAQ,YAAY,OAAO,OAAU,IACvE,EAAE,GAAG,QAAQ,OAAO,OAAO,OAAO,OAAO,YAAY,QAAQ,OAAU;AAAA,EAC/E;AACF;AAGA,eAAsB,kBACpB,WACA,cAAsC,CAAC,GACvC,YAAgC,UAChC,WAAW,KACG;AACd,QAAM,QAAa,CAAC;AACpB,mBAAiB,QAAQ,SAAS,WAAW,aAAa,SAAS,GAAG;AACpE,UAAM,KAAK,IAAI;AACf,QAAI,MAAM,UAAU,SAAU;AAAA,EAChC;AACA,SAAO;AACT;;;AClDO,IAAM,UAAU;AAAA;AAAA,EAErB,QAAQ,KAAK;AAAA;AAAA,EAEb,eAAe,KAAK;AAAA;AAAA,EAEpB,gBAAgB,KAAK;AAAA;AAAA,EAErB,yBAAyB,KAAK;AAAA;AAAA,EAE9B,oBAAoB,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOzB,iBAAiB,KAAK;AACxB;AAKO,IAAM,kBACX,QAAQ,SAAS,QAAQ,iBAAiB,QAAQ;AAG7C,SAAS,gBAAgB,OAAyB;AACvD,QAAM,QAAQ,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC;AAC7C,MAAI,QAAQ,KAAK,QAAQ,OAAQ;AAC/B,UAAM,IAAI,WAAW,0CAA0C;AAAA,EACjE;AACA,SAAO;AACT;AAGO,SAAS,YAAY,OAA6B;AACvD,QAAM,QAAsB,CAAC;AAC7B,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,OAAO,GAAkC;AACjF,SAAK,QAAQ,UAAU,KAAM,OAAM,KAAK,IAAI;AAAA,EAC9C;AACA,SAAO;AACT;","names":["onMessage","onClose","onError"]}