@openvertice/bot-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.
Files changed (48) hide show
  1. package/README.md +189 -2
  2. package/dist/src/audio.d.ts +32 -0
  3. package/dist/src/audio.d.ts.map +1 -0
  4. package/dist/src/audio.js +47 -0
  5. package/dist/src/audio.js.map +1 -0
  6. package/dist/src/cliente.d.ts +213 -0
  7. package/dist/src/cliente.d.ts.map +1 -0
  8. package/dist/src/cliente.js +381 -0
  9. package/dist/src/cliente.js.map +1 -0
  10. package/dist/src/gateway.d.ts +76 -0
  11. package/dist/src/gateway.d.ts.map +1 -0
  12. package/dist/src/gateway.js +299 -0
  13. package/dist/src/gateway.js.map +1 -0
  14. package/dist/src/http.d.ts +119 -0
  15. package/dist/src/http.d.ts.map +1 -0
  16. package/dist/src/http.js +189 -0
  17. package/dist/src/http.js.map +1 -0
  18. package/dist/src/index.d.ts +19 -0
  19. package/dist/src/index.d.ts.map +1 -0
  20. package/dist/src/index.js +16 -0
  21. package/dist/src/index.js.map +1 -0
  22. package/dist/src/tipos.d.ts +243 -0
  23. package/dist/src/tipos.d.ts.map +1 -0
  24. package/dist/src/tipos.js +5 -0
  25. package/dist/src/tipos.js.map +1 -0
  26. package/dist/src/voz-wrtc.d.ts +20 -0
  27. package/dist/src/voz-wrtc.d.ts.map +1 -0
  28. package/dist/src/voz-wrtc.js +68 -0
  29. package/dist/src/voz-wrtc.js.map +1 -0
  30. package/dist/src/voz.d.ts +150 -0
  31. package/dist/src/voz.d.ts.map +1 -0
  32. package/dist/src/voz.js +311 -0
  33. package/dist/src/voz.js.map +1 -0
  34. package/dist/src/wav.d.ts +29 -0
  35. package/dist/src/wav.d.ts.map +1 -0
  36. package/dist/src/wav.js +54 -0
  37. package/dist/src/wav.js.map +1 -0
  38. package/package.json +58 -3
  39. package/src/audio.ts +88 -0
  40. package/src/cliente.ts +472 -0
  41. package/src/gateway.ts +354 -0
  42. package/src/http.ts +249 -0
  43. package/src/index.ts +41 -0
  44. package/src/tipos.ts +220 -0
  45. package/src/voz-wrtc.ts +100 -0
  46. package/src/voz.ts +407 -0
  47. package/src/wav.ts +71 -0
  48. package/src/wrtc.d.ts +4 -0
@@ -0,0 +1,381 @@
1
+ // The bot as its author sees it: `start`, `on`, `command`, `enviar`. Everything
2
+ // else (token, session, heartbeat, reconnection) stays underneath.
3
+ import { ErroDaApi, Http } from "./http.js";
4
+ import { Gateway } from "./gateway.js";
5
+ /** Renews the session slightly before it expires, so it never dies mid-event. */
6
+ const RENOVAR_ANTES_MS = 120_000;
7
+ /**
8
+ * A Vértice bot.
9
+ *
10
+ * Create one, register listeners with {@link on} and commands with
11
+ * {@link command}, then call {@link start}. Sessions, heartbeats, `resume` and
12
+ * reconnection are handled internally, so the author only has to react to
13
+ * events.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const bot = new Bot({ token: process.env.VERTICE_BOT_TOKEN! });
18
+ *
19
+ * bot.command("ping", { descricao: "responde pong" }, async ({ responder }) => {
20
+ * await responder("pong");
21
+ * });
22
+ *
23
+ * await bot.start();
24
+ * ```
25
+ */
26
+ export class Bot {
27
+ #http;
28
+ #intents;
29
+ #log;
30
+ #ouvintes = new Map();
31
+ #comandos = [];
32
+ #ouvintesDeEstado = new Set();
33
+ #descoberta = null;
34
+ #sessao = null;
35
+ #gateway = null;
36
+ #ultimoErro = null;
37
+ /** @param opcoes Token, base URL and the intents this process wants. */
38
+ constructor(opcoes) {
39
+ this.#http = new Http({ baseUrl: opcoes.baseUrl, token: opcoes.token });
40
+ this.#intents = opcoes.intents ?? ["MESSAGES"];
41
+ this.#log = opcoes.log ?? (() => { });
42
+ }
43
+ /** Identity the server assigned, or `null` before {@link start}. */
44
+ get bot() {
45
+ return this.#descoberta?.bot ?? null;
46
+ }
47
+ /** Channels granted to the bot, or `null` before {@link start}. */
48
+ get canais() {
49
+ return this.#descoberta?.canais ?? null;
50
+ }
51
+ /** ICE servers from discovery (the bot's voice uses the same ones). */
52
+ get iceServers() {
53
+ return this.#descoberta?.iceServers ?? [];
54
+ }
55
+ /** Current gateway state, or `"parado"` before {@link start} and after {@link stop}. */
56
+ get estado() {
57
+ return this.#gateway?.estado ?? "parado";
58
+ }
59
+ /**
60
+ * Registers a listener for every gateway state change.
61
+ *
62
+ * Voice uses it to leave the room when the connection drops: `resume` brings
63
+ * the events back, but not the seat in the voice room.
64
+ *
65
+ * @param ouvinte Called with the new state.
66
+ * @returns This bot, for chaining.
67
+ */
68
+ aoMudarEstado(ouvinte) {
69
+ this.#ouvintesDeEstado.add(ouvinte);
70
+ return this;
71
+ }
72
+ /** Last connection error, for callers that want to show it in a `/status` command. */
73
+ get ultimoErro() {
74
+ return this.#ultimoErro;
75
+ }
76
+ /**
77
+ * Discovers what the bot may do, opens a session and connects the gateway.
78
+ *
79
+ * @returns This bot, once the gateway reports `ready`.
80
+ * @throws {ErroDaApi} When discovery or session creation fails.
81
+ * @throws {Error} When the server refuses the bot.
82
+ */
83
+ async start() {
84
+ this.#descoberta = await this.#http.descobrir();
85
+ this.#log(`conectando como @${this.#descoberta.bot.usuario} (${this.#descoberta.canais.texto.length} canal(is) de texto)`);
86
+ this.#sessao = await this.#http.abrirSessao();
87
+ this.#gateway = new Gateway({
88
+ url: this.#descoberta.gateway.url,
89
+ heartbeatMs: this.#descoberta.gateway.heartbeatMs,
90
+ intents: this.#intents,
91
+ comandos: this.#anunciarComandos(),
92
+ sessao: () => this.#sessaoValida(),
93
+ aoEvento: (t, d) => this.#despachar(t, d),
94
+ aoEstado: (estado, detalhe) => {
95
+ if (estado === "recusado")
96
+ this.#ultimoErro = new Error(detalhe ?? estado);
97
+ this.#log(`gateway: ${estado}${detalhe ? ` (${detalhe})` : ""}`);
98
+ for (const ouvinte of this.#ouvintesDeEstado) {
99
+ try {
100
+ ouvinte(estado);
101
+ }
102
+ catch (erro) {
103
+ this.#log(`ouvinte de estado falhou: ${erro}`);
104
+ }
105
+ }
106
+ },
107
+ log: this.#log,
108
+ });
109
+ await this.#gateway.conectar();
110
+ return this;
111
+ }
112
+ /**
113
+ * Returns a session that will not expire while the bot is connected.
114
+ *
115
+ * On reconnect it asks for a new one when the current session is about to
116
+ * expire. Rotating the token or disabling the bot kills the connection for
117
+ * good (4009) — in that case `start` fails on purpose, instead of retrying
118
+ * forever with a dead credential.
119
+ *
120
+ * @returns A session valid for at least {@link RENOVAR_ANTES_MS} more.
121
+ */
122
+ async #sessaoValida() {
123
+ const atual = this.#sessao;
124
+ if (atual && atual.expiraEm - RENOVAR_ANTES_MS > Date.now())
125
+ return atual;
126
+ this.#sessao = await this.#http.abrirSessao();
127
+ return this.#sessao;
128
+ }
129
+ /**
130
+ * Sends a raw gateway action (voice uses it to join, leave and signal).
131
+ *
132
+ * @param tipo Action name understood by the server.
133
+ * @param dados Action payload.
134
+ * @throws {Error} When `start()` has not been called yet.
135
+ */
136
+ agir(tipo, dados = {}) {
137
+ if (!this.#gateway)
138
+ throw new Error("Chame `start()` antes de agir no gateway.");
139
+ this.#gateway.agir(tipo, dados);
140
+ }
141
+ /** Closes the gateway for good and forgets the session. */
142
+ async stop() {
143
+ this.#gateway?.fechar();
144
+ this.#gateway = null;
145
+ this.#sessao = null;
146
+ }
147
+ /**
148
+ * Subscribes to a gateway event (`message.created`, `voice.joined`, …).
149
+ *
150
+ * @param nome Event name.
151
+ * @param ouvinte Handler; it may be async. Failures are logged, never thrown.
152
+ * @returns This bot, for chaining.
153
+ */
154
+ on(nome, ouvinte) {
155
+ if (!this.#ouvintes.has(nome))
156
+ this.#ouvintes.set(nome, new Set());
157
+ this.#ouvintes.get(nome).add(ouvinte);
158
+ return this;
159
+ }
160
+ /**
161
+ * Removes a listener previously registered with {@link on}.
162
+ *
163
+ * @param nome Event name.
164
+ * @param ouvinte The exact handler reference that was registered.
165
+ * @returns This bot, for chaining.
166
+ */
167
+ off(nome, ouvinte) {
168
+ this.#ouvintes.get(nome)?.delete(ouvinte);
169
+ return this;
170
+ }
171
+ /**
172
+ * Fans an event out to its listeners.
173
+ *
174
+ * Listener failures (a sync throw or a rejected promise) are logged and
175
+ * swallowed, so one broken handler cannot stop the others.
176
+ *
177
+ * @param nome Event name.
178
+ * @param dados Event payload.
179
+ */
180
+ #despachar(nome, dados) {
181
+ if (nome === "message.created")
182
+ this.#talvezComando(dados);
183
+ for (const ouvinte of this.#ouvintes.get(nome) ?? []) {
184
+ try {
185
+ const resultado = ouvinte(dados);
186
+ if (resultado instanceof Promise)
187
+ resultado.catch((erro) => this.#log(`ouvinte falhou: ${erro}`));
188
+ }
189
+ catch (erro) {
190
+ this.#log(`ouvinte falhou: ${erro}`);
191
+ }
192
+ }
193
+ }
194
+ // ---- commands (the everyday `!tocar`)
195
+ /**
196
+ * Registers a command.
197
+ *
198
+ * The channel prefix (`!`) belongs to the server: here the name is just
199
+ * `tocar`. Without `canais`, the command works in every channel where the bot
200
+ * may speak. Every registered command is announced to the client's
201
+ * autocomplete, including ones registered after `start()`.
202
+ *
203
+ * @param nome Command name; a leading `!` or `/` is stripped.
204
+ * @param opcoesOuFn Either the options object or the handler itself.
205
+ * @param talvezFn Handler, when the second argument carries the options.
206
+ * @returns This bot, for chaining.
207
+ * @throws {Error} When no handler is provided.
208
+ *
209
+ * @example
210
+ * ```ts
211
+ * bot.command("ping", async ({ responder }) => {
212
+ * await responder("pong");
213
+ * });
214
+ *
215
+ * bot.command("eco", { descricao: "repete o texto" }, async ({ resto, responder }) => {
216
+ * await responder(resto);
217
+ * });
218
+ * ```
219
+ */
220
+ command(nome, opcoesOuFn, talvezFn) {
221
+ const opcoes = typeof opcoesOuFn === "function" ? {} : opcoesOuFn;
222
+ const executar = typeof opcoesOuFn === "function" ? opcoesOuFn : talvezFn;
223
+ if (!executar)
224
+ throw new Error(`O comando ${nome} não tem o que executar.`);
225
+ this.#comandos.push({
226
+ nome: nome.replace(/^[!\/]/, "").toLowerCase(),
227
+ ...(opcoes.descricao ? { descricao: opcoes.descricao } : {}),
228
+ canais: (opcoes.canais ?? []).map((c) => c.toUpperCase()),
229
+ executar,
230
+ });
231
+ // Announced here and not only in `start()`: a command registered after
232
+ // connecting must reach the autocomplete too.
233
+ this.#anunciarComandos();
234
+ return this;
235
+ }
236
+ /**
237
+ * Builds the list announced on `identify`: names and descriptions only, no handlers.
238
+ *
239
+ * It also pushes the list to a live gateway, so a command registered after
240
+ * `start()` appears in the client's autocomplete without reconnecting.
241
+ *
242
+ * @returns The list of commands to announce.
243
+ */
244
+ #anunciarComandos() {
245
+ const anunciados = this.#comandos.map(({ nome, descricao }) => descricao ? { nome, descricao } : { nome });
246
+ // Already connected: send the new list without reconnecting (the client's
247
+ // autocomplete updates immediately).
248
+ if (this.#gateway?.estado === "pronto")
249
+ this.#gateway.agir("comandos", { comandos: anunciados });
250
+ return anunciados;
251
+ }
252
+ /** Registered commands, in registration order (handy in a `!help` command). */
253
+ get comandos() {
254
+ return this.#comandos.map(({ nome, descricao }) => descricao ? { nome, descricao } : { nome });
255
+ }
256
+ /**
257
+ * Tries to run a command for a message that just arrived.
258
+ *
259
+ * Prefix handling, channel filtering and "the bot never runs its own
260
+ * commands" all live here.
261
+ *
262
+ * @param mensagem The `message.created` payload that just arrived.
263
+ */
264
+ #talvezComando(mensagem) {
265
+ if (!mensagem.texto || !mensagem.sala)
266
+ return;
267
+ // The bot does not run its own commands: otherwise `!eco !eco …` would loop.
268
+ if (mensagem.autorBot && mensagem.autorId === this.#descoberta?.bot.id)
269
+ return;
270
+ const canal = this.#descoberta?.canais.texto.find((c) => c.code === mensagem.sala);
271
+ if (!canal)
272
+ return;
273
+ const texto = mensagem.texto.trim();
274
+ const prefixo = canal.prefixo;
275
+ // Without a channel prefix, the command is simply the first token ("tocar x").
276
+ const semPrefixo = prefixo && texto.startsWith(prefixo) ? texto.slice(prefixo.length) : texto;
277
+ if (prefixo && !texto.startsWith(prefixo))
278
+ return;
279
+ const [bruto = "", ...args] = semPrefixo.split(/\s+/);
280
+ const nome = bruto.toLowerCase();
281
+ const comando = this.#comandos.find((c) => c.nome === nome && (c.canais.length === 0 || c.canais.includes(canal.code)));
282
+ if (!comando)
283
+ return;
284
+ const contexto = {
285
+ mensagem,
286
+ canal,
287
+ args,
288
+ resto: semPrefixo.slice(bruto.length).trim(),
289
+ responder: (resposta) => this.enviar(canal.code, resposta),
290
+ apagar: () => this.#http.apagar(canal.code, mensagem.id, this.#sessao?.sessao),
291
+ };
292
+ Promise.resolve(comando.executar(contexto)).catch((erro) => this.#log(`comando ${comando.nome} falhou: ${erro.message}`));
293
+ }
294
+ // ---- messages
295
+ /**
296
+ * Sends a text message.
297
+ *
298
+ * It goes over HTTP on purpose: the response carries the created item (id,
299
+ * timestamp), and the gateway delivers `message.created` to everyone anyway.
300
+ *
301
+ * @param canal Channel code (case-insensitive; uppercased before sending).
302
+ * @param texto Message content.
303
+ * @returns The message the server created.
304
+ * @throws {ErroDaApi} When the bot cannot post in the channel.
305
+ */
306
+ enviar(canal, texto) {
307
+ return this.#http.enviar(canal.toUpperCase(), texto, this.#sessao?.sessao);
308
+ }
309
+ /**
310
+ * Sends audio as a **voice message** — the item the client renders as a
311
+ * "voice message" and plays inline.
312
+ *
313
+ * @param canal Channel code.
314
+ * @param audio The audio bytes (WAV by default; see `wavDeTom`).
315
+ * @param opcoes File name and MIME type; defaults to `recado.wav` / `audio/wav`.
316
+ * @returns The message the server created.
317
+ * @throws {ErroDaApi} When the upload fails.
318
+ */
319
+ enviarVoz(canal, audio, opcoes = {}) {
320
+ return this.#http.enviarArquivo(canal.toUpperCase(), audio, {
321
+ nome: opcoes.nome ?? "recado.wav",
322
+ mime: opcoes.mime ?? "audio/wav",
323
+ tipo: "voz",
324
+ sessao: this.#sessao?.sessao,
325
+ });
326
+ }
327
+ /**
328
+ * Sends any other file (image, PDF, audio as a regular attachment).
329
+ *
330
+ * @param canal Channel code.
331
+ * @param conteudo File bytes.
332
+ * @param opcoes File name and MIME type; defaults to `arquivo` /
333
+ * `application/octet-stream`.
334
+ * @returns The message the server created.
335
+ * @throws {ErroDaApi} When the upload fails.
336
+ */
337
+ enviarArquivo(canal, conteudo, opcoes = {}) {
338
+ return this.#http.enviarArquivo(canal.toUpperCase(), conteudo, {
339
+ nome: opcoes.nome ?? "arquivo",
340
+ mime: opcoes.mime ?? "application/octet-stream",
341
+ tipo: "arquivo",
342
+ sessao: this.#sessao?.sessao,
343
+ });
344
+ }
345
+ /**
346
+ * Reads a page of history (100 items; `antesDe` pages backwards).
347
+ *
348
+ * @param canal Channel code.
349
+ * @param antesDe Timestamp cursor: returns messages older than this one.
350
+ * @returns The page, plus `temMais` telling whether another page exists.
351
+ * @throws {ErroDaApi} When the bot cannot read the channel.
352
+ */
353
+ historico(canal, antesDe) {
354
+ return this.#http.historico(canal.toUpperCase(), {
355
+ ...(antesDe ? { antesDe } : {}),
356
+ sessao: this.#sessao?.sessao,
357
+ });
358
+ }
359
+ /**
360
+ * Deletes a message the bot wrote.
361
+ *
362
+ * @param canal Channel code.
363
+ * @param id Message id.
364
+ * @throws {ErroDaApi} When the message is not the bot's or is already gone.
365
+ */
366
+ apagar(canal, id) {
367
+ return this.#http.apagar(canal.toUpperCase(), id, this.#sessao?.sessao);
368
+ }
369
+ /**
370
+ * Re-runs only the discovery step (e.g. after changing channels in the panel).
371
+ *
372
+ * @returns The fresh discovery document.
373
+ * @throws {ErroDaApi} When the token is rejected.
374
+ */
375
+ async recarregar() {
376
+ this.#descoberta = await this.#http.descobrir();
377
+ return this.#descoberta;
378
+ }
379
+ }
380
+ export { ErroDaApi };
381
+ //# sourceMappingURL=cliente.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cliente.js","sourceRoot":"","sources":["../../src/cliente.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type { ComandoAnunciado, Eventos, Sessao } from "./tipos.js";
2
+ /**
3
+ * Connection states the bot can observe.
4
+ *
5
+ * - `conectando` — socket being opened and the bot identified.
6
+ * - `pronto` — `ready` received; events are flowing.
7
+ * - `reconectando` — waiting out the backoff before trying again.
8
+ * - `encerrado` — closed on purpose (`stop()`); no reconnect.
9
+ * - `recusado` — the server refused the bot; no reconnect.
10
+ */
11
+ export type EstadoDoGateway = "conectando" | "pronto" | "reconectando" | "encerrado" | "recusado";
12
+ /** Everything the gateway needs from the bot, plus its hooks. */
13
+ export interface OpcoesGateway {
14
+ /** WebSocket URL from the discovery document. */
15
+ url: string;
16
+ /** Returns a valid session; called again when the current one expires. */
17
+ sessao: () => Promise<Sessao>;
18
+ /** Intents requested on `identify`. */
19
+ intents: string[];
20
+ /** Commands for the client's autocomplete; resent on every connection. */
21
+ comandos?: ComandoAnunciado[];
22
+ /** Heartbeat interval in milliseconds, as told by the server. */
23
+ heartbeatMs: number;
24
+ /** Called for every dispatched event (op 0). */
25
+ aoEvento: <K extends keyof Eventos>(t: K, d: Eventos[K]) => void;
26
+ /** Called on every state change, with an optional human-readable detail. */
27
+ aoEstado?: (estado: EstadoDoGateway, detalhe?: string) => void;
28
+ /** Diagnostic sink: one line per interesting step. */
29
+ log?: (mensagem: string) => void;
30
+ }
31
+ /**
32
+ * WebSocket client for the Vértice gateway.
33
+ *
34
+ * It speaks the `{op, t, d, s}` envelope: op 10 `hello`, op 2 `identify` (or
35
+ * op 6 `resume`), op 1 heartbeat, op 11 heartbeat ack, op 0 dispatch and op 4
36
+ * action. Heartbeat, session resume and reconnection with exponential backoff
37
+ * are handled here, so bot authors never have to.
38
+ *
39
+ * One instance per bot: `conectar()` resolves only after `ready` arrives.
40
+ */
41
+ export declare class Gateway {
42
+ #private;
43
+ private readonly opcoes;
44
+ /** @param opcoes Endpoints, credentials and hooks used by the connection. */
45
+ constructor(opcoes: OpcoesGateway);
46
+ /** Current connection state. */
47
+ get estado(): EstadoDoGateway;
48
+ /** Session in use, or `null` before the first connection attempt. */
49
+ get sessaoAtual(): Sessao | null;
50
+ /**
51
+ * Opens the socket and resolves once the bot is identified (`ready`).
52
+ *
53
+ * @returns A promise that settles when the gateway is truly ready.
54
+ * @throws {Error} When the server refuses the bot or the socket cannot open.
55
+ */
56
+ conectar(): Promise<void>;
57
+ /**
58
+ * Sends an action (op 4) to the gateway.
59
+ *
60
+ * Voice uses this for `voz.entrar`, `voz.sair` and `voice.signal`; the same
61
+ * route carries `comandos` updates.
62
+ *
63
+ * @param tipo Action name understood by the server.
64
+ * @param dados Action payload, merged into `d`.
65
+ * @throws {Error} When the gateway is not connected.
66
+ */
67
+ agir(tipo: string, dados?: Record<string, unknown>): void;
68
+ /**
69
+ * Closes the connection on purpose: it will not reconnect.
70
+ *
71
+ * @param codigo WebSocket close code sent to the server.
72
+ * @param motivo Human-readable reason sent to the server.
73
+ */
74
+ fechar(codigo?: number, motivo?: string): void;
75
+ }
76
+ //# sourceMappingURL=gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/gateway.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAgBpE;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GACvB,YAAY,GACZ,QAAQ,GACR,cAAc,GACd,WAAW,GACX,UAAU,CAAC;AAEf,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,uCAAuC;IACvC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,QAAQ,EAAE,CAAC,CAAC,SAAS,MAAM,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACjE,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,sDAAsD;IACtD,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAUD;;;;;;;;;GASG;AACH,qBAAa,OAAO;;IAYN,OAAO,CAAC,QAAQ,CAAC,MAAM;IADnC,6EAA6E;gBAChD,MAAM,EAAE,aAAa;IAElD,gCAAgC;IAChC,IAAI,MAAM,IAAI,eAAe,CAE5B;IAED,qEAAqE;IACrE,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IAED;;;;;OAKG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAoHzB;;;;;;;;;OASG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAO7D;;;;;OAKG;IACH,MAAM,CAAC,MAAM,SAAO,EAAE,MAAM,SAAkB,GAAG,IAAI;CA6GtD"}