@whanext/core 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  Todas as mudanças relevantes do projeto serão registradas neste arquivo.
4
4
 
5
+ ## 0.7.0
6
+
7
+ ### Adicionado
8
+
9
+ - `app.message.react(message, emoji)` e `app.message.unreact(message)` para adicionar e remover reações sem expor tipos do provider.
10
+ - Evento `groupParticipantsChanged`, com grupo, ação, participantes afetados e autor quando informado pelo WhatsApp.
11
+
12
+ ### Alterado
13
+
14
+ - Alterações de participantes continuam invalidando automaticamente o cache de metadados do grupo antes da emissão do evento público.
15
+
16
+ ## 0.6.0
17
+
18
+ ### Adicionado
19
+
20
+ - `app.media.download(message)` para baixar imagens, vídeos, áudios, documentos e stickers recebidos como um `Buffer` com metadados normalizados.
21
+ - Renovação automática da URL de mídia quando o link original expira.
22
+ - Configurações `cache.memoryMaxEntries` e `messageCacheSize` para limitar a memória usada pelos caches internos.
23
+
24
+ ### Alterado
25
+
26
+ - O cache em memória agora usa LRU e agrupa buscas simultâneas dos metadados do mesmo grupo em uma única consulta ao WhatsApp.
27
+ - O cache de mensagens usa a chave completa da conversa, evitando colisões entre mensagens de chats distintos, e mantém até 1.000 entradas por padrão.
28
+ - Envio de presença deixou de fazer uma assinatura remota antes de cada atualização, reduzindo uma ida extra à rede para `typing`, `recording` e `paused`.
29
+
5
30
  ## 0.5.1
6
31
 
7
32
  ### Adicionado
package/CONTRIBUTING.md CHANGED
@@ -18,6 +18,9 @@ npm run check
18
18
  - A API pública usa modelos e erros do WhaNext.
19
19
  - Operações dependentes de estado retornam resultados tipados e idempotentes.
20
20
  - JID, LID e PN são resolvidos pela biblioteca.
21
+ - Mídias são expostas por modelos normalizados; tipos e objetos do provider não entram na API pública.
22
+ - APIs de presença não devem adicionar chamadas remotas além da atualização de estado solicitada.
23
+ - Caches internos devem ter limite de memória, TTL quando aplicável e cobertura para concorrência.
21
24
  - Novos comportamentos possuem testes sem conexão real com o WhatsApp.
22
25
  - Imports com vários nomes mantêm um nome por linha.
23
26
  - Código-fonte não contém comentários explicando implementação óbvia.
package/README.md CHANGED
@@ -35,7 +35,7 @@ await app.login({
35
35
  - Login por pairing code, sessão persistente e reconexão automática.
36
36
  - Prefixo global e comandos declarativos com argumentos tipados.
37
37
  - Usuários normalizados entre JID, LID e PN.
38
- - Mensagens, replies, edição, exclusão, menções e mídias.
38
+ - Mensagens, replies, edição, exclusão, menções, mídias e download normalizado.
39
39
  - Operações de grupos e membros com resultados idempotentes.
40
40
  - Cache de metadados transparente e substituível.
41
41
  - Mute permanente ou temporário com SQLite ou banco próprio.
@@ -261,10 +261,15 @@ await app.message.reply(message, {
261
261
 
262
262
  await app.message.edit(sent, 'Texto atualizado.');
263
263
  await app.message.delete(sent);
264
+
265
+ await app.message.react(sent, '👏🏻');
266
+ await app.message.unreact(sent);
264
267
  ```
265
268
 
266
269
  `delete()` aceita `Message`, `SentMessage` ou `MessageKey`.
267
270
 
271
+ `react()` aceita os mesmos tipos e adiciona uma reação à mensagem. `unreact()` remove a reação da conta conectada.
272
+
268
273
  ## Mídias
269
274
 
270
275
  ```ts
@@ -284,8 +289,14 @@ await app.media.audio(chatId, {
284
289
  mimetype: 'audio/ogg; codecs=opus',
285
290
  voice: true,
286
291
  });
292
+
293
+ const downloaded = await app.media.download(message);
294
+
295
+ await writeFile(`./downloads/${downloaded.fileName ?? message.id}`, downloaded.data);
287
296
  ```
288
297
 
298
+ `download()` aceita a `Message` recebida ou a sua `MessageKey` e devolve o buffer junto dos metadados normalizados. A mídia deve ser baixada enquanto a mensagem ainda está no cache da instância; o provider tenta renovar a URL de mídia automaticamente quando necessário.
299
+
289
300
  Texto, imagem e vídeo aceitam `User` diretamente em `mentions`.
290
301
 
291
302
  ## Grupos e membros
@@ -305,6 +316,19 @@ await app.member.demote(groupId, user);
305
316
 
306
317
  Estados como `already_open`, `already_admin`, `not_admin`, `not_in_group` e `already_removed` evitam mutações redundantes. A biblioteca escolhe automaticamente a identidade correta para grupos LID ou PN e só retorna sucesso depois da confirmação do WhatsApp.
307
318
 
319
+ Mudanças feitas por outros participantes podem ser acompanhadas sem lidar com o provider:
320
+
321
+ ```ts
322
+ app.on('groupParticipantsChanged', async (change) => {
323
+ console.log(change.groupId);
324
+ console.log(change.action);
325
+ console.log(change.participantIds);
326
+ console.log(change.authorId);
327
+ });
328
+ ```
329
+
330
+ `action` pode ser `add`, `remove`, `promote`, `demote` ou `modify`. O cache de metadados do grupo é invalidado antes desse evento ser emitido.
331
+
308
332
  ## Mute nativo
309
333
 
310
334
  Quando habilitado, o mute é aplicado antes dos eventos públicos e do router. Mensagens de um usuário mutado são apagadas automaticamente.
@@ -489,11 +513,18 @@ const app = await create({
489
513
  cache: {
490
514
  store: myRedisStore,
491
515
  groupTtlMs: 300_000,
516
+ memoryMaxEntries: 1_000,
492
517
  },
493
518
  });
494
519
  ```
495
520
 
496
- O cache padrão vive na instância do app. Eventos e mutações de grupo invalidam automaticamente entradas relacionadas.
521
+ O cache padrão vive na instância do app, usa LRU limitado e elimina entradas expiradas durante as leituras. Consultas simultâneas dos mesmos metadados são agrupadas em uma única chamada ao WhatsApp. Eventos e mutações de grupo invalidam automaticamente entradas relacionadas.
522
+
523
+ O cache interno de mensagens mantém até 1.000 mensagens por padrão para replies, reenvios do provider e downloads de mídia. Ajuste quando necessário:
524
+
525
+ ```ts
526
+ const app = await create({ messageCacheSize: 2_000 });
527
+ ```
497
528
 
498
529
  ## Presença
499
530
 
@@ -503,6 +534,8 @@ await app.chat.recording(chatId);
503
534
  await app.chat.stopTyping(chatId);
504
535
  ```
505
536
 
537
+ `typing()` envia `composing`, `recording()` envia `recording` com mídia de áudio e `stopTyping()` envia `paused`, conforme o protocolo do WhatsApp. Nenhuma assinatura de presença desnecessária é feita antes do envio.
538
+
506
539
  ## Chamadas
507
540
 
508
541
  ```ts
@@ -533,8 +566,8 @@ Todos os erros públicos usam `WhaNextError` e códigos estáveis. O logger regi
533
566
 
534
567
  | Domínio | Responsabilidade |
535
568
  | --- | --- |
536
- | `app.message` | Envio, reply, edição, exclusão e texto |
537
- | `app.media` | Imagem, vídeo e áudio |
569
+ | `app.message` | Envio, reply, edição, exclusão, texto e reações |
570
+ | `app.media` | Envio e download de mídia |
538
571
  | `app.group` | Estado, convite, pin e metadados |
539
572
  | `app.member` | Remoção, promoção e rebaixamento |
540
573
  | `app.user` | Criação e resolução de usuários |
@@ -544,6 +577,7 @@ Todos os erros públicos usam `WhaNextError` e códigos estáveis. O logger regi
544
577
  | `app.router()` | Registro e despacho de comandos |
545
578
  | `loadCommands()` | Autoload de comandos a partir de uma pasta |
546
579
  | `app.health()` | Snapshot de saúde da aplicação |
580
+ | `app.on('groupParticipantsChanged')` | Alterações de participantes em grupos |
547
581
 
548
582
  ## Exemplo executável
549
583
 
package/SECURITY.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  | Versão | Suporte |
6
6
  | --- | --- |
7
- | 0.3.x | Sim |
7
+ | 0.7.x | Sim |
8
8
  | anteriores | Não |
9
9
 
10
10
  ## Reportando uma vulnerabilidade
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ interface CacheStore {
7
7
  interface CacheOptions {
8
8
  store?: CacheStore;
9
9
  groupTtlMs?: number;
10
+ memoryMaxEntries?: number;
10
11
  }
11
12
 
12
13
  interface UserData {
@@ -107,6 +108,12 @@ interface SentMessage {
107
108
  keys: MessageKey;
108
109
  timestamp: Date;
109
110
  }
111
+ interface DownloadedMedia {
112
+ data: Buffer;
113
+ kind: MediaKind;
114
+ mimetype?: string;
115
+ fileName?: string;
116
+ }
110
117
  type MediaSource = Uint8Array | {
111
118
  url: string;
112
119
  } | {
@@ -150,7 +157,7 @@ interface CommandDefinition {
150
157
  declare function defineCommand<const Command extends CommandDefinition>(command: Command): Command;
151
158
  declare function defineCommands<const Commands extends readonly CommandDefinition[]>(...commands: Commands): Commands;
152
159
 
153
- type WhaNextErrorCode = 'AUTH_INVALID_PHONE' | 'AUTH_EXPIRED' | 'CONNECTION_CLOSED' | 'CONNECTION_FAILED' | 'GROUP_NOT_FOUND' | 'MEMBER_NOT_FOUND' | 'BOT_NOT_ADMIN' | 'MESSAGE_NOT_FOUND' | 'MUTE_DISABLED' | 'STORAGE_ERROR' | 'ARGUMENT_MISSING' | 'ARGUMENT_INVALID' | 'COMMAND_NOT_ALLOWED' | 'COMMAND_LOAD_FAILED' | 'PROVIDER_ERROR' | 'UNKNOWN_ERROR';
160
+ type WhaNextErrorCode = 'AUTH_INVALID_PHONE' | 'AUTH_EXPIRED' | 'CONNECTION_CLOSED' | 'CONNECTION_FAILED' | 'GROUP_NOT_FOUND' | 'MEMBER_NOT_FOUND' | 'BOT_NOT_ADMIN' | 'MESSAGE_NOT_FOUND' | 'MEDIA_NOT_AVAILABLE' | 'MUTE_DISABLED' | 'STORAGE_ERROR' | 'ARGUMENT_MISSING' | 'ARGUMENT_INVALID' | 'COMMAND_NOT_ALLOWED' | 'COMMAND_LOAD_FAILED' | 'PROVIDER_ERROR' | 'UNKNOWN_ERROR';
154
161
  interface WhaNextErrorOptions {
155
162
  cause?: unknown;
156
163
  context?: Readonly<Record<string, unknown>>;
@@ -167,6 +174,13 @@ declare function toWhaNextError(error: unknown, context?: Readonly<Record<string
167
174
  type GroupAccess = 'open' | 'closed';
168
175
  type GroupRole = 'member' | 'admin' | 'owner';
169
176
  type GroupAddressingMode = 'lid' | 'pn';
177
+ type GroupParticipantAction = 'add' | 'remove' | 'promote' | 'demote' | 'modify';
178
+ interface GroupParticipantsChanged {
179
+ groupId: string;
180
+ action: GroupParticipantAction;
181
+ participantIds: string[];
182
+ authorId?: string;
183
+ }
170
184
  interface GroupParticipant {
171
185
  id: string;
172
186
  lid?: string;
@@ -228,6 +242,7 @@ interface ProviderEvents {
228
242
  groupChanged: {
229
243
  groupId: string;
230
244
  };
245
+ groupParticipantsChanged: GroupParticipantsChanged;
231
246
  call: CallEvent;
232
247
  }
233
248
  type Unsubscribe = () => void;
@@ -238,6 +253,8 @@ interface WhatsAppProvider {
238
253
  requestPairingCode(phone: string): Promise<string>;
239
254
  on<Event extends keyof ProviderEvents>(event: Event, listener: (payload: ProviderEvents[Event]) => void | Promise<void>): Unsubscribe;
240
255
  sendMessage(chatId: string, content: MessageContent, replyTo?: MessageKey): Promise<SentMessage>;
256
+ reactToMessage(key: MessageKey, emoji?: string): Promise<SentMessage>;
257
+ downloadMedia(key: MessageKey): Promise<DownloadedMedia>;
241
258
  editMessage(key: MessageKey, content: string): Promise<SentMessage>;
242
259
  deleteMessage(key: MessageKey): Promise<void>;
243
260
  getGroup(groupId: string): Promise<GroupSnapshot>;
@@ -393,6 +410,7 @@ declare class MediaService {
393
410
  image(chatId: string, content: ImageContent): Promise<SentMessage>;
394
411
  video(chatId: string, content: VideoContent): Promise<SentMessage>;
395
412
  audio(chatId: string, content: AudioContent): Promise<SentMessage>;
413
+ download(message: Message | MessageKey): Promise<DownloadedMedia>;
396
414
  }
397
415
 
398
416
  declare class MemberService {
@@ -410,6 +428,8 @@ declare class MessageService {
410
428
  reply(message: Message, content: MessageContent): Promise<SentMessage>;
411
429
  edit(message: Message | SentMessage | MessageKey, text: string): Promise<SentMessage>;
412
430
  delete(message: Message | SentMessage | MessageKey): Promise<void>;
431
+ react(message: Message | SentMessage | MessageKey, emoji: string): Promise<SentMessage>;
432
+ unreact(message: Message | SentMessage | MessageKey): Promise<SentMessage>;
413
433
  text(chatId: string, text: string, mentions?: MentionTarget[]): Promise<SentMessage>;
414
434
  }
415
435
 
@@ -426,6 +446,7 @@ interface AppEvents {
426
446
  error: WhaNextError;
427
447
  mute: MuteEnforcement;
428
448
  call: CallEvent;
449
+ groupParticipantsChanged: GroupParticipantsChanged;
429
450
  }
430
451
  interface LoginOptions {
431
452
  onCode?: (code: string) => void | Promise<void>;
@@ -491,12 +512,16 @@ interface CreateOptions {
491
512
  mute?: MuteOptions;
492
513
  router?: Omit<RouterOptions, 'prefix'>;
493
514
  reconnect?: ReconnectOptions;
515
+ messageCacheSize?: number;
494
516
  provider?: WhatsAppProvider;
495
517
  }
496
518
  declare function create(options?: CreateOptions): Promise<WhaNextApp>;
497
519
 
498
520
  declare class MemoryCache implements CacheStore {
499
521
  #private;
522
+ constructor(options?: {
523
+ maxEntries?: number;
524
+ });
500
525
  get<T>(key: string): Promise<T | undefined>;
501
526
  set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
502
527
  delete(key: string): Promise<void>;
@@ -531,4 +556,4 @@ declare class SqliteMuteStore implements MuteStore {
531
556
  close(): void;
532
557
  }
533
558
 
534
- export { type AddMuteOptions, type AddMuteResult, type AppEvents, type AppHealth, type AppHealthStatus, ArgsParser, type AudioContent, Browser, type CacheOptions, type CacheStore, type CallEvent, type CallStatus, type ChangeResult, type CommandDefinition, type CommandRegistrar, CommandRouter, type ConnectionState, type ConnectionUpdate, type CreateOptions, type GroupAccess, type GroupAddressingMode, type GroupParticipant, type GroupRole, type GroupSnapshot, type ImageContent, type InviteResult, type LoadCommandsOptions, type LoadCommandsResult, type LoadedCommand, type LogContext, type LogEntry, type LogFormat, type LogLevel, type LogWriter, Logger, type LoggerConfig, type LoggerOptions, type LoginOptions, type MediaKind, type MediaSource, type MemberActionState, MemoryCache, type MentionTarget, type Message, type MessageContent, type MessageKey, type MessageMedia, type MuteChangeResult, type MuteEnforcement, type MuteOptions, type MuteRecord, MuteService, type MuteStore, type ParticipantUpdateResult, type PresenceState, type QuotedMessage, type ReconnectOptions, type RemoveMuteResult, type RouterOptions, type SentMessage, SqliteMuteStore, type StoredMute, type TextContent, User, type UserData, type VideoContent, WhaNextApp, WhaNextError, type WhaNextErrorCode, type WhatsAppProvider, create, defineCommand, defineCommands, loadCommands, toWhaNextError };
559
+ export { type AddMuteOptions, type AddMuteResult, type AppEvents, type AppHealth, type AppHealthStatus, ArgsParser, type AudioContent, Browser, type CacheOptions, type CacheStore, type CallEvent, type CallStatus, type ChangeResult, type CommandDefinition, type CommandRegistrar, CommandRouter, type ConnectionState, type ConnectionUpdate, type CreateOptions, type DownloadedMedia, type GroupAccess, type GroupAddressingMode, type GroupParticipant, type GroupParticipantAction, type GroupParticipantsChanged, type GroupRole, type GroupSnapshot, type ImageContent, type InviteResult, type LoadCommandsOptions, type LoadCommandsResult, type LoadedCommand, type LogContext, type LogEntry, type LogFormat, type LogLevel, type LogWriter, Logger, type LoggerConfig, type LoggerOptions, type LoginOptions, type MediaKind, type MediaSource, type MemberActionState, MemoryCache, type MentionTarget, type Message, type MessageContent, type MessageKey, type MessageMedia, type MuteChangeResult, type MuteEnforcement, type MuteOptions, type MuteRecord, MuteService, type MuteStore, type ParticipantUpdateResult, type PresenceState, type QuotedMessage, type ReconnectOptions, type RemoveMuteResult, type RouterOptions, type SentMessage, SqliteMuteStore, type StoredMute, type TextContent, User, type UserData, type VideoContent, WhaNextApp, WhaNextError, type WhaNextErrorCode, type WhatsAppProvider, create, defineCommand, defineCommands, loadCommands, toWhaNextError };
package/dist/index.js CHANGED
@@ -1,6 +1,10 @@
1
1
  // src/cache/memory-cache.ts
2
2
  var MemoryCache = class {
3
3
  #entries = /* @__PURE__ */ new Map();
4
+ #maxEntries;
5
+ constructor(options = {}) {
6
+ this.#maxEntries = Math.max(1, options.maxEntries ?? 1e3);
7
+ }
4
8
  async get(key) {
5
9
  const entry = this.#entries.get(key);
6
10
  if (!entry) {
@@ -10,6 +14,8 @@ var MemoryCache = class {
10
14
  this.#entries.delete(key);
11
15
  return void 0;
12
16
  }
17
+ this.#entries.delete(key);
18
+ this.#entries.set(key, entry);
13
19
  return entry.value;
14
20
  }
15
21
  async set(key, value, ttlMs) {
@@ -18,6 +24,11 @@ var MemoryCache = class {
18
24
  entry.expiresAt = Date.now() + ttlMs;
19
25
  }
20
26
  this.#entries.set(key, entry);
27
+ while (this.#entries.size > this.#maxEntries) {
28
+ const oldest = this.#entries.keys().next().value;
29
+ if (oldest === void 0) return;
30
+ this.#entries.delete(oldest);
31
+ }
21
32
  }
22
33
  async delete(key) {
23
34
  this.#entries.delete(key);
@@ -932,6 +943,7 @@ var GroupService = class {
932
943
  #provider;
933
944
  #cache;
934
945
  #ttlMs;
946
+ #requests = /* @__PURE__ */ new Map();
935
947
  constructor(provider, cache, ttlMs = 3e5) {
936
948
  this.#provider = provider;
937
949
  this.#cache = cache;
@@ -979,9 +991,17 @@ var GroupService = class {
979
991
  return cached;
980
992
  }
981
993
  }
982
- const group = await this.#provider.getGroup(groupId);
983
- await this.#cache.set(key, group, this.#ttlMs);
984
- return group;
994
+ const pending = this.#requests.get(key);
995
+ if (pending) {
996
+ return pending;
997
+ }
998
+ const request = this.#loadMetadata(key, groupId);
999
+ this.#requests.set(key, request);
1000
+ try {
1001
+ return await request;
1002
+ } finally {
1003
+ this.#requests.delete(key);
1004
+ }
985
1005
  }
986
1006
  async isAdmin(groupId, memberIds) {
987
1007
  if (!groupId.endsWith("@g.us")) {
@@ -1030,6 +1050,11 @@ var GroupService = class {
1030
1050
  #key(groupId) {
1031
1051
  return `group:${groupId}`;
1032
1052
  }
1053
+ async #loadMetadata(key, groupId) {
1054
+ const group = await this.#provider.getGroup(groupId);
1055
+ await this.#cache.set(key, group, this.#ttlMs);
1056
+ return group;
1057
+ }
1033
1058
  #matchesParticipant(participant, identities) {
1034
1059
  const participantIds = [participant.id, participant.lid, participant.phoneNumber].filter((identity) => identity !== void 0);
1035
1060
  return identities.some((identity) => participantIds.some((participantId) => identitiesMatch(identity, participantId)));
@@ -1051,6 +1076,10 @@ var MediaService = class {
1051
1076
  audio(chatId, content) {
1052
1077
  return this.#provider.sendMessage(chatId, content);
1053
1078
  }
1079
+ download(message) {
1080
+ const key = "keys" in message ? message.keys : message;
1081
+ return this.#provider.downloadMedia(key);
1082
+ }
1054
1083
  };
1055
1084
 
1056
1085
  // src/services/member-service.ts
@@ -1141,6 +1170,14 @@ var MessageService = class {
1141
1170
  const key = "keys" in message ? message.keys : message;
1142
1171
  return this.#provider.deleteMessage(key);
1143
1172
  }
1173
+ react(message, emoji) {
1174
+ const key = "keys" in message ? message.keys : message;
1175
+ return this.#provider.reactToMessage(key, emoji);
1176
+ }
1177
+ unreact(message) {
1178
+ const key = "keys" in message ? message.keys : message;
1179
+ return this.#provider.reactToMessage(key);
1180
+ }
1144
1181
  text(chatId, text, mentions) {
1145
1182
  const content = { text };
1146
1183
  if (mentions !== void 0) {
@@ -1199,7 +1236,9 @@ var WhaNextApp = class {
1199
1236
  this.#provider = provider;
1200
1237
  this.#phone = options.phone;
1201
1238
  this.logger = logger;
1202
- const cache = options.cache?.store ?? new MemoryCache();
1239
+ const cache = options.cache?.store ?? new MemoryCache(
1240
+ options.cache?.memoryMaxEntries === void 0 ? void 0 : { maxEntries: options.cache.memoryMaxEntries }
1241
+ );
1203
1242
  this.group = new GroupService(provider, cache, options.cache?.groupTtlMs);
1204
1243
  this.member = new MemberService(provider, this.group);
1205
1244
  this.message = new MessageService(provider);
@@ -1307,6 +1346,10 @@ var WhaNextApp = class {
1307
1346
  await this.#events.emit("connection", update);
1308
1347
  });
1309
1348
  this.#provider.on("groupChanged", ({ groupId }) => this.group.invalidate(groupId));
1349
+ this.#provider.on("groupParticipantsChanged", async (change) => {
1350
+ await this.group.invalidate(change.groupId);
1351
+ await this.#events.emit("groupParticipantsChanged", change);
1352
+ });
1310
1353
  this.#provider.on("call", async (call) => {
1311
1354
  this.logger.debug("Call received", {
1312
1355
  callId: call.id,
@@ -1401,6 +1444,7 @@ var Browser = /* @__PURE__ */ ((Browser2) => {
1401
1444
  import {
1402
1445
  Browsers,
1403
1446
  DisconnectReason,
1447
+ downloadMediaMessage,
1404
1448
  makeWASocket,
1405
1449
  proto,
1406
1450
  useMultiFileAuthState
@@ -1611,6 +1655,7 @@ var BaileysProvider = class {
1611
1655
  #events = new TypedEventEmitter();
1612
1656
  #logger;
1613
1657
  #messageStore = /* @__PURE__ */ new Map();
1658
+ #messageCacheSize;
1614
1659
  #socket;
1615
1660
  #saveCredentials;
1616
1661
  #saveQueue = Promise.resolve();
@@ -1621,6 +1666,7 @@ var BaileysProvider = class {
1621
1666
  constructor(options) {
1622
1667
  this.#options = options;
1623
1668
  this.#logger = options.logger ?? new Logger("silent");
1669
+ this.#messageCacheSize = Math.max(1, options.messageCacheSize ?? 1e3);
1624
1670
  }
1625
1671
  on(event, listener) {
1626
1672
  return this.#events.on(event, listener);
@@ -1645,7 +1691,7 @@ var BaileysProvider = class {
1645
1691
  markOnlineOnConnect: false,
1646
1692
  enableAutoSessionRecreation: true,
1647
1693
  enableRecentMessageCache: true,
1648
- getMessage: async (key) => key.id ? this.#messageStore.get(key.id) : void 0
1694
+ getMessage: async (key) => this.#messageStore.get(this.#messageStoreKey(key))?.message ?? void 0
1649
1695
  });
1650
1696
  this.#socket = socket;
1651
1697
  this.#bind(socket);
@@ -1724,6 +1770,39 @@ var BaileysProvider = class {
1724
1770
  const result = await socket.sendMessage(chatId, this.#toContent(content), options);
1725
1771
  return this.#sent(result);
1726
1772
  }
1773
+ async reactToMessage(key, emoji) {
1774
+ const result = await this.#requireSocket().sendMessage(key.chatId, {
1775
+ react: {
1776
+ text: emoji ?? "",
1777
+ key: this.#toWaKey(key)
1778
+ }
1779
+ });
1780
+ return this.#sent(result);
1781
+ }
1782
+ async downloadMedia(key) {
1783
+ const message = this.#messageStore.get(this.#messageStoreKey(key));
1784
+ if (!message?.message) {
1785
+ throw new WhaNextError(
1786
+ "MEDIA_NOT_AVAILABLE",
1787
+ "The media is unavailable. Download it from the received message event while it is cached.",
1788
+ { recoverable: true }
1789
+ );
1790
+ }
1791
+ const data = await downloadMediaMessage(message, "buffer", {}, {
1792
+ reuploadRequest: (current) => this.#requireSocket().updateMediaMessage(current),
1793
+ logger: createBaileysLogger(this.#logger.child("media"))
1794
+ });
1795
+ const media = normalizeBaileysMessage(message)?.media;
1796
+ if (!media) {
1797
+ throw new WhaNextError("MEDIA_NOT_AVAILABLE", "The selected message does not contain media.");
1798
+ }
1799
+ return {
1800
+ data,
1801
+ kind: media.kind,
1802
+ ...media.mimetype ? { mimetype: media.mimetype } : {},
1803
+ ...media.fileName ? { fileName: media.fileName } : {}
1804
+ };
1805
+ }
1727
1806
  async editMessage(key, content) {
1728
1807
  const result = await this.#requireSocket().sendMessage(key.chatId, {
1729
1808
  text: content,
@@ -1792,7 +1871,6 @@ var BaileysProvider = class {
1792
1871
  }
1793
1872
  async setPresence(chatId, state) {
1794
1873
  const socket = this.#requireSocket();
1795
- await socket.presenceSubscribe(chatId);
1796
1874
  const presence = state === "typing" ? "composing" : state === "recording" ? "recording" : "paused";
1797
1875
  await socket.sendPresenceUpdate(presence, chatId);
1798
1876
  }
@@ -1809,7 +1887,7 @@ var BaileysProvider = class {
1809
1887
  socket.ev.on("messages.upsert", ({ messages, type }) => {
1810
1888
  if (type !== "notify") return;
1811
1889
  for (const raw of messages) {
1812
- if (raw.key.id && raw.message) this.#remember(raw.key.id, raw.message);
1890
+ if (raw.key.id && raw.message) this.#remember(raw);
1813
1891
  const message = normalizeBaileysMessage(raw);
1814
1892
  if (message) void this.#events.emit("message", message);
1815
1893
  }
@@ -1819,7 +1897,10 @@ var BaileysProvider = class {
1819
1897
  if (group.id) void this.#events.emit("groupChanged", { groupId: group.id });
1820
1898
  }
1821
1899
  });
1822
- socket.ev.on("group-participants.update", ({ id }) => {
1900
+ socket.ev.on("group-participants.update", (update) => {
1901
+ const change = this.#groupParticipantsChanged(update);
1902
+ void this.#events.emit("groupParticipantsChanged", change);
1903
+ const { id } = update;
1823
1904
  void this.#events.emit("groupChanged", { groupId: id });
1824
1905
  });
1825
1906
  socket.ev.on("call", (calls) => {
@@ -1949,7 +2030,7 @@ var BaileysProvider = class {
1949
2030
  if (!message?.key.id || !message.key.remoteJid) {
1950
2031
  throw new WhaNextError("PROVIDER_ERROR", "WhatsApp did not confirm the sent message.");
1951
2032
  }
1952
- if (message.message) this.#remember(message.key.id, message.message);
2033
+ if (message.message) this.#remember(message);
1953
2034
  return {
1954
2035
  id: message.key.id,
1955
2036
  chatId: message.key.remoteJid,
@@ -1968,6 +2049,15 @@ var BaileysProvider = class {
1968
2049
  date: call.date ?? /* @__PURE__ */ new Date()
1969
2050
  };
1970
2051
  }
2052
+ #groupParticipantsChanged(change) {
2053
+ const participantIds = change.participants.map((participant) => participant.id).filter((id) => Boolean(id));
2054
+ return {
2055
+ groupId: change.id,
2056
+ action: change.action,
2057
+ participantIds,
2058
+ ...change.author ? { authorId: change.author } : {}
2059
+ };
2060
+ }
1971
2061
  #callStatus(status) {
1972
2062
  const known = [
1973
2063
  "offer",
@@ -1979,13 +2069,19 @@ var BaileysProvider = class {
1979
2069
  ];
1980
2070
  return known.find((value) => value === status) ?? "timeout";
1981
2071
  }
1982
- #remember(id, message) {
1983
- this.#messageStore.set(id, message);
1984
- if (this.#messageStore.size > 500) {
2072
+ #remember(message) {
2073
+ const key = this.#messageStoreKey(message.key);
2074
+ this.#messageStore.delete(key);
2075
+ this.#messageStore.set(key, message);
2076
+ while (this.#messageStore.size > this.#messageCacheSize) {
1985
2077
  const oldest = this.#messageStore.keys().next().value;
1986
2078
  if (oldest) this.#messageStore.delete(oldest);
1987
2079
  }
1988
2080
  }
2081
+ #messageStoreKey(key) {
2082
+ const chatId = "chatId" in key ? key.chatId : key.remoteJid;
2083
+ return `${chatId ?? ""}:${key.id ?? ""}`;
2084
+ }
1989
2085
  };
1990
2086
 
1991
2087
  // src/app/create.ts
@@ -1995,6 +2091,7 @@ async function create(options = {}) {
1995
2091
  auth: options.auth ?? "./session",
1996
2092
  browser: options.browser ?? "windows" /* Windows */,
1997
2093
  logger: logger.child("provider"),
2094
+ ...options.messageCacheSize !== void 0 ? { messageCacheSize: options.messageCacheSize } : {},
1998
2095
  ...options.reconnect ? { reconnect: options.reconnect } : {}
1999
2096
  });
2000
2097
  return new WhaNextApp(provider, {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cache/memory-cache.ts","../src/errors/error.ts","../src/models/identity.ts","../src/models/user.ts","../src/commands/args-parser.ts","../src/commands/router.ts","../src/logger/logger.ts","../src/mute/mute-service.ts","../src/mute/sqlite-mute-store.ts","../src/provider/event-emitter.ts","../src/services/chat-service.ts","../src/services/group-service.ts","../src/services/media-service.ts","../src/services/member-service.ts","../src/services/message-service.ts","../src/services/user-service.ts","../src/app/whanext-app.ts","../src/auth/browser.ts","../src/provider/baileys/baileys-provider.ts","../src/provider/baileys/baileys-logger.ts","../src/provider/baileys/normalize-message.ts","../src/app/create.ts","../src/commands/command.ts","../src/commands/load-commands.ts"],"sourcesContent":["import type { CacheStore } from '@/cache/cache-store.js';\n\ninterface CacheEntry {\n value: unknown;\n expiresAt?: number;\n}\n\nexport class MemoryCache implements CacheStore {\n readonly #entries = new Map<string, CacheEntry>();\n\n async get<T>(key: string): Promise<T | undefined> {\n const entry = this.#entries.get(key);\n\n if (!entry) {\n return undefined;\n }\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n this.#entries.delete(key);\n return undefined;\n }\n\n return entry.value as T;\n }\n\n async set<T>(key: string, value: T, ttlMs?: number): Promise<void> {\n const entry: CacheEntry = { value };\n\n if (ttlMs !== undefined) {\n entry.expiresAt = Date.now() + ttlMs;\n }\n\n this.#entries.set(key, entry);\n }\n\n async delete(key: string): Promise<void> {\n this.#entries.delete(key);\n }\n\n async clear(): Promise<void> {\n this.#entries.clear();\n }\n}\n","export type WhaNextErrorCode =\n | 'AUTH_INVALID_PHONE'\n | 'AUTH_EXPIRED'\n | 'CONNECTION_CLOSED'\n | 'CONNECTION_FAILED'\n | 'GROUP_NOT_FOUND'\n | 'MEMBER_NOT_FOUND'\n | 'BOT_NOT_ADMIN'\n | 'MESSAGE_NOT_FOUND'\n | 'MUTE_DISABLED'\n | 'STORAGE_ERROR'\n | 'ARGUMENT_MISSING'\n | 'ARGUMENT_INVALID'\n | 'COMMAND_NOT_ALLOWED'\n | 'COMMAND_LOAD_FAILED'\n | 'PROVIDER_ERROR'\n | 'UNKNOWN_ERROR';\n\nexport interface WhaNextErrorOptions {\n cause?: unknown;\n context?: Readonly<Record<string, unknown>>;\n recoverable?: boolean;\n}\n\nexport class WhaNextError extends Error {\n readonly code: WhaNextErrorCode;\n readonly context: Readonly<Record<string, unknown>>;\n readonly recoverable: boolean;\n\n constructor(\n code: WhaNextErrorCode,\n message: string,\n options: WhaNextErrorOptions = {},\n ) {\n super(message, { cause: options.cause });\n this.name = 'WhaNextError';\n this.code = code;\n this.context = options.context ?? {};\n this.recoverable = options.recoverable ?? false;\n }\n}\n\nexport function toWhaNextError(\n error: unknown,\n context?: Readonly<Record<string, unknown>>,\n): WhaNextError {\n if (error instanceof WhaNextError) {\n return error;\n }\n\n const message = error instanceof Error ? error.message : 'An unknown error occurred.';\n return new WhaNextError('UNKNOWN_ERROR', message, {\n cause: error,\n ...(context ? { context } : {}),\n });\n}\n","export function normalizeIdentity(identity: string): string {\n const value = identity.trim().toLowerCase();\n const separator = value.lastIndexOf('@');\n\n if (separator === -1) {\n return value.replace(/\\D/g, '');\n }\n\n const user = value.slice(0, separator).replace(/:\\d+$/, '');\n const rawServer = value.slice(separator + 1);\n const server = rawServer === 'c.us' ? 's.whatsapp.net' : rawServer;\n return `${user}@${server}`;\n}\n\nexport function identityUsername(identity: string): string {\n const normalized = normalizeIdentity(identity);\n const separator = normalized.lastIndexOf('@');\n return separator === -1 ? normalized : normalized.slice(0, separator);\n}\n\nexport function identityPhoneNumber(identity: string): string | undefined {\n const normalized = normalizeIdentity(identity);\n\n if (normalized.endsWith('@lid')) {\n return undefined;\n }\n\n const username = identityUsername(normalized);\n return /^\\d+$/.test(username) ? username : undefined;\n}\n\nexport function identitiesMatch(left: string, right: string): boolean {\n return normalizeIdentity(left) === normalizeIdentity(right);\n}\n\nexport function uniqueIdentities(identities: ReadonlyArray<string | null | undefined>): string[] {\n const values = identities.filter((identity): identity is string => Boolean(identity));\n return [...new Map(values.map((identity) => [normalizeIdentity(identity), identity])).values()];\n}\n","import {\n identityPhoneNumber,\n identityUsername,\n identitiesMatch,\n uniqueIdentities,\n} from '@/models/identity.js';\n\nexport interface UserData {\n id: string;\n identities?: readonly string[];\n jid?: string;\n lid?: string;\n phoneNumber?: string;\n name?: string;\n}\n\nexport class User {\n readonly id: string;\n readonly identities: string[];\n readonly jid: string | undefined;\n readonly lid: string | undefined;\n readonly phoneNumber: string | undefined;\n readonly name: string | undefined;\n\n constructor(data: UserData) {\n const identities = uniqueIdentities([\n data.id,\n data.jid,\n data.lid,\n data.phoneNumber,\n ...(data.identities ?? []),\n ]);\n\n this.jid = data.jid ?? identities.find((identity) =>\n identity.endsWith('@s.whatsapp.net') || identity.endsWith('@c.us'));\n this.lid = data.lid ?? identities.find((identity) => identity.endsWith('@lid'));\n this.phoneNumber = data.phoneNumber ?? this.jid;\n this.name = data.name;\n this.id = this.jid ?? this.phoneNumber ?? this.lid ?? data.id;\n this.identities = identities;\n }\n\n get mentionId(): string {\n return this.jid ?? this.phoneNumber ?? this.lid ?? this.id;\n }\n\n get mention(): string {\n return `@${this.username}`;\n }\n\n get phone(): string | undefined {\n return this.phoneNumber ? identityPhoneNumber(this.phoneNumber) : undefined;\n }\n\n get username(): string {\n return identityUsername(this.mentionId);\n }\n\n get displayName(): string {\n return this.name ?? this.mention;\n }\n\n matches(identity: string | User): boolean {\n const candidates = typeof identity === 'string' ? [identity] : identity.identities;\n return this.identities.some((ownIdentity) =>\n candidates.some((candidate) => identitiesMatch(ownIdentity, candidate)));\n }\n\n toJSON(): UserData {\n return {\n id: this.id,\n identities: this.identities,\n ...(this.jid ? { jid: this.jid } : {}),\n ...(this.lid ? { lid: this.lid } : {}),\n ...(this.phoneNumber ? { phoneNumber: this.phoneNumber } : {}),\n ...(this.name ? { name: this.name } : {}),\n };\n }\n\n static fromIdentities(identities: readonly string[]): User {\n const [id] = identities;\n\n if (!id) {\n throw new TypeError('A user requires at least one identity.');\n }\n\n return new User({ id, identities });\n }\n\n static fromPhoneNumber(phoneNumber: string): User {\n const normalized = phoneNumber.replace(/\\D/g, '');\n\n if (normalized.length < 8) {\n throw new TypeError('A user phone number must include country and area codes.');\n }\n\n return User.fromIdentities([`${normalized}@s.whatsapp.net`]);\n }\n}\n","import { WhaNextError } from '@/errors/error.js';\nimport { User } from '@/models/user.js';\n\nexport interface ArgumentOptions {\n optional?: boolean;\n}\n\nexport class ArgsParser {\n readonly #values: string[];\n #cursor = 0;\n\n constructor(values: readonly string[]) {\n this.#values = [...values];\n }\n\n get remaining(): number {\n return this.#values.length - this.#cursor;\n }\n\n peek(): string | undefined {\n return this.#values[this.#cursor];\n }\n\n skip(count = 1): this {\n this.#cursor = Math.min(this.#values.length, this.#cursor + Math.max(0, count));\n return this;\n }\n\n string(name = 'argument', options: ArgumentOptions = {}): string | undefined {\n return this.#consume(name, options);\n }\n\n number(name = 'number', options: ArgumentOptions = {}): number | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n const value = Number(raw);\n\n if (!Number.isFinite(value)) {\n throw new WhaNextError('ARGUMENT_INVALID', `The argument \"${name}\" must be a number.`, {\n context: { name, received: raw },\n });\n }\n\n return value;\n }\n\n boolean(name = 'boolean', options: ArgumentOptions = {}): boolean | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n const normalized = raw.toLowerCase();\n const truthy = new Set(['true', 'on', 'yes', 'sim', '1']);\n const falsy = new Set(['false', 'off', 'no', 'não', 'nao', '0']);\n\n if (truthy.has(normalized)) {\n return true;\n }\n\n if (falsy.has(normalized)) {\n return false;\n }\n\n throw new WhaNextError('ARGUMENT_INVALID', `The argument \"${name}\" must be a boolean.`, {\n context: { name, received: raw },\n });\n }\n\n enum<const Values extends readonly string[]>(\n values: Values,\n name = 'option',\n options: ArgumentOptions = {},\n ): Values[number] | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n if (!values.includes(raw)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n `The argument \"${name}\" must be one of: ${values.join(', ')}.`,\n {\n context: { name, received: raw, expected: values },\n },\n );\n }\n\n return raw as Values[number];\n }\n\n user(name?: string): User;\n user(name: string, options: { optional: true }): User | undefined;\n user(name = 'user', options: ArgumentOptions = {}): User | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n const normalized = raw.replace(/^@/, '').replace(/\\D/g, '');\n\n if (normalized.length < 8) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n `The argument \"${name}\" must be a mention or phone number.`,\n {\n context: { name, received: raw },\n },\n );\n }\n\n return User.fromPhoneNumber(normalized);\n }\n\n duration(name = 'duration', options: ArgumentOptions = {}): number | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n const normalized = raw.toLowerCase();\n const permanent = new Set([\n 'forever',\n 'indefinido',\n 'permanent',\n 'permanente',\n 'sempre',\n ]);\n\n if (permanent.has(normalized)) {\n return undefined;\n }\n\n const match = /^(\\d+)(ms|s|m|h|d)$/.exec(normalized);\n\n if (!match) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n `The argument \"${name}\" must be a duration such as 30s or 5m.`,\n {\n context: { name, received: raw },\n },\n );\n }\n\n const amount = Number(match[1]);\n const unit = match[2] as 'ms' | 's' | 'm' | 'h' | 'd';\n const multiplier = { ms: 1, s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000 }[unit];\n return amount * multiplier;\n }\n\n rest(): string {\n const value = this.#values.slice(this.#cursor).join(' ');\n this.#cursor = this.#values.length;\n return value;\n }\n\n #consume(name: string, options: ArgumentOptions): string | undefined {\n const value = this.#values[this.#cursor];\n\n if (value === undefined) {\n if (options.optional) {\n return undefined;\n }\n\n throw new WhaNextError('ARGUMENT_MISSING', `The argument \"${name}\" is required.`, {\n context: { name, position: this.#cursor },\n });\n }\n\n this.#cursor += 1;\n return value;\n }\n}\n","import { ArgsParser } from '@/commands/args-parser.js';\nimport type { CommandDefinition } from '@/commands/command.js';\nimport {\n WhaNextError,\n toWhaNextError,\n} from '@/errors/error.js';\nimport type { Message } from '@/models/message.js';\nimport type { GroupService } from '@/services/group-service.js';\n\nexport interface RouterOptions {\n prefix?: string;\n onError?: (error: WhaNextError, message: Message) => void | Promise<void>;\n}\n\nexport class CommandRouter {\n readonly #commands = new Map<string, CommandDefinition>();\n readonly #prefix: string;\n readonly #group: GroupService;\n readonly #onError?: RouterOptions['onError'];\n\n constructor(group: GroupService, options: RouterOptions = {}) {\n this.#group = group;\n this.#prefix = options.prefix ?? '!';\n this.#onError = options.onError;\n\n if (this.#prefix.length === 0 || /\\s/.test(this.#prefix)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n 'The command prefix cannot be empty or contain whitespace.',\n {\n context: { prefix: this.#prefix },\n },\n );\n }\n }\n\n command(definition: CommandDefinition): this {\n const names = [definition.name, ...(definition.aliases ?? [])];\n\n for (const name of names) {\n const normalized = name.toLowerCase();\n\n if (this.#commands.has(normalized)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n `The command \"${normalized}\" is already registered.`,\n );\n }\n\n this.#commands.set(normalized, definition);\n }\n\n return this;\n }\n\n async dispatch(message: Message): Promise<boolean> {\n const text = message.text?.trim();\n\n if (!text?.startsWith(this.#prefix)) {\n return false;\n }\n\n const tokens = tokenize(text.slice(this.#prefix.length));\n const name = tokens.shift()?.toLowerCase();\n\n if (!name) {\n return false;\n }\n\n const command = this.#commands.get(name);\n\n if (!command) {\n return false;\n }\n\n try {\n await this.#authorize(command, message);\n await command.execute(message, new ArgsParser(tokens));\n return true;\n } catch (error) {\n const normalized = toWhaNextError(error, { command: command.name, messageId: message.id });\n\n if (this.#onError) {\n await this.#onError(normalized, message);\n return true;\n }\n\n throw normalized;\n }\n }\n\n async #authorize(command: CommandDefinition, message: Message): Promise<void> {\n if (command.onlyGroup && !message.isGroup) {\n throw new WhaNextError('COMMAND_NOT_ALLOWED', 'This command can only be used in groups.');\n }\n\n if (command.onlyPrivate && message.isGroup) {\n throw new WhaNextError(\n 'COMMAND_NOT_ALLOWED',\n 'This command can only be used in private chats.',\n );\n }\n\n if (command.onlyAdmin && !(await this.#group.isAdmin(message.chatId, message.senderIds))) {\n throw new WhaNextError(\n 'COMMAND_NOT_ALLOWED',\n 'This command can only be used by group administrators.',\n );\n }\n\n if (command.botMustBeAdmin && !(await this.#group.isCurrentUserAdmin(message.chatId))) {\n throw new WhaNextError(\n 'BOT_NOT_ADMIN',\n 'The connected WhatsApp account must be a group administrator.',\n );\n }\n }\n}\n\nfunction tokenize(input: string): string[] {\n return input\n .match(/(?:[^\\s\"']+|\"[^\"]*\"|'[^']*')+/g)\n ?.map((token) => token.replace(/^([\"'])(.*)\\1$/, '$2'))\n ?? [];\n}\n","import { WhaNextError } from '@/errors/error.js';\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\nexport type LogFormat = 'pretty' | 'json';\nexport type LogContext = Readonly<Record<string, unknown>>;\n\nexport interface LogEntry {\n timestamp: string;\n level: Exclude<LogLevel, 'silent'>;\n scope: string;\n message: string;\n context: LogContext;\n}\n\nexport type LogWriter = (entry: LogEntry) => unknown;\n\nexport interface LoggerOptions {\n level?: LogLevel;\n format?: LogFormat;\n writer?: LogWriter;\n scope?: string;\n redact?: readonly string[];\n}\n\nexport type LoggerConfig = LogLevel | LoggerOptions;\n\nconst priorities: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n silent: Number.POSITIVE_INFINITY,\n};\n\nconst defaultRedactions = [\n 'auth',\n 'pairingcode',\n 'password',\n 'phone',\n 'secret',\n 'session',\n 'token',\n];\n\ninterface LoggerState {\n level: LogLevel;\n}\n\nexport class Logger {\n #state: LoggerState;\n readonly #scope: string;\n readonly #writer: LogWriter;\n readonly #redactions: Set<string>;\n\n constructor(config: LoggerConfig = 'info') {\n const options = typeof config === 'string' ? { level: config } : config;\n const level = options.level ?? 'info';\n assertLevel(level);\n\n if (options.writer !== undefined && typeof options.writer !== 'function') {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n 'Logger writer must be a function.',\n );\n }\n\n if (options.format !== undefined && !['pretty', 'json'].includes(options.format)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n 'Logger format must be \"pretty\" or \"json\".',\n { context: { format: options.format } },\n );\n }\n\n this.#state = { level };\n this.#scope = options.scope ?? 'whanext';\n this.#redactions = new Set(\n [...defaultRedactions, ...(options.redact ?? [])]\n .map((key) => key.toLowerCase()),\n );\n this.#writer = options.writer ?? consoleWriter(options.format ?? 'pretty');\n }\n\n get level(): LogLevel {\n return this.#state.level;\n }\n\n setLevel(level: LogLevel): this {\n assertLevel(level);\n this.#state.level = level;\n return this;\n }\n\n isEnabled(level: Exclude<LogLevel, 'silent'>): boolean {\n return priorities[level] >= priorities[this.#state.level];\n }\n\n child(scope: string): Logger {\n const childScope = this.#scope ? `${this.#scope}:${scope}` : scope;\n const child = new Logger({\n level: this.#state.level,\n scope: childScope,\n writer: this.#writer,\n redact: [...this.#redactions],\n });\n child.#state = this.#state;\n return child;\n }\n\n debug(message: string, context: LogContext = {}): void {\n this.#write('debug', message, context);\n }\n\n info(message: string, context: LogContext = {}): void {\n this.#write('info', message, context);\n }\n\n warn(message: string, context: LogContext = {}): void {\n this.#write('warn', message, context);\n }\n\n error(message: string, context: LogContext = {}): void {\n this.#write('error', message, context);\n }\n\n #write(\n level: Exclude<LogLevel, 'silent'>,\n message: string,\n context: LogContext,\n ): void {\n if (!this.isEnabled(level)) {\n return;\n }\n\n try {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n scope: this.#scope,\n message,\n context: normalizeContext(context, this.#redactions),\n };\n const result = this.#writer(entry);\n\n if (result instanceof Promise) {\n void result.catch(() => undefined);\n }\n } catch {\n return;\n }\n }\n}\n\nfunction assertLevel(level: LogLevel): void {\n if (!(level in priorities)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n 'Logger level must be debug, info, warn, error or silent.',\n { context: { level } },\n );\n }\n}\n\nfunction consoleWriter(format: LogFormat): LogWriter {\n return (entry) => {\n const method = entry.level === 'debug'\n ? console.debug\n : entry.level === 'info'\n ? console.info\n : entry.level === 'warn'\n ? console.warn\n : console.error;\n\n if (format === 'json') {\n method(JSON.stringify(entry));\n return;\n }\n\n const details = Object.keys(entry.context).length > 0\n ? ` ${JSON.stringify(entry.context)}`\n : '';\n method(\n `[${entry.timestamp}] ${entry.level.toUpperCase()} ${entry.scope} ${entry.message}${details}`,\n );\n };\n}\n\nfunction normalizeContext(\n context: LogContext,\n redactions: ReadonlySet<string>,\n): LogContext {\n const seen = new WeakSet<object>();\n return Object.fromEntries(\n Object.entries(context).map(([key, value]) => [\n key,\n normalizeValue(value, key, redactions, seen),\n ]),\n );\n}\n\nfunction normalizeValue(\n value: unknown,\n key: string,\n redactions: ReadonlySet<string>,\n seen: WeakSet<object>,\n): unknown {\n if (isRedactedKey(key, redactions)) {\n return '[REDACTED]';\n }\n\n if (\n value === null\n || typeof value === 'string'\n || typeof value === 'number'\n || typeof value === 'boolean'\n || value === undefined\n ) {\n return value;\n }\n\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (value instanceof Error) {\n return {\n name: value.name,\n message: value.message,\n ...('code' in value ? { code: value.code } : {}),\n };\n }\n\n if (typeof value !== 'object') {\n return String(value);\n }\n\n if (seen.has(value)) {\n return '[Circular]';\n }\n\n seen.add(value);\n\n if (Array.isArray(value)) {\n return value.map((item) =>\n normalizeValue(item, '', redactions, seen));\n }\n\n return Object.fromEntries(\n Object.entries(value).map(([nestedKey, nestedValue]) => [\n nestedKey,\n normalizeValue(nestedValue, nestedKey, redactions, seen),\n ]),\n );\n}\n\nfunction isRedactedKey(\n key: string,\n redactions: ReadonlySet<string>,\n): boolean {\n const normalized = key.toLowerCase();\n return [...redactions].some((redaction) =>\n normalized === redaction\n || normalized.startsWith(redaction)\n || normalized.endsWith(redaction));\n}\n","import { WhaNextError } from '@/errors/error.js';\nimport { normalizeIdentity } from '@/models/identity.js';\nimport type { Message } from '@/models/message.js';\nimport { User } from '@/models/user.js';\nimport type {\n MuteStore,\n StoredMute,\n} from '@/mute/mute-store.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport interface AddMuteOptions {\n durationMs?: number;\n}\n\nexport interface MuteRecord {\n groupId: string;\n user: User;\n createdAt: Date;\n expiresAt: Date | null;\n}\n\nexport type AddMuteResult =\n | {\n ok: true;\n changed: true;\n state: 'muted' | 'updated';\n record: MuteRecord;\n }\n | {\n ok: true;\n changed: false;\n state: 'already_muted';\n record: MuteRecord;\n };\n\nexport type RemoveMuteResult =\n | {\n ok: true;\n changed: true;\n state: 'unmuted';\n }\n | {\n ok: true;\n changed: false;\n state: 'already_unmuted';\n };\n\nexport type MuteChangeResult = AddMuteResult | RemoveMuteResult;\n\nexport interface MuteEnforcement {\n message: Message;\n record: MuteRecord;\n}\n\nexport class MuteService {\n readonly #provider: WhatsAppProvider;\n readonly #store: MuteStore | undefined;\n\n constructor(provider: WhatsAppProvider, store?: MuteStore) {\n this.#provider = provider;\n this.#store = store;\n }\n\n get enabled(): boolean {\n return this.#store !== undefined;\n }\n\n async add(\n groupId: string,\n user: User,\n options: AddMuteOptions = {},\n ): Promise<AddMuteResult> {\n const store = this.#requireStore();\n const now = Date.now();\n\n if (options.durationMs !== undefined && options.durationMs <= 0) {\n throw new WhaNextError('ARGUMENT_INVALID', 'Mute duration must be greater than zero.');\n }\n\n const current = await this.#findActive(groupId, user.identities);\n\n if (current && current.expiresAt === null && options.durationMs === undefined) {\n return {\n ok: true,\n changed: false,\n state: 'already_muted',\n record: this.#record(current),\n };\n }\n\n const stored: StoredMute = {\n key: normalizeIdentity(user.id),\n groupId,\n user: user.toJSON(),\n identities: user.identities,\n createdAt: now,\n expiresAt: options.durationMs === undefined ? null : now + options.durationMs,\n };\n await this.#storage(\n 'upsert',\n () => store.upsert(stored),\n { groupId, userId: user.id },\n );\n return {\n ok: true,\n changed: true,\n state: current ? 'updated' : 'muted',\n record: this.#record(stored),\n };\n }\n\n async remove(groupId: string, user: User): Promise<RemoveMuteResult> {\n const store = this.#requireStore();\n const changed = await this.#storage(\n 'delete',\n () => store.delete(groupId, user.identities),\n { groupId, userId: user.id },\n );\n\n if (changed) {\n return {\n ok: true,\n changed: true,\n state: 'unmuted',\n };\n }\n\n return {\n ok: true,\n changed: false,\n state: 'already_unmuted',\n };\n }\n\n async get(groupId: string, user: User): Promise<MuteRecord | undefined> {\n this.#requireStore();\n const stored = await this.#findActive(groupId, user.identities);\n return stored ? this.#record(stored) : undefined;\n }\n\n async isMuted(groupId: string, user: User): Promise<boolean> {\n return (await this.get(groupId, user)) !== undefined;\n }\n\n async enforce(message: Message): Promise<MuteEnforcement | undefined> {\n if (!this.#store || !message.isGroup || message.keys.fromMe) {\n return undefined;\n }\n\n const stored = await this.#findActive(message.chatId, message.sender.identities);\n\n if (!stored) {\n return undefined;\n }\n\n try {\n await this.#provider.deleteMessage(message.keys);\n } catch (error) {\n throw new WhaNextError(\n 'PROVIDER_ERROR',\n 'Could not delete a message sent by a muted member.',\n {\n cause: error,\n context: {\n groupId: message.chatId,\n messageId: message.id,\n userId: message.sender.id,\n },\n recoverable: true,\n },\n );\n }\n\n return {\n message,\n record: this.#record(stored),\n };\n }\n\n async purgeExpired(): Promise<number> {\n const store = this.#requireStore();\n return this.#storage(\n 'purge',\n () => store.purgeExpired(Date.now()),\n );\n }\n\n async close(): Promise<void> {\n if (this.#store?.close) {\n await this.#storage('close', () => this.#store?.close?.());\n }\n }\n\n #record(stored: StoredMute): MuteRecord {\n return {\n groupId: stored.groupId,\n user: new User(stored.user),\n createdAt: new Date(stored.createdAt),\n expiresAt: stored.expiresAt === null ? null : new Date(stored.expiresAt),\n };\n }\n\n async #findActive(\n groupId: string,\n identities: readonly string[],\n ): Promise<StoredMute | undefined> {\n const stored = await this.#storage(\n 'find',\n () => this.#store?.find(groupId, identities),\n { groupId },\n );\n\n if (!stored) {\n return undefined;\n }\n\n if (stored.expiresAt !== null && stored.expiresAt <= Date.now()) {\n await this.#storage(\n 'delete_expired',\n () => this.#store?.delete(groupId, stored.identities),\n { groupId },\n );\n return undefined;\n }\n\n return stored;\n }\n\n #requireStore(): MuteStore {\n if (!this.#store) {\n throw new WhaNextError(\n 'MUTE_DISABLED',\n 'Mute is disabled. Enable it in create({ mute: { enabled: true } }).',\n );\n }\n\n return this.#store;\n }\n\n async #storage<Result>(\n action: string,\n operation: () => Result | Promise<Result>,\n context: Readonly<Record<string, unknown>> = {},\n ): Promise<Result> {\n try {\n return await operation();\n } catch (error) {\n throw new WhaNextError(\n 'STORAGE_ERROR',\n `Mute storage operation \"${action}\" failed.`,\n {\n cause: error,\n context: { action, ...context },\n recoverable: true,\n },\n );\n }\n }\n}\n","import { mkdirSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport {\n dirname,\n resolve,\n} from 'node:path';\nimport type { DatabaseSync as NodeDatabaseSync } from 'node:sqlite';\nimport { WhaNextError } from '@/errors/error.js';\nimport { normalizeIdentity } from '@/models/identity.js';\nimport type {\n MuteStore,\n StoredMute,\n} from '@/mute/mute-store.js';\n\ninterface MuteRow {\n mute_key: string;\n group_id: string;\n user_json: string;\n created_at: number;\n expires_at: number | null;\n}\n\nexport class SqliteMuteStore implements MuteStore {\n readonly #database: NodeDatabaseSync;\n\n constructor(path = './data/whanext.sqlite') {\n const databasePath = path === ':memory:' ? path : resolve(path);\n\n if (databasePath !== ':memory:') {\n mkdirSync(dirname(databasePath), { recursive: true });\n }\n\n let database: NodeDatabaseSync | undefined;\n\n try {\n const require = createRequire(import.meta.url);\n const sqlite = require('node:sqlite') as typeof import('node:sqlite');\n database = new sqlite.DatabaseSync(databasePath);\n database.exec('PRAGMA journal_mode = WAL');\n database.exec('PRAGMA busy_timeout = 5000');\n database.exec(`\n CREATE TABLE IF NOT EXISTS whanext_mutes (\n group_id TEXT NOT NULL,\n identity TEXT NOT NULL,\n mute_key TEXT NOT NULL,\n user_json TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n expires_at INTEGER,\n PRIMARY KEY (group_id, identity)\n ) STRICT;\n CREATE INDEX IF NOT EXISTS whanext_mutes_expiration\n ON whanext_mutes (expires_at);\n CREATE INDEX IF NOT EXISTS whanext_mutes_key\n ON whanext_mutes (group_id, mute_key);\n `);\n } catch (error) {\n database?.close();\n throw new WhaNextError(\n 'STORAGE_ERROR',\n 'Could not initialize the SQLite mute store.',\n {\n cause: error,\n context: { database: databasePath },\n },\n );\n }\n\n this.#database = database;\n }\n\n upsert(mute: StoredMute): void {\n const identities = this.#identities(mute.identities);\n const existingKeys = this.#matchingKeys(mute.groupId, identities);\n\n this.#transaction(() => {\n for (const key of existingKeys) {\n this.#database.prepare(\n 'DELETE FROM whanext_mutes WHERE group_id = ? AND mute_key = ?',\n ).run(mute.groupId, key);\n }\n\n const insert = this.#database.prepare(`\n INSERT OR REPLACE INTO whanext_mutes (\n group_id,\n identity,\n mute_key,\n user_json,\n created_at,\n expires_at\n ) VALUES (?, ?, ?, ?, ?, ?)\n `);\n\n for (const identity of identities) {\n insert.run(\n mute.groupId,\n identity,\n mute.key,\n JSON.stringify(mute.user),\n mute.createdAt,\n mute.expiresAt,\n );\n }\n });\n }\n\n find(groupId: string, identities: readonly string[]): StoredMute | undefined {\n const normalized = this.#identities(identities);\n\n if (normalized.length === 0) {\n return undefined;\n }\n\n const placeholders = normalized.map(() => '?').join(', ');\n const row = this.#database.prepare(`\n SELECT mute_key, group_id, user_json, created_at, expires_at\n FROM whanext_mutes\n WHERE group_id = ? AND identity IN (${placeholders})\n LIMIT 1\n `).get(groupId, ...normalized) as unknown as MuteRow | undefined;\n\n if (!row) {\n return undefined;\n }\n\n if (row.expires_at !== null && row.expires_at <= Date.now()) {\n this.#database.prepare(\n 'DELETE FROM whanext_mutes WHERE group_id = ? AND mute_key = ?',\n ).run(groupId, row.mute_key);\n return undefined;\n }\n\n const identityRows = this.#database.prepare(`\n SELECT identity\n FROM whanext_mutes\n WHERE group_id = ? AND mute_key = ?\n `).all(groupId, row.mute_key) as unknown as Array<{ identity: string }>;\n\n return {\n key: row.mute_key,\n groupId: row.group_id,\n user: JSON.parse(row.user_json) as StoredMute['user'],\n identities: identityRows.map(({ identity }) => identity),\n createdAt: row.created_at,\n expiresAt: row.expires_at,\n };\n }\n\n delete(groupId: string, identities: readonly string[]): boolean {\n const keys = this.#matchingKeys(groupId, this.#identities(identities));\n\n if (keys.length === 0) {\n return false;\n }\n\n this.#transaction(() => {\n const statement = this.#database.prepare(\n 'DELETE FROM whanext_mutes WHERE group_id = ? AND mute_key = ?',\n );\n\n for (const key of keys) {\n statement.run(groupId, key);\n }\n });\n return true;\n }\n\n purgeExpired(now: number): number {\n const result = this.#database.prepare(`\n DELETE FROM whanext_mutes\n WHERE expires_at IS NOT NULL AND expires_at <= ?\n `).run(now);\n return Number(result.changes);\n }\n\n close(): void {\n this.#database.close();\n }\n\n #matchingKeys(groupId: string, identities: readonly string[]): string[] {\n if (identities.length === 0) {\n return [];\n }\n\n const placeholders = identities.map(() => '?').join(', ');\n const rows = this.#database.prepare(`\n SELECT DISTINCT mute_key\n FROM whanext_mutes\n WHERE group_id = ? AND identity IN (${placeholders})\n `).all(groupId, ...identities) as unknown as Array<{ mute_key: string }>;\n return rows.map(({ mute_key }) => mute_key);\n }\n\n #identities(identities: readonly string[]): string[] {\n return [...new Set(identities.map(normalizeIdentity).filter(Boolean))];\n }\n\n #transaction(operation: () => void): void {\n this.#database.exec('BEGIN IMMEDIATE');\n\n try {\n operation();\n this.#database.exec('COMMIT');\n } catch (error) {\n this.#database.exec('ROLLBACK');\n throw error;\n }\n }\n}\n","export class TypedEventEmitter<Events extends object> {\n readonly #listeners = new Map<keyof Events, Set<(payload: never) => void | Promise<void>>>();\n\n on<Event extends keyof Events>(\n event: Event,\n listener: (payload: Events[Event]) => void | Promise<void>,\n ): () => void {\n const listeners = this.#listeners.get(event) ?? new Set();\n listeners.add(listener as (payload: never) => void | Promise<void>);\n this.#listeners.set(event, listeners);\n\n return () => listeners.delete(listener as (payload: never) => void | Promise<void>);\n }\n\n async emit<Event extends keyof Events>(event: Event, payload: Events[Event]): Promise<void> {\n const listeners = this.#listeners.get(event);\n\n if (!listeners) {\n return;\n }\n\n await Promise.all([...listeners].map((listener) => listener(payload as never)));\n }\n}\n","import type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport class ChatService {\n readonly #provider: WhatsAppProvider;\n\n constructor(provider: WhatsAppProvider) {\n this.#provider = provider;\n }\n\n typing(chatId: string): Promise<void> {\n return this.#provider.setPresence(chatId, 'typing');\n }\n\n recording(chatId: string): Promise<void> {\n return this.#provider.setPresence(chatId, 'recording');\n }\n\n stop(chatId: string): Promise<void> {\n return this.#provider.setPresence(chatId, 'paused');\n }\n\n stopTyping(chatId: string): Promise<void> {\n return this.stop(chatId);\n }\n\n rejectCall(callId: string, from: string): Promise<void> {\n return this.#provider.rejectCall(callId, from);\n }\n}\n","import type { CacheStore } from '@/cache/cache-store.js';\nimport type {\n ChangeResult,\n GroupAccess,\n GroupSnapshot,\n InviteResult,\n} from '@/models/group.js';\nimport { identitiesMatch } from '@/models/identity.js';\nimport type { MessageKey } from '@/models/message.js';\nimport { User } from '@/models/user.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport class GroupService {\n readonly #provider: WhatsAppProvider;\n readonly #cache: CacheStore;\n readonly #ttlMs: number;\n\n constructor(provider: WhatsAppProvider, cache: CacheStore, ttlMs = 300_000) {\n this.#provider = provider;\n this.#cache = cache;\n this.#ttlMs = ttlMs;\n }\n\n async open(groupId: string): Promise<ChangeResult<'open' | 'already_open'>> {\n const group = await this.metadata(groupId);\n\n if (group.access === 'open') {\n return { ok: true, changed: false, state: 'already_open' };\n }\n\n await this.#provider.setGroupAccess(groupId, 'open');\n await this.invalidate(groupId);\n return { ok: true, changed: true, state: 'open' };\n }\n\n async close(groupId: string): Promise<ChangeResult<'closed' | 'already_closed'>> {\n const group = await this.metadata(groupId);\n\n if (group.access === 'closed') {\n return { ok: true, changed: false, state: 'already_closed' };\n }\n\n await this.#provider.setGroupAccess(groupId, 'closed');\n await this.invalidate(groupId);\n return { ok: true, changed: true, state: 'closed' };\n }\n\n async invite(groupId: string): Promise<InviteResult> {\n const code = await this.#provider.getGroupInviteCode(groupId);\n return { ok: true, code, url: `https://chat.whatsapp.com/${code}` };\n }\n\n async revokeInvite(groupId: string): Promise<InviteResult> {\n const code = await this.#provider.revokeGroupInvite(groupId);\n return { ok: true, code, url: `https://chat.whatsapp.com/${code}` };\n }\n\n async pin(groupId: string, key: MessageKey): Promise<ChangeResult<'pinned'>> {\n await this.#provider.setMessagePin(groupId, key, true);\n return { ok: true, changed: true, state: 'pinned' };\n }\n\n async unpin(groupId: string, key: MessageKey): Promise<ChangeResult<'unpinned'>> {\n await this.#provider.setMessagePin(groupId, key, false);\n return { ok: true, changed: true, state: 'unpinned' };\n }\n\n async metadata(groupId: string, refresh = false): Promise<GroupSnapshot> {\n const key = this.#key(groupId);\n\n if (!refresh) {\n const cached = await this.#cache.get<GroupSnapshot>(key);\n\n if (cached) {\n return cached;\n }\n }\n\n const group = await this.#provider.getGroup(groupId);\n await this.#cache.set(key, group, this.#ttlMs);\n return group;\n }\n\n async isAdmin(\n groupId: string,\n memberIds: string | readonly string[],\n ): Promise<boolean> {\n if (!groupId.endsWith('@g.us')) {\n return false;\n }\n\n const group = await this.metadata(groupId);\n const identities = typeof memberIds === 'string' ? [memberIds] : memberIds;\n const participant = group.participants.find((item) =>\n this.#matchesParticipant(item, identities));\n return participant?.role === 'admin' || participant?.role === 'owner';\n }\n\n async isCurrentUserAdmin(groupId: string): Promise<boolean> {\n const ids = this.#provider.getCurrentUserIds();\n\n if (ids.length === 0 || !groupId.endsWith('@g.us')) {\n return false;\n }\n\n const group = await this.metadata(groupId);\n return group.participants.some((participant) =>\n this.#matchesParticipant(participant, ids)\n && (participant.role === 'admin' || participant.role === 'owner'));\n }\n\n async resolveUser(groupId: string, user: User): Promise<User> {\n if (!groupId.endsWith('@g.us')) {\n return user;\n }\n\n const group = await this.metadata(groupId);\n const participant = group.participants.find((item) =>\n this.#matchesParticipant(item, user.identities));\n\n if (!participant) {\n return user;\n }\n\n return new User({\n id: participant.id,\n identities: [\n participant.id,\n ...(participant.lid ? [participant.lid] : []),\n ...(participant.phoneNumber ? [participant.phoneNumber] : []),\n ],\n ...(participant.lid ? { lid: participant.lid } : {}),\n ...(participant.phoneNumber ? {\n jid: participant.phoneNumber,\n phoneNumber: participant.phoneNumber,\n } : {}),\n ...(user.name ? { name: user.name } : {}),\n });\n }\n\n invalidate(groupId: string): Promise<void> {\n return this.#cache.delete(this.#key(groupId));\n }\n\n #key(groupId: string): string {\n return `group:${groupId}`;\n }\n\n #matchesParticipant(\n participant: GroupSnapshot['participants'][number],\n identities: readonly string[],\n ): boolean {\n const participantIds = [participant.id, participant.lid, participant.phoneNumber]\n .filter((identity): identity is string => identity !== undefined);\n return identities.some((identity) =>\n participantIds.some((participantId) =>\n identitiesMatch(identity, participantId)));\n }\n}\n","import type {\n AudioContent,\n ImageContent,\n SentMessage,\n VideoContent,\n} from '@/models/message.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport class MediaService {\n readonly #provider: WhatsAppProvider;\n\n constructor(provider: WhatsAppProvider) {\n this.#provider = provider;\n }\n\n image(chatId: string, content: ImageContent): Promise<SentMessage> {\n return this.#provider.sendMessage(chatId, content);\n }\n\n video(chatId: string, content: VideoContent): Promise<SentMessage> {\n return this.#provider.sendMessage(chatId, content);\n }\n\n audio(chatId: string, content: AudioContent): Promise<SentMessage> {\n return this.#provider.sendMessage(chatId, content);\n }\n}\n","import { WhaNextError } from '@/errors/error.js';\nimport type {\n ChangeResult,\n GroupParticipant,\n GroupSnapshot,\n MemberActionState,\n} from '@/models/group.js';\nimport { identitiesMatch } from '@/models/identity.js';\nimport type { User } from '@/models/user.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\nimport type { GroupService } from '@/services/group-service.js';\n\nexport class MemberService {\n readonly #provider: WhatsAppProvider;\n readonly #group: GroupService;\n\n constructor(provider: WhatsAppProvider, group: GroupService) {\n this.#provider = provider;\n this.#group = group;\n }\n\n async remove(groupId: string, member: string | User): Promise<ChangeResult<MemberActionState>> {\n const { group, participant } = await this.#participant(groupId, member);\n\n if (!participant) {\n return { ok: true, changed: false, state: 'already_removed' };\n }\n\n await this.#update(groupId, this.#actionId(group, participant), 'remove');\n await this.#group.invalidate(groupId);\n return { ok: true, changed: true, state: 'removed' };\n }\n\n async promote(groupId: string, member: string | User): Promise<ChangeResult<MemberActionState>> {\n const { group, participant } = await this.#participant(groupId, member);\n\n if (!participant) {\n return { ok: true, changed: false, state: 'not_in_group' };\n }\n\n if (participant.role === 'admin' || participant.role === 'owner') {\n return { ok: true, changed: false, state: 'already_admin' };\n }\n\n await this.#update(groupId, this.#actionId(group, participant), 'promote');\n await this.#group.invalidate(groupId);\n return { ok: true, changed: true, state: 'promoted' };\n }\n\n async demote(groupId: string, member: string | User): Promise<ChangeResult<MemberActionState>> {\n const { group, participant } = await this.#participant(groupId, member);\n\n if (!participant) {\n return { ok: true, changed: false, state: 'not_in_group' };\n }\n\n if (participant.role === 'member') {\n return { ok: true, changed: false, state: 'not_admin' };\n }\n\n await this.#update(groupId, this.#actionId(group, participant), 'demote');\n await this.#group.invalidate(groupId);\n return { ok: true, changed: true, state: 'demoted' };\n }\n\n async #participant(groupId: string, member: string | User): Promise<{\n group: GroupSnapshot;\n participant: GroupParticipant | undefined;\n }> {\n const group = await this.#group.metadata(groupId);\n const memberIds = typeof member === 'string' ? [member] : member.identities;\n const participant = group.participants.find((item) =>\n [item.id, item.lid, item.phoneNumber]\n .filter((identity): identity is string => identity !== undefined)\n .some((identity) =>\n memberIds.some((memberId) => identitiesMatch(identity, memberId))));\n return { group, participant };\n }\n\n #actionId(group: GroupSnapshot, participant: GroupParticipant): string {\n if (group.addressingMode === 'lid') {\n return participant.lid\n ?? (participant.id.endsWith('@lid')\n ? participant.id\n : participant.phoneNumber ?? participant.id);\n }\n\n return participant.phoneNumber\n ?? (participant.id.endsWith('@s.whatsapp.net')\n ? participant.id\n : participant.lid ?? participant.id);\n }\n\n async #update(\n groupId: string,\n memberId: string,\n action: 'remove' | 'promote' | 'demote',\n ): Promise<void> {\n const result = await this.#provider.updateParticipant(groupId, memberId, action);\n\n if (!result.success) {\n throw new WhaNextError(\n 'PROVIDER_ERROR',\n `WhatsApp rejected the member action with status ${result.status}.`,\n {\n context: { groupId, memberId, action, status: result.status },\n recoverable: true,\n },\n );\n }\n }\n}\n","import type {\n MentionTarget,\n Message,\n MessageContent,\n MessageKey,\n SentMessage,\n TextContent,\n} from '@/models/message.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport class MessageService {\n readonly #provider: WhatsAppProvider;\n\n constructor(provider: WhatsAppProvider) {\n this.#provider = provider;\n }\n\n send(chatId: string, content: MessageContent): Promise<SentMessage> {\n return this.#provider.sendMessage(chatId, content);\n }\n\n reply(message: Message, content: MessageContent): Promise<SentMessage> {\n return this.#provider.sendMessage(message.chatId, content, message.keys);\n }\n\n edit(message: Message | SentMessage | MessageKey, text: string): Promise<SentMessage> {\n const key = 'keys' in message ? message.keys : message;\n return this.#provider.editMessage(key, text);\n }\n\n delete(message: Message | SentMessage | MessageKey): Promise<void> {\n const key = 'keys' in message ? message.keys : message;\n return this.#provider.deleteMessage(key);\n }\n\n text(chatId: string, text: string, mentions?: MentionTarget[]): Promise<SentMessage> {\n const content: TextContent = { text };\n\n if (mentions !== undefined) {\n content.mentions = mentions;\n }\n\n return this.send(chatId, content);\n }\n}\n","import type { ArgsParser } from '@/commands/args-parser.js';\nimport type { Message } from '@/models/message.js';\nimport { User } from '@/models/user.js';\nimport type { GroupService } from '@/services/group-service.js';\n\nexport class UserService {\n readonly #group: GroupService;\n\n constructor(group: GroupService) {\n this.#group = group;\n }\n\n async resolve(message: Message, args: ArgsParser): Promise<User> {\n const mentioned = message.mentionedUsers[0];\n let user: User;\n\n if (mentioned) {\n if (args.peek()?.startsWith('@')) {\n args.skip();\n }\n\n user = mentioned;\n } else if (message.quoted?.sender) {\n user = message.quoted.sender;\n } else {\n user = args.user('membro');\n }\n\n return this.#group.resolveUser(message.chatId, user);\n }\n\n from(identity: string): User {\n if (!identity.includes('@')) {\n return User.fromPhoneNumber(identity);\n }\n\n return User.fromIdentities([identity]);\n }\n}\n","import type { CacheOptions } from '@/cache/cache-store.js';\nimport { MemoryCache } from '@/cache/memory-cache.js';\nimport {\n CommandRouter,\n type RouterOptions,\n} from '@/commands/router.js';\nimport {\n WhaNextError,\n toWhaNextError,\n} from '@/errors/error.js';\nimport {\n Logger,\n type LogLevel,\n type LoggerConfig,\n} from '@/logger/logger.js';\nimport type { CallEvent } from '@/models/call.js';\nimport type { Message } from '@/models/message.js';\nimport type { MuteOptions } from '@/mute/mute-store.js';\nimport {\n MuteService,\n type MuteEnforcement,\n} from '@/mute/mute-service.js';\nimport { SqliteMuteStore } from '@/mute/sqlite-mute-store.js';\nimport { TypedEventEmitter } from '@/provider/event-emitter.js';\nimport type {\n ConnectionUpdate,\n WhatsAppProvider,\n} from '@/provider/provider.js';\nimport { ChatService } from '@/services/chat-service.js';\nimport { GroupService } from '@/services/group-service.js';\nimport { MediaService } from '@/services/media-service.js';\nimport { MemberService } from '@/services/member-service.js';\nimport { MessageService } from '@/services/message-service.js';\nimport { UserService } from '@/services/user-service.js';\n\nexport interface AppEvents {\n message: Message;\n connection: ConnectionUpdate;\n error: WhaNextError;\n mute: MuteEnforcement;\n call: CallEvent;\n}\n\nexport interface LoginOptions {\n onCode?: (code: string) => void | Promise<void>;\n timeoutMs?: number;\n}\n\nexport type AppHealthStatus = 'idle' | 'starting' | 'ready' | 'stopped';\n\nexport interface AppHealth {\n status: AppHealthStatus;\n state: ConnectionUpdate['state'];\n ready: boolean;\n uptimeMs: number;\n timestamp: Date;\n muteEnabled: boolean;\n logLevel: LogLevel;\n}\n\nexport interface WhaNextAppOptions {\n phone?: string;\n prefix?: string;\n cache?: CacheOptions;\n logger?: LoggerConfig;\n mute?: MuteOptions;\n router?: Omit<RouterOptions, 'prefix'>;\n}\n\nexport class WhaNextApp {\n readonly message: MessageService;\n readonly media: MediaService;\n readonly group: GroupService;\n readonly member: MemberService;\n readonly chat: ChatService;\n readonly user: UserService;\n readonly mute: MuteService;\n readonly logger: Logger;\n readonly #provider: WhatsAppProvider;\n readonly #phone: string | undefined;\n readonly #events = new TypedEventEmitter<AppEvents>();\n readonly #router: CommandRouter;\n readonly #startedAt = Date.now();\n #state: ConnectionUpdate['state'] = 'idle';\n\n constructor(\n provider: WhatsAppProvider,\n options: WhaNextAppOptions = {},\n logger = new Logger(options.logger),\n ) {\n this.#provider = provider;\n this.#phone = options.phone;\n this.logger = logger;\n const cache = options.cache?.store ?? new MemoryCache();\n this.group = new GroupService(provider, cache, options.cache?.groupTtlMs);\n this.member = new MemberService(provider, this.group);\n this.message = new MessageService(provider);\n this.media = new MediaService(provider);\n this.chat = new ChatService(provider);\n this.user = new UserService(this.group);\n const muteEnabled = options.mute?.enabled === true || options.mute?.store !== undefined;\n const muteStore = muteEnabled\n ? options.mute?.store ?? new SqliteMuteStore(options.mute?.database)\n : undefined;\n this.mute = new MuteService(provider, muteStore);\n this.#router = new CommandRouter(this.group, {\n ...options.router,\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n });\n this.#bind();\n this.logger.debug('Application initialized', {\n muteEnabled: this.mute.enabled,\n prefix: options.prefix ?? '!',\n });\n }\n\n get state(): ConnectionUpdate['state'] {\n return this.#state;\n }\n\n get isReady(): boolean {\n return this.#state === 'connected';\n }\n\n health(): AppHealth {\n return {\n status: this.#healthStatus(),\n state: this.#state,\n ready: this.isReady,\n uptimeMs: Date.now() - this.#startedAt,\n timestamp: new Date(),\n muteEnabled: this.mute.enabled,\n logLevel: this.logger.level,\n };\n }\n\n router(): CommandRouter {\n return this.#router;\n }\n\n on<Event extends keyof AppEvents>(\n event: Event,\n listener: (payload: AppEvents[Event]) => void | Promise<void>,\n ) {\n return this.#events.on(event, listener);\n }\n\n async login(options: LoginOptions = {}): Promise<void> {\n if (this.#state === 'connected') {\n return;\n }\n\n this.logger.info('Login started');\n\n let unsubscribe: () => void = () => undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const connected = new Promise<void>((resolve, reject) => {\n unsubscribe = this.#provider.on('connection', (update) => {\n if (update.state === 'connected') resolve();\n if (update.state === 'closed') {\n reject(\n new WhaNextError(\n 'CONNECTION_FAILED',\n 'WhatsApp closed the connection before login completed.',\n {\n cause: update.error,\n recoverable: true,\n },\n ),\n );\n }\n });\n\n timer = setTimeout(() => {\n reject(\n new WhaNextError(\n 'CONNECTION_FAILED',\n 'WhatsApp login timed out.',\n { recoverable: true },\n ),\n );\n }, options.timeoutMs ?? 300_000);\n });\n\n try {\n await this.#provider.connect();\n\n if (this.#phone) {\n const code = await this.#provider.requestPairingCode(this.#phone);\n\n if (code) {\n this.logger.info('Pairing code generated');\n\n if (options.onCode) {\n await options.onCode(code);\n }\n }\n }\n\n await connected;\n } finally {\n unsubscribe();\n if (timer) clearTimeout(timer);\n }\n }\n\n async disconnect(): Promise<void> {\n this.logger.info('Disconnecting application');\n\n try {\n await this.#provider.disconnect();\n } finally {\n await this.mute.close();\n }\n }\n\n #bind(): void {\n this.#provider.on('connection', async (update) => {\n this.#state = update.state;\n this.#logConnection(update);\n await this.#events.emit('connection', update);\n });\n\n this.#provider.on('groupChanged', ({ groupId }) => this.group.invalidate(groupId));\n\n this.#provider.on('call', async (call) => {\n this.logger.debug('Call received', {\n callId: call.id,\n from: call.from,\n status: call.status,\n });\n await this.#events.emit('call', call);\n });\n\n this.#provider.on('message', async (message) => {\n try {\n const enforcement = await this.mute.enforce(message);\n\n if (enforcement) {\n this.logger.info('Muted message deleted', {\n groupId: message.chatId,\n messageId: message.id,\n userId: message.sender.id,\n });\n await this.#events.emit('mute', enforcement);\n return;\n }\n } catch (error) {\n await this.#reportError(error, { messageId: message.id });\n return;\n }\n\n try {\n this.logger.debug('Message received', {\n chatId: message.chatId,\n messageId: message.id,\n senderId: message.sender.id,\n });\n await this.#events.emit('message', message);\n const dispatched = await this.#router.dispatch(message);\n\n if (dispatched) {\n this.logger.debug('Command dispatched', {\n chatId: message.chatId,\n messageId: message.id,\n });\n }\n } catch (error) {\n await this.#reportError(error, { messageId: message.id });\n }\n });\n }\n\n #healthStatus(): AppHealthStatus {\n if (this.#state === 'connected') {\n return 'ready';\n }\n\n if (this.#state === 'closed') {\n return 'stopped';\n }\n\n if (this.#state === 'connecting' || this.#state === 'reconnecting') {\n return 'starting';\n }\n\n return 'idle';\n }\n\n #logConnection(update: ConnectionUpdate): void {\n const context = {\n ...(update.attempt !== undefined ? { attempt: update.attempt } : {}),\n ...(update.error ? { error: update.error } : {}),\n };\n\n if (update.state === 'connected') {\n this.logger.info('WhatsApp connected');\n } else if (update.state === 'reconnecting') {\n this.logger.warn('WhatsApp reconnecting', context);\n } else if (update.state === 'closed' && update.error) {\n this.logger.warn('WhatsApp connection closed', context);\n } else if (update.state === 'closed') {\n this.logger.info('WhatsApp connection closed');\n } else {\n this.logger.debug('WhatsApp connecting', context);\n }\n }\n\n async #reportError(\n error: unknown,\n context: Readonly<Record<string, unknown>>,\n ): Promise<void> {\n const normalized = toWhaNextError(error, context);\n this.logger.error(normalized.message, {\n code: normalized.code,\n ...normalized.context,\n });\n await this.#events.emit('error', normalized);\n }\n}\n","export enum Browser {\n Windows = 'windows',\n MacOS = 'macos',\n Ubuntu = 'ubuntu',\n}\n","import {\n Browsers,\n DisconnectReason,\n makeWASocket,\n proto,\n useMultiFileAuthState,\n type AnyMessageContent,\n type WACallEvent,\n type WAMessage,\n type WAMessageContent,\n type WAMessageKey,\n type WASocket,\n} from '@whiskeysockets/baileys';\nimport { Browser } from '@/auth/browser.js';\nimport { WhaNextError } from '@/errors/error.js';\nimport { Logger } from '@/logger/logger.js';\nimport type { CallEvent, CallStatus } from '@/models/call.js';\nimport type {\n GroupAccess,\n GroupSnapshot,\n} from '@/models/group.js';\nimport type {\n MediaSource,\n MentionTarget,\n MessageContent,\n MessageKey,\n SentMessage,\n} from '@/models/message.js';\nimport {\n createBaileysLogger,\n} from '@/provider/baileys/baileys-logger.js';\nimport {\n normalizeBaileysMessage,\n normalizeKey,\n} from '@/provider/baileys/normalize-message.js';\nimport { TypedEventEmitter } from '@/provider/event-emitter.js';\nimport type {\n ParticipantAction,\n ParticipantUpdateResult,\n PresenceState,\n ProviderEvents,\n WhatsAppProvider,\n} from '@/provider/provider.js';\n\nexport interface BaileysProviderOptions {\n auth: string;\n browser: Browser;\n logger?: Logger;\n reconnect?: {\n enabled?: boolean;\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n };\n}\n\nexport class BaileysProvider implements WhatsAppProvider {\n readonly #options: BaileysProviderOptions;\n readonly #events = new TypedEventEmitter<ProviderEvents>();\n readonly #logger: Logger;\n readonly #messageStore = new Map<string, WAMessageContent>();\n #socket: WASocket | undefined;\n #saveCredentials: (() => Promise<void>) | undefined;\n #saveQueue: Promise<void> = Promise.resolve();\n #intentionalClose = false;\n #reconnectAttempt = 0;\n #reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n #registered = false;\n\n constructor(options: BaileysProviderOptions) {\n this.#options = options;\n this.#logger = options.logger ?? new Logger('silent');\n }\n\n on<Event extends keyof ProviderEvents>(\n event: Event,\n listener: (payload: ProviderEvents[Event]) => void | Promise<void>,\n ) {\n return this.#events.on(event, listener);\n }\n\n async connect(): Promise<void> {\n if (this.#socket) {\n return;\n }\n\n this.#intentionalClose = false;\n await this.#events.emit('connection', {\n state: this.#reconnectAttempt > 0 ? 'reconnecting' : 'connecting',\n attempt: this.#reconnectAttempt,\n });\n\n try {\n const { state, saveCreds } = await useMultiFileAuthState(this.#options.auth);\n this.#registered = state.creds.registered;\n this.#saveCredentials = saveCreds;\n const socket = makeWASocket({\n auth: state,\n browser: this.#browserDescription(),\n logger: createBaileysLogger(this.#logger.child('baileys')),\n markOnlineOnConnect: false,\n enableAutoSessionRecreation: true,\n enableRecentMessageCache: true,\n getMessage: async (key) => key.id ? this.#messageStore.get(key.id) : undefined,\n });\n this.#socket = socket;\n this.#bind(socket);\n } catch (error) {\n this.#socket = undefined;\n throw new WhaNextError('CONNECTION_FAILED', 'Could not start the WhatsApp connection.', {\n cause: error,\n recoverable: true,\n });\n }\n }\n\n async disconnect(): Promise<void> {\n this.#intentionalClose = true;\n if (this.#reconnectTimer) clearTimeout(this.#reconnectTimer);\n const socket = this.#socket;\n this.#socket = undefined;\n\n if (socket) {\n await socket.end(undefined);\n }\n\n await this.#events.emit('connection', { state: 'closed' });\n }\n\n getCurrentUserIds(): string[] {\n const user = this.#socket?.user;\n\n if (!user) {\n return [];\n }\n\n return [user.id, user.lid, user.phoneNumber]\n .filter((id): id is string => Boolean(id))\n .filter((id, index, ids) => ids.indexOf(id) === index);\n }\n\n async requestPairingCode(phone: string): Promise<string> {\n const normalized = phone.replace(/\\D/g, '');\n\n if (normalized.length < 10) {\n throw new WhaNextError(\n 'AUTH_INVALID_PHONE',\n 'The phone number must include its country code.',\n );\n }\n\n if (this.#registered) {\n return '';\n }\n\n const socket = this.#requireSocket();\n\n try {\n await socket.waitForConnectionUpdate(async (update) => Boolean(update.qr), 60_000);\n\n if (socket !== this.#socket) {\n throw new WhaNextError(\n 'CONNECTION_CLOSED',\n 'The WhatsApp socket changed while preparing the pairing code.',\n {\n recoverable: true,\n },\n );\n }\n\n return await socket.requestPairingCode(normalized);\n } catch (error) {\n if (error instanceof WhaNextError) {\n throw error;\n }\n\n throw new WhaNextError(\n 'CONNECTION_FAILED',\n 'Could not request the pairing code after the authentication challenge.',\n {\n cause: error,\n context: { statusCode: this.#statusCode(error) },\n recoverable: this.#statusCode(error) === DisconnectReason.connectionClosed,\n },\n );\n }\n }\n\n async sendMessage(\n chatId: string,\n content: MessageContent,\n replyTo?: MessageKey,\n ): Promise<SentMessage> {\n const socket = this.#requireSocket();\n const options = replyTo\n ? {\n quoted: {\n key: this.#toWaKey(replyTo),\n message: { conversation: '' },\n } as WAMessage,\n }\n : undefined;\n const result = await socket.sendMessage(chatId, this.#toContent(content), options);\n return this.#sent(result);\n }\n\n async editMessage(key: MessageKey, content: string): Promise<SentMessage> {\n const result = await this.#requireSocket().sendMessage(key.chatId, {\n text: content,\n edit: this.#toWaKey(key),\n });\n return this.#sent(result);\n }\n\n async deleteMessage(key: MessageKey): Promise<void> {\n await this.#requireSocket().sendMessage(key.chatId, { delete: this.#toWaKey(key) });\n }\n\n async getGroup(groupId: string): Promise<GroupSnapshot> {\n const metadata = await this.#requireSocket().groupMetadata(groupId);\n return {\n id: metadata.id,\n subject: metadata.subject,\n access: metadata.announce ? 'closed' : 'open',\n addressingMode: metadata.addressingMode === 'lid' ? 'lid' : 'pn',\n fetchedAt: new Date(),\n participants: metadata.participants.map((participant) => ({\n id: participant.id,\n ...(participant.lid ? { lid: participant.lid } : {}),\n ...(participant.phoneNumber ? { phoneNumber: participant.phoneNumber } : {}),\n role: participant.admin === 'superadmin' || participant.isSuperAdmin\n ? 'owner'\n : participant.admin === 'admin' || participant.isAdmin\n ? 'admin'\n : 'member',\n })),\n };\n }\n\n async setGroupAccess(groupId: string, access: GroupAccess): Promise<void> {\n const setting = access === 'closed' ? 'announcement' : 'not_announcement';\n await this.#requireSocket().groupSettingUpdate(groupId, setting);\n }\n\n async getGroupInviteCode(groupId: string): Promise<string> {\n const code = await this.#requireSocket().groupInviteCode(groupId);\n if (!code) {\n throw new WhaNextError(\n 'PROVIDER_ERROR',\n 'WhatsApp did not return a group invite code.',\n );\n }\n return code;\n }\n\n async revokeGroupInvite(groupId: string): Promise<string> {\n const code = await this.#requireSocket().groupRevokeInvite(groupId);\n if (!code) {\n throw new WhaNextError(\n 'PROVIDER_ERROR',\n 'WhatsApp did not return a new group invite code.',\n );\n }\n return code;\n }\n\n async setMessagePin(groupId: string, key: MessageKey, pinned: boolean): Promise<void> {\n await this.#requireSocket().sendMessage(groupId, {\n pin: this.#toWaKey(key),\n type: pinned ? proto.PinInChat.Type.PIN_FOR_ALL : proto.PinInChat.Type.UNPIN_FOR_ALL,\n ...(pinned ? { time: 604800 as const } : {}),\n });\n }\n\n async updateParticipant(\n groupId: string,\n memberId: string,\n action: ParticipantAction,\n ): Promise<ParticipantUpdateResult> {\n const [result] = await this.#requireSocket()\n .groupParticipantsUpdate(groupId, [memberId], action);\n const status = result?.status ?? 'unknown';\n return {\n success: status === '200',\n status,\n ...(result?.jid ? { memberId: result.jid } : {}),\n };\n }\n\n async setPresence(chatId: string, state: PresenceState): Promise<void> {\n const socket = this.#requireSocket();\n await socket.presenceSubscribe(chatId);\n const presence = state === 'typing'\n ? 'composing'\n : state === 'recording'\n ? 'recording'\n : 'paused';\n await socket.sendPresenceUpdate(presence, chatId);\n }\n\n async rejectCall(callId: string, from: string): Promise<void> {\n await this.#requireSocket().rejectCall(callId, from);\n }\n\n #bind(socket: WASocket): void {\n socket.ev.on('creds.update', (update) => {\n if (update.registered !== undefined) {\n this.#registered = update.registered;\n }\n\n this.#saveQueue = this.#saveQueue.then(() => this.#saveCredentials?.()).then(() => undefined);\n });\n\n socket.ev.on('messages.upsert', ({ messages, type }) => {\n if (type !== 'notify') return;\n\n for (const raw of messages) {\n if (raw.key.id && raw.message) this.#remember(raw.key.id, raw.message);\n const message = normalizeBaileysMessage(raw);\n if (message) void this.#events.emit('message', message);\n }\n });\n\n socket.ev.on('groups.update', (groups) => {\n for (const group of groups) {\n if (group.id) void this.#events.emit('groupChanged', { groupId: group.id });\n }\n });\n\n socket.ev.on('group-participants.update', ({ id }) => {\n void this.#events.emit('groupChanged', { groupId: id });\n });\n\n socket.ev.on('call', (calls) => {\n for (const call of calls) {\n void this.#events.emit('call', this.#normalizeCall(call));\n }\n });\n\n socket.ev.on('connection.update', (update) => {\n void this.#handleConnectionUpdate(socket, update.connection, update.lastDisconnect?.error);\n });\n }\n\n async #handleConnectionUpdate(\n socket: WASocket,\n connection?: 'open' | 'connecting' | 'close',\n error?: Error,\n ): Promise<void> {\n if (socket !== this.#socket || !connection) return;\n\n if (connection === 'open') {\n this.#reconnectAttempt = 0;\n await this.#events.emit('connection', { state: 'connected' });\n return;\n }\n\n if (connection === 'connecting') {\n await this.#events.emit('connection', {\n state: 'connecting',\n attempt: this.#reconnectAttempt,\n });\n return;\n }\n\n this.#socket = undefined;\n\n if (this.#intentionalClose || this.#isTerminal(error)) {\n await this.#events.emit('connection', { state: 'closed', ...(error ? { error } : {}) });\n return;\n }\n\n await this.#scheduleReconnect(error);\n }\n\n async #scheduleReconnect(error?: Error): Promise<void> {\n const options = this.#options.reconnect;\n const maxAttempts = options?.maxAttempts ?? 10;\n\n if (options?.enabled === false || this.#reconnectAttempt >= maxAttempts) {\n await this.#events.emit('connection', { state: 'closed', ...(error ? { error } : {}) });\n return;\n }\n\n this.#reconnectAttempt += 1;\n await this.#events.emit('connection', {\n state: 'reconnecting',\n attempt: this.#reconnectAttempt,\n ...(error ? { error } : {}),\n });\n const initial = options?.initialDelayMs ?? 1_000;\n const maximum = options?.maxDelayMs ?? 30_000;\n const delay = Math.min(maximum, initial * 2 ** (this.#reconnectAttempt - 1));\n this.#reconnectTimer = setTimeout(\n () => void this.connect(),\n delay + Math.floor(Math.random() * 250),\n );\n }\n\n #browserDescription(): [string, string, string] {\n if (this.#options.browser === Browser.MacOS) return Browsers.macOS('Chrome');\n if (this.#options.browser === Browser.Ubuntu) return Browsers.ubuntu('Chrome');\n return Browsers.windows('Chrome');\n }\n\n #isTerminal(error?: Error): boolean {\n const statusCode = this.#statusCode(error);\n return statusCode === DisconnectReason.loggedOut\n || statusCode === DisconnectReason.badSession\n || statusCode === DisconnectReason.connectionReplaced;\n }\n\n #statusCode(error: unknown): number | undefined {\n return (error as { output?: { statusCode?: number } } | undefined)?.output?.statusCode;\n }\n\n #requireSocket(): WASocket {\n if (!this.#socket) {\n throw new WhaNextError(\n 'CONNECTION_CLOSED',\n 'WhatsApp is not connected.',\n { recoverable: true },\n );\n }\n\n return this.#socket;\n }\n\n #toContent(content: MessageContent): AnyMessageContent {\n if ('text' in content) {\n return {\n text: content.text,\n ...(content.mentions\n ? { mentions: this.#mentions(content.mentions) }\n : {}),\n };\n }\n\n if ('image' in content) {\n return {\n image: this.#media(content.image),\n ...(content.caption !== undefined ? { caption: content.caption } : {}),\n ...(content.mentions\n ? { mentions: this.#mentions(content.mentions) }\n : {}),\n ...(content.viewOnce !== undefined\n ? { viewOnce: content.viewOnce }\n : {}),\n };\n }\n\n if ('video' in content) {\n return {\n video: this.#media(content.video),\n ...(content.caption !== undefined ? { caption: content.caption } : {}),\n ...(content.mentions\n ? { mentions: this.#mentions(content.mentions) }\n : {}),\n ...(content.viewOnce !== undefined\n ? { viewOnce: content.viewOnce }\n : {}),\n ...(content.gif !== undefined ? { gifPlayback: content.gif } : {}),\n };\n }\n\n return {\n audio: this.#media(content.audio),\n ...(content.mimetype ? { mimetype: content.mimetype } : {}),\n ...(content.voice !== undefined ? { ptt: content.voice } : {}),\n };\n }\n\n #media(source: MediaSource): Buffer | { url: string } {\n if (source instanceof Uint8Array) {\n return Buffer.from(source);\n }\n\n if ('url' in source) {\n return { url: source.url };\n }\n\n return { url: source.path };\n }\n\n #mentions(mentions: readonly MentionTarget[]): string[] {\n return mentions.map((mention) =>\n typeof mention === 'string' ? mention : mention.mentionId);\n }\n\n #toWaKey(key: MessageKey): WAMessageKey {\n return {\n id: key.id,\n remoteJid: key.chatId,\n fromMe: key.fromMe,\n ...(key.participantId ? { participant: key.participantId } : {}),\n };\n }\n\n #sent(message: WAMessage | undefined): SentMessage {\n if (!message?.key.id || !message.key.remoteJid) {\n throw new WhaNextError('PROVIDER_ERROR', 'WhatsApp did not confirm the sent message.');\n }\n\n if (message.message) this.#remember(message.key.id, message.message);\n return {\n id: message.key.id,\n chatId: message.key.remoteJid,\n keys: normalizeKey(message.key),\n timestamp: new Date(),\n };\n }\n\n #normalizeCall(call: WACallEvent): CallEvent {\n return {\n id: call.id,\n chatId: call.chatId,\n from: call.from,\n status: this.#callStatus(call.status),\n isVideo: Boolean(call.isVideo),\n isGroup: Boolean(call.isGroup),\n date: call.date ?? new Date(),\n };\n }\n\n #callStatus(status: WACallEvent['status']): CallStatus {\n const known: readonly CallStatus[] = [\n 'offer',\n 'ringing',\n 'preaccept',\n 'timeout',\n 'reject',\n 'accept',\n ];\n return known.find((value) => value === status) ?? 'timeout';\n }\n\n #remember(id: string, message: WAMessageContent): void {\n this.#messageStore.set(id, message);\n\n if (this.#messageStore.size > 500) {\n const oldest = this.#messageStore.keys().next().value as string | undefined;\n if (oldest) this.#messageStore.delete(oldest);\n }\n }\n}\n","import type {\n LogContext,\n Logger,\n} from '@/logger/logger.js';\n\ninterface ProviderLogger {\n level: string;\n child(context: Record<string, unknown>): ProviderLogger;\n trace(value: unknown, message?: string): void;\n debug(value: unknown, message?: string): void;\n info(value: unknown, message?: string): void;\n warn(value: unknown, message?: string): void;\n error(value: unknown, message?: string): void;\n}\n\nexport function createBaileysLogger(logger: Logger): ProviderLogger {\n return {\n level: logger.level,\n\n child(context) {\n const name = typeof context.class === 'string'\n ? context.class\n : 'internal';\n return createBaileysLogger(logger.child(name));\n },\n\n trace(value, message) {\n logger.debug(resolveMessage(value, message, 'Provider trace'), safeContext(value));\n },\n\n debug(value, message) {\n logger.debug(resolveMessage(value, message, 'Provider debug'), safeContext(value));\n },\n\n info(value, message) {\n logger.debug(resolveMessage(value, message, 'Provider info'), safeContext(value));\n },\n\n warn(value, message) {\n logger.warn(resolveMessage(value, message, 'Provider warning'), safeContext(value));\n },\n\n error(value, message) {\n logger.error(resolveMessage(value, message, 'Provider error'), safeContext(value));\n },\n };\n}\n\nfunction resolveMessage(\n value: unknown,\n message: string | undefined,\n fallback: string,\n): string {\n if (message) {\n return message;\n }\n\n return typeof value === 'string' ? value : fallback;\n}\n\nfunction safeContext(value: unknown): LogContext {\n if (value instanceof Error) {\n return { error: value };\n }\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return {};\n }\n\n const source = value as Record<string, unknown>;\n const allowed = [\n 'location',\n 'reason',\n 'status',\n 'statusCode',\n 'type',\n ];\n\n return Object.fromEntries(\n allowed\n .filter((key) => source[key] !== undefined)\n .map((key) => [key, source[key]]),\n );\n}\n","import {\n extractMessageContent,\n getContentType,\n normalizeMessageContent,\n type WAMessage,\n type WAMessageContent,\n type WAMessageKey,\n type proto,\n} from '@whiskeysockets/baileys';\nimport { uniqueIdentities } from '@/models/identity.js';\nimport type {\n MediaKind,\n Message,\n MessageKey,\n MessageMedia,\n QuotedMessage,\n} from '@/models/message.js';\nimport { User } from '@/models/user.js';\n\nexport function normalizeBaileysMessage(input: WAMessage): Message | undefined {\n const chatId = input.key.remoteJid;\n const id = input.key.id;\n\n if (!chatId || !id || !input.message) {\n return undefined;\n }\n\n const normalized = normalizeMessageContent(input.message);\n const content = extractMessageContent(normalized);\n\n if (!content) {\n return undefined;\n }\n\n const type = getContentType(content);\n const node = type ? content[type] : undefined;\n const context = getContextInfo(node);\n const senderIds = uniqueIdentities([\n input.key.participant,\n input.key.participantAlt,\n input.key.participantUsername?.includes('@')\n ? input.key.participantUsername\n : undefined,\n ]);\n const senderJid = senderIds.find((identity) =>\n identity.endsWith('@s.whatsapp.net') || identity.endsWith('@c.us'));\n const senderLid = senderIds.find((identity) => identity.endsWith('@lid'));\n const senderId = senderJid ?? senderLid ?? senderIds[0] ?? chatId;\n const sender = new User({\n id: senderId,\n identities: senderIds.length > 0 ? senderIds : [senderId],\n ...(input.pushName ? { name: input.pushName } : {}),\n });\n const mentionedUsers = (context?.mentionedJid ?? []).map((identity) =>\n User.fromIdentities([identity]));\n const media = getMedia(type, node, Boolean(input.key.isViewOnce));\n const text = getText(content);\n const caption = getCaption(content);\n const quoted = getQuoted(context, chatId);\n\n const message: Message = {\n id,\n jid: chatId,\n chatId,\n senderId,\n senderIds: senderIds.length > 0 ? senderIds : [senderId],\n sender,\n keys: normalizeKey(input.key),\n mentions: [...(context?.mentionedJid ?? [])],\n mentionedUsers,\n timestamp: toDate(input.messageTimestamp),\n isGroup: chatId.endsWith('@g.us'),\n isReply: quoted !== undefined,\n isViewOnce: media?.viewOnce ?? false,\n hasMedia: media !== undefined,\n };\n\n if (senderJid !== undefined) message.senderJid = senderJid;\n if (senderLid !== undefined) {\n message.lid = senderLid;\n message.senderLid = senderLid;\n }\n if (text !== undefined) message.text = text;\n if (caption !== undefined) message.caption = caption;\n if (media !== undefined) message.media = media;\n if (quoted !== undefined) message.quoted = quoted;\n return message;\n}\n\nexport function normalizeKey(key: WAMessageKey): MessageKey {\n const normalized: MessageKey = {\n id: key.id ?? '',\n chatId: key.remoteJid ?? '',\n fromMe: key.fromMe ?? false,\n };\n\n const participantId = key.participant ?? key.participantAlt;\n\n if (participantId !== null && participantId !== undefined) {\n normalized.participantId = participantId;\n }\n\n return normalized;\n}\n\nfunction getText(content: WAMessageContent): string | undefined {\n return content.conversation\n ?? content.extendedTextMessage?.text\n ?? content.buttonsResponseMessage?.selectedDisplayText\n ?? content.listResponseMessage?.title\n ?? undefined;\n}\n\nfunction getCaption(content: WAMessageContent): string | undefined {\n return content.imageMessage?.caption\n ?? content.videoMessage?.caption\n ?? content.documentMessage?.caption\n ?? undefined;\n}\n\nfunction getContextInfo(node: unknown): proto.IContextInfo | undefined {\n if (typeof node !== 'object' || node === null || !('contextInfo' in node)) {\n return undefined;\n }\n\n return (node as { contextInfo?: proto.IContextInfo }).contextInfo;\n}\n\nfunction getMedia(\n type: keyof WAMessageContent | undefined,\n node: unknown,\n keyViewOnce: boolean,\n): MessageMedia | undefined {\n const mapping: Partial<Record<keyof WAMessageContent, MediaKind>> = {\n imageMessage: 'image',\n videoMessage: 'video',\n audioMessage: 'audio',\n documentMessage: 'document',\n stickerMessage: 'sticker',\n };\n\n const kind = type ? mapping[type] : undefined;\n\n if (!kind || typeof node !== 'object' || node === null) {\n return undefined;\n }\n\n const value = node as {\n mimetype?: string | null;\n fileName?: string | null;\n seconds?: number | LongLike | null;\n viewOnce?: boolean | null;\n };\n const media: MessageMedia = {\n kind,\n viewOnce: keyViewOnce || value.viewOnce === true,\n };\n if (value.mimetype) media.mimetype = value.mimetype;\n if (value.fileName) media.fileName = value.fileName;\n if (value.seconds !== undefined && value.seconds !== null) media.seconds = Number(value.seconds);\n return media;\n}\n\nfunction getQuoted(\n context: proto.IContextInfo | undefined,\n chatId: string,\n): QuotedMessage | undefined {\n if (!context?.stanzaId) {\n return undefined;\n }\n\n const quoted = context.quotedMessage;\n const normalized = normalizeMessageContent(quoted);\n const content = extractMessageContent(normalized);\n const result: QuotedMessage = {\n key: {\n id: context.stanzaId,\n chatId: context.remoteJid ?? chatId,\n fromMe: false,\n },\n hasMedia: Boolean(\n content\n && getMedia(\n getContentType(content),\n content[getContentType(content) ?? 'conversation'],\n false,\n ),\n ),\n };\n\n if (context.participant) {\n result.senderId = context.participant;\n result.sender = User.fromIdentities([context.participant]);\n result.key.participantId = context.participant;\n }\n\n if (content) {\n const text = getText(content) ?? getCaption(content);\n if (text !== undefined) result.text = text;\n }\n\n return result;\n}\n\ninterface LongLike {\n toString(): string;\n}\n\nfunction toDate(value: number | LongLike | null | undefined): Date {\n const seconds = value === null || value === undefined ? Date.now() / 1_000 : Number(value);\n return new Date(seconds * 1_000);\n}\n","import { WhaNextApp } from '@/app/whanext-app.js';\nimport { Browser } from '@/auth/browser.js';\nimport type { CacheOptions } from '@/cache/cache-store.js';\nimport type { RouterOptions } from '@/commands/router.js';\nimport {\n Logger,\n type LoggerConfig,\n} from '@/logger/logger.js';\nimport type { MuteOptions } from '@/mute/mute-store.js';\nimport { BaileysProvider } from '@/provider/baileys/baileys-provider.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport interface ReconnectOptions {\n enabled?: boolean;\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n}\n\nexport interface CreateOptions {\n phone?: string;\n browser?: Browser;\n auth?: string;\n prefix?: string;\n cache?: CacheOptions;\n logger?: LoggerConfig;\n mute?: MuteOptions;\n router?: Omit<RouterOptions, 'prefix'>;\n reconnect?: ReconnectOptions;\n provider?: WhatsAppProvider;\n}\n\nexport async function create(options: CreateOptions = {}): Promise<WhaNextApp> {\n const logger = new Logger(options.logger);\n const provider = options.provider ?? new BaileysProvider({\n auth: options.auth ?? './session',\n browser: options.browser ?? Browser.Windows,\n logger: logger.child('provider'),\n ...(options.reconnect ? { reconnect: options.reconnect } : {}),\n });\n\n return new WhaNextApp(provider, {\n ...(options.phone ? { phone: options.phone } : {}),\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options.cache ? { cache: options.cache } : {}),\n ...(options.logger ? { logger: options.logger } : {}),\n ...(options.mute ? { mute: options.mute } : {}),\n ...(options.router ? { router: options.router } : {}),\n }, logger);\n}\n","import type { ArgsParser } from '@/commands/args-parser.js';\nimport type { Message } from '@/models/message.js';\n\nexport interface CommandDefinition {\n name: string;\n description: string;\n aliases?: readonly string[];\n onlyGroup?: boolean;\n onlyPrivate?: boolean;\n onlyAdmin?: boolean;\n botMustBeAdmin?: boolean;\n execute(message: Message, args: ArgsParser): void | Promise<void>;\n}\n\nexport function defineCommand<const Command extends CommandDefinition>(command: Command): Command {\n return command;\n}\n\nexport function defineCommands<const Commands extends readonly CommandDefinition[]>(\n ...commands: Commands\n): Commands {\n return commands;\n}\n","import type { Dirent } from 'node:fs';\nimport { readdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport type { CommandDefinition } from '@/commands/command.js';\nimport { WhaNextError } from '@/errors/error.js';\n\nexport interface CommandRegistrar {\n command(definition: CommandDefinition): unknown;\n}\n\nexport interface LoadCommandsOptions {\n extensions?: readonly string[];\n recursive?: boolean;\n}\n\nexport interface LoadCommandsResult {\n loaded: readonly string[];\n skipped: readonly string[];\n commands: readonly LoadedCommand[];\n}\n\nexport interface LoadedCommand {\n name: string;\n filePath: string;\n}\n\nconst DEFAULT_EXTENSIONS = ['.js', '.mjs', '.cjs'] as const;\n\nexport async function loadCommands(\n registrar: CommandRegistrar,\n dirPath: string,\n options: LoadCommandsOptions = {},\n): Promise<LoadCommandsResult> {\n const extensions = options.extensions ?? DEFAULT_EXTENSIONS;\n const recursive = options.recursive ?? true;\n\n const entries = await readEntries(dirPath, recursive);\n const loaded: string[] = [];\n const skipped: string[] = [];\n const commands: LoadedCommand[] = [];\n\n for (const filePath of entries) {\n if (!extensions.includes(path.extname(filePath))) {\n skipped.push(filePath);\n continue;\n }\n\n const definitions = await importCommands(filePath);\n\n for (const definition of definitions) {\n registrar.command(definition);\n commands.push({ name: definition.name, filePath });\n }\n\n loaded.push(filePath);\n }\n\n return { loaded, skipped, commands };\n}\n\nasync function readEntries(dirPath: string, recursive: boolean): Promise<string[]> {\n let dirents: Dirent[];\n\n try {\n dirents = await readdir(dirPath, { recursive, withFileTypes: true });\n } catch (error) {\n throw new WhaNextError('COMMAND_LOAD_FAILED', `Could not read the commands directory \"${dirPath}\".`, {\n cause: error,\n context: { dirPath },\n });\n }\n\n return dirents\n .filter((dirent) => dirent.isFile())\n .map((dirent) => path.join(dirent.parentPath, dirent.name))\n .sort((left, right) => left.localeCompare(right));\n}\n\nasync function importCommands(filePath: string): Promise<CommandDefinition[]> {\n let module: Record<string, unknown>;\n\n try {\n module = await import(pathToFileURL(filePath).href);\n } catch (error) {\n throw new WhaNextError('COMMAND_LOAD_FAILED', `Could not import the command file \"${filePath}\".`, {\n cause: error,\n context: { filePath },\n });\n }\n\n const definitions: CommandDefinition[] = [];\n const seen = new Set<CommandDefinition>();\n const exports = [\n module.default,\n ...Object.entries(module)\n .filter(([name]) => name !== 'default')\n .map(([, value]) => value),\n ];\n\n for (const value of exports) {\n const candidates = Array.isArray(value) ? value : [value];\n\n for (const candidate of candidates) {\n if (isCommandDefinition(candidate) && !seen.has(candidate)) {\n seen.add(candidate);\n definitions.push(candidate);\n }\n }\n }\n\n if (definitions.length === 0) {\n throw new WhaNextError('COMMAND_LOAD_FAILED', `The file \"${filePath}\" does not export any valid commands.`, {\n context: { filePath },\n });\n }\n\n return definitions;\n}\n\nfunction isCommandDefinition(value: unknown): value is CommandDefinition {\n return (\n typeof value === 'object'\n && value !== null\n && typeof (value as CommandDefinition).name === 'string'\n && typeof (value as CommandDefinition).execute === 'function'\n );\n}\n"],"mappings":"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","names":["path","require","resolve","Browser"]}
1
+ {"version":3,"sources":["../src/cache/memory-cache.ts","../src/errors/error.ts","../src/models/identity.ts","../src/models/user.ts","../src/commands/args-parser.ts","../src/commands/router.ts","../src/logger/logger.ts","../src/mute/mute-service.ts","../src/mute/sqlite-mute-store.ts","../src/provider/event-emitter.ts","../src/services/chat-service.ts","../src/services/group-service.ts","../src/services/media-service.ts","../src/services/member-service.ts","../src/services/message-service.ts","../src/services/user-service.ts","../src/app/whanext-app.ts","../src/auth/browser.ts","../src/provider/baileys/baileys-provider.ts","../src/provider/baileys/baileys-logger.ts","../src/provider/baileys/normalize-message.ts","../src/app/create.ts","../src/commands/command.ts","../src/commands/load-commands.ts"],"sourcesContent":["import type { CacheStore } from '@/cache/cache-store.js';\n\ninterface CacheEntry {\n value: unknown;\n expiresAt?: number;\n}\n\nexport class MemoryCache implements CacheStore {\n readonly #entries = new Map<string, CacheEntry>();\n readonly #maxEntries: number;\n\n constructor(options: { maxEntries?: number } = {}) {\n this.#maxEntries = Math.max(1, options.maxEntries ?? 1_000);\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const entry = this.#entries.get(key);\n\n if (!entry) {\n return undefined;\n }\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n this.#entries.delete(key);\n return undefined;\n }\n\n this.#entries.delete(key);\n this.#entries.set(key, entry);\n return entry.value as T;\n }\n\n async set<T>(key: string, value: T, ttlMs?: number): Promise<void> {\n const entry: CacheEntry = { value };\n\n if (ttlMs !== undefined) {\n entry.expiresAt = Date.now() + ttlMs;\n }\n\n this.#entries.set(key, entry);\n\n while (this.#entries.size > this.#maxEntries) {\n const oldest = this.#entries.keys().next().value as string | undefined;\n if (oldest === undefined) return;\n this.#entries.delete(oldest);\n }\n }\n\n async delete(key: string): Promise<void> {\n this.#entries.delete(key);\n }\n\n async clear(): Promise<void> {\n this.#entries.clear();\n }\n}\n","export type WhaNextErrorCode =\n | 'AUTH_INVALID_PHONE'\n | 'AUTH_EXPIRED'\n | 'CONNECTION_CLOSED'\n | 'CONNECTION_FAILED'\n | 'GROUP_NOT_FOUND'\n | 'MEMBER_NOT_FOUND'\n | 'BOT_NOT_ADMIN'\n | 'MESSAGE_NOT_FOUND'\n | 'MEDIA_NOT_AVAILABLE'\n | 'MUTE_DISABLED'\n | 'STORAGE_ERROR'\n | 'ARGUMENT_MISSING'\n | 'ARGUMENT_INVALID'\n | 'COMMAND_NOT_ALLOWED'\n | 'COMMAND_LOAD_FAILED'\n | 'PROVIDER_ERROR'\n | 'UNKNOWN_ERROR';\n\nexport interface WhaNextErrorOptions {\n cause?: unknown;\n context?: Readonly<Record<string, unknown>>;\n recoverable?: boolean;\n}\n\nexport class WhaNextError extends Error {\n readonly code: WhaNextErrorCode;\n readonly context: Readonly<Record<string, unknown>>;\n readonly recoverable: boolean;\n\n constructor(\n code: WhaNextErrorCode,\n message: string,\n options: WhaNextErrorOptions = {},\n ) {\n super(message, { cause: options.cause });\n this.name = 'WhaNextError';\n this.code = code;\n this.context = options.context ?? {};\n this.recoverable = options.recoverable ?? false;\n }\n}\n\nexport function toWhaNextError(\n error: unknown,\n context?: Readonly<Record<string, unknown>>,\n): WhaNextError {\n if (error instanceof WhaNextError) {\n return error;\n }\n\n const message = error instanceof Error ? error.message : 'An unknown error occurred.';\n return new WhaNextError('UNKNOWN_ERROR', message, {\n cause: error,\n ...(context ? { context } : {}),\n });\n}\n","export function normalizeIdentity(identity: string): string {\n const value = identity.trim().toLowerCase();\n const separator = value.lastIndexOf('@');\n\n if (separator === -1) {\n return value.replace(/\\D/g, '');\n }\n\n const user = value.slice(0, separator).replace(/:\\d+$/, '');\n const rawServer = value.slice(separator + 1);\n const server = rawServer === 'c.us' ? 's.whatsapp.net' : rawServer;\n return `${user}@${server}`;\n}\n\nexport function identityUsername(identity: string): string {\n const normalized = normalizeIdentity(identity);\n const separator = normalized.lastIndexOf('@');\n return separator === -1 ? normalized : normalized.slice(0, separator);\n}\n\nexport function identityPhoneNumber(identity: string): string | undefined {\n const normalized = normalizeIdentity(identity);\n\n if (normalized.endsWith('@lid')) {\n return undefined;\n }\n\n const username = identityUsername(normalized);\n return /^\\d+$/.test(username) ? username : undefined;\n}\n\nexport function identitiesMatch(left: string, right: string): boolean {\n return normalizeIdentity(left) === normalizeIdentity(right);\n}\n\nexport function uniqueIdentities(identities: ReadonlyArray<string | null | undefined>): string[] {\n const values = identities.filter((identity): identity is string => Boolean(identity));\n return [...new Map(values.map((identity) => [normalizeIdentity(identity), identity])).values()];\n}\n","import {\n identityPhoneNumber,\n identityUsername,\n identitiesMatch,\n uniqueIdentities,\n} from '@/models/identity.js';\n\nexport interface UserData {\n id: string;\n identities?: readonly string[];\n jid?: string;\n lid?: string;\n phoneNumber?: string;\n name?: string;\n}\n\nexport class User {\n readonly id: string;\n readonly identities: string[];\n readonly jid: string | undefined;\n readonly lid: string | undefined;\n readonly phoneNumber: string | undefined;\n readonly name: string | undefined;\n\n constructor(data: UserData) {\n const identities = uniqueIdentities([\n data.id,\n data.jid,\n data.lid,\n data.phoneNumber,\n ...(data.identities ?? []),\n ]);\n\n this.jid = data.jid ?? identities.find((identity) =>\n identity.endsWith('@s.whatsapp.net') || identity.endsWith('@c.us'));\n this.lid = data.lid ?? identities.find((identity) => identity.endsWith('@lid'));\n this.phoneNumber = data.phoneNumber ?? this.jid;\n this.name = data.name;\n this.id = this.jid ?? this.phoneNumber ?? this.lid ?? data.id;\n this.identities = identities;\n }\n\n get mentionId(): string {\n return this.jid ?? this.phoneNumber ?? this.lid ?? this.id;\n }\n\n get mention(): string {\n return `@${this.username}`;\n }\n\n get phone(): string | undefined {\n return this.phoneNumber ? identityPhoneNumber(this.phoneNumber) : undefined;\n }\n\n get username(): string {\n return identityUsername(this.mentionId);\n }\n\n get displayName(): string {\n return this.name ?? this.mention;\n }\n\n matches(identity: string | User): boolean {\n const candidates = typeof identity === 'string' ? [identity] : identity.identities;\n return this.identities.some((ownIdentity) =>\n candidates.some((candidate) => identitiesMatch(ownIdentity, candidate)));\n }\n\n toJSON(): UserData {\n return {\n id: this.id,\n identities: this.identities,\n ...(this.jid ? { jid: this.jid } : {}),\n ...(this.lid ? { lid: this.lid } : {}),\n ...(this.phoneNumber ? { phoneNumber: this.phoneNumber } : {}),\n ...(this.name ? { name: this.name } : {}),\n };\n }\n\n static fromIdentities(identities: readonly string[]): User {\n const [id] = identities;\n\n if (!id) {\n throw new TypeError('A user requires at least one identity.');\n }\n\n return new User({ id, identities });\n }\n\n static fromPhoneNumber(phoneNumber: string): User {\n const normalized = phoneNumber.replace(/\\D/g, '');\n\n if (normalized.length < 8) {\n throw new TypeError('A user phone number must include country and area codes.');\n }\n\n return User.fromIdentities([`${normalized}@s.whatsapp.net`]);\n }\n}\n","import { WhaNextError } from '@/errors/error.js';\nimport { User } from '@/models/user.js';\n\nexport interface ArgumentOptions {\n optional?: boolean;\n}\n\nexport class ArgsParser {\n readonly #values: string[];\n #cursor = 0;\n\n constructor(values: readonly string[]) {\n this.#values = [...values];\n }\n\n get remaining(): number {\n return this.#values.length - this.#cursor;\n }\n\n peek(): string | undefined {\n return this.#values[this.#cursor];\n }\n\n skip(count = 1): this {\n this.#cursor = Math.min(this.#values.length, this.#cursor + Math.max(0, count));\n return this;\n }\n\n string(name = 'argument', options: ArgumentOptions = {}): string | undefined {\n return this.#consume(name, options);\n }\n\n number(name = 'number', options: ArgumentOptions = {}): number | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n const value = Number(raw);\n\n if (!Number.isFinite(value)) {\n throw new WhaNextError('ARGUMENT_INVALID', `The argument \"${name}\" must be a number.`, {\n context: { name, received: raw },\n });\n }\n\n return value;\n }\n\n boolean(name = 'boolean', options: ArgumentOptions = {}): boolean | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n const normalized = raw.toLowerCase();\n const truthy = new Set(['true', 'on', 'yes', 'sim', '1']);\n const falsy = new Set(['false', 'off', 'no', 'não', 'nao', '0']);\n\n if (truthy.has(normalized)) {\n return true;\n }\n\n if (falsy.has(normalized)) {\n return false;\n }\n\n throw new WhaNextError('ARGUMENT_INVALID', `The argument \"${name}\" must be a boolean.`, {\n context: { name, received: raw },\n });\n }\n\n enum<const Values extends readonly string[]>(\n values: Values,\n name = 'option',\n options: ArgumentOptions = {},\n ): Values[number] | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n if (!values.includes(raw)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n `The argument \"${name}\" must be one of: ${values.join(', ')}.`,\n {\n context: { name, received: raw, expected: values },\n },\n );\n }\n\n return raw as Values[number];\n }\n\n user(name?: string): User;\n user(name: string, options: { optional: true }): User | undefined;\n user(name = 'user', options: ArgumentOptions = {}): User | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n const normalized = raw.replace(/^@/, '').replace(/\\D/g, '');\n\n if (normalized.length < 8) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n `The argument \"${name}\" must be a mention or phone number.`,\n {\n context: { name, received: raw },\n },\n );\n }\n\n return User.fromPhoneNumber(normalized);\n }\n\n duration(name = 'duration', options: ArgumentOptions = {}): number | undefined {\n const raw = this.#consume(name, options);\n\n if (raw === undefined) {\n return undefined;\n }\n\n const normalized = raw.toLowerCase();\n const permanent = new Set([\n 'forever',\n 'indefinido',\n 'permanent',\n 'permanente',\n 'sempre',\n ]);\n\n if (permanent.has(normalized)) {\n return undefined;\n }\n\n const match = /^(\\d+)(ms|s|m|h|d)$/.exec(normalized);\n\n if (!match) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n `The argument \"${name}\" must be a duration such as 30s or 5m.`,\n {\n context: { name, received: raw },\n },\n );\n }\n\n const amount = Number(match[1]);\n const unit = match[2] as 'ms' | 's' | 'm' | 'h' | 'd';\n const multiplier = { ms: 1, s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000 }[unit];\n return amount * multiplier;\n }\n\n rest(): string {\n const value = this.#values.slice(this.#cursor).join(' ');\n this.#cursor = this.#values.length;\n return value;\n }\n\n #consume(name: string, options: ArgumentOptions): string | undefined {\n const value = this.#values[this.#cursor];\n\n if (value === undefined) {\n if (options.optional) {\n return undefined;\n }\n\n throw new WhaNextError('ARGUMENT_MISSING', `The argument \"${name}\" is required.`, {\n context: { name, position: this.#cursor },\n });\n }\n\n this.#cursor += 1;\n return value;\n }\n}\n","import { ArgsParser } from '@/commands/args-parser.js';\nimport type { CommandDefinition } from '@/commands/command.js';\nimport {\n WhaNextError,\n toWhaNextError,\n} from '@/errors/error.js';\nimport type { Message } from '@/models/message.js';\nimport type { GroupService } from '@/services/group-service.js';\n\nexport interface RouterOptions {\n prefix?: string;\n onError?: (error: WhaNextError, message: Message) => void | Promise<void>;\n}\n\nexport class CommandRouter {\n readonly #commands = new Map<string, CommandDefinition>();\n readonly #prefix: string;\n readonly #group: GroupService;\n readonly #onError?: RouterOptions['onError'];\n\n constructor(group: GroupService, options: RouterOptions = {}) {\n this.#group = group;\n this.#prefix = options.prefix ?? '!';\n this.#onError = options.onError;\n\n if (this.#prefix.length === 0 || /\\s/.test(this.#prefix)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n 'The command prefix cannot be empty or contain whitespace.',\n {\n context: { prefix: this.#prefix },\n },\n );\n }\n }\n\n command(definition: CommandDefinition): this {\n const names = [definition.name, ...(definition.aliases ?? [])];\n\n for (const name of names) {\n const normalized = name.toLowerCase();\n\n if (this.#commands.has(normalized)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n `The command \"${normalized}\" is already registered.`,\n );\n }\n\n this.#commands.set(normalized, definition);\n }\n\n return this;\n }\n\n async dispatch(message: Message): Promise<boolean> {\n const text = message.text?.trim();\n\n if (!text?.startsWith(this.#prefix)) {\n return false;\n }\n\n const tokens = tokenize(text.slice(this.#prefix.length));\n const name = tokens.shift()?.toLowerCase();\n\n if (!name) {\n return false;\n }\n\n const command = this.#commands.get(name);\n\n if (!command) {\n return false;\n }\n\n try {\n await this.#authorize(command, message);\n await command.execute(message, new ArgsParser(tokens));\n return true;\n } catch (error) {\n const normalized = toWhaNextError(error, { command: command.name, messageId: message.id });\n\n if (this.#onError) {\n await this.#onError(normalized, message);\n return true;\n }\n\n throw normalized;\n }\n }\n\n async #authorize(command: CommandDefinition, message: Message): Promise<void> {\n if (command.onlyGroup && !message.isGroup) {\n throw new WhaNextError('COMMAND_NOT_ALLOWED', 'This command can only be used in groups.');\n }\n\n if (command.onlyPrivate && message.isGroup) {\n throw new WhaNextError(\n 'COMMAND_NOT_ALLOWED',\n 'This command can only be used in private chats.',\n );\n }\n\n if (command.onlyAdmin && !(await this.#group.isAdmin(message.chatId, message.senderIds))) {\n throw new WhaNextError(\n 'COMMAND_NOT_ALLOWED',\n 'This command can only be used by group administrators.',\n );\n }\n\n if (command.botMustBeAdmin && !(await this.#group.isCurrentUserAdmin(message.chatId))) {\n throw new WhaNextError(\n 'BOT_NOT_ADMIN',\n 'The connected WhatsApp account must be a group administrator.',\n );\n }\n }\n}\n\nfunction tokenize(input: string): string[] {\n return input\n .match(/(?:[^\\s\"']+|\"[^\"]*\"|'[^']*')+/g)\n ?.map((token) => token.replace(/^([\"'])(.*)\\1$/, '$2'))\n ?? [];\n}\n","import { WhaNextError } from '@/errors/error.js';\n\nexport type LogLevel = \n | 'debug'\n | 'info'\n | 'warn'\n | 'error'\n | 'silent';\n \nexport type LogFormat = \n | 'pretty'\n | 'json';\n \nexport type LogContext = Readonly<Record<string, unknown>>;\n\nexport interface LogEntry {\n timestamp: string;\n level: Exclude<LogLevel, 'silent'>;\n scope: string;\n message: string;\n context: LogContext;\n}\n\nexport type LogWriter = (entry: LogEntry) => unknown;\n\nexport interface LoggerOptions {\n level?: LogLevel;\n format?: LogFormat;\n writer?: LogWriter;\n scope?: string;\n redact?: readonly string[];\n}\n\nexport type LoggerConfig = LogLevel | LoggerOptions;\n\nconst priorities: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n silent: Number.POSITIVE_INFINITY,\n};\n\nconst defaultRedactions = [\n 'auth',\n 'pairingcode',\n 'password',\n 'phone',\n 'secret',\n 'session',\n 'token',\n];\n\ninterface LoggerState {\n level: LogLevel;\n}\n\nexport class Logger {\n #state: LoggerState;\n readonly #scope: string;\n readonly #writer: LogWriter;\n readonly #redactions: Set<string>;\n\n constructor(config: LoggerConfig = 'info') {\n const options = typeof config === 'string' ? { level: config } : config;\n const level = options.level ?? 'info';\n assertLevel(level);\n\n if (options.writer !== undefined && typeof options.writer !== 'function') {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n 'Logger writer must be a function.',\n );\n }\n\n if (options.format !== undefined && !['pretty', 'json'].includes(options.format)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n 'Logger format must be \"pretty\" or \"json\".',\n { context: { format: options.format } },\n );\n }\n\n this.#state = { level };\n this.#scope = options.scope ?? 'whanext';\n this.#redactions = new Set(\n [...defaultRedactions, ...(options.redact ?? [])]\n .map((key) => key.toLowerCase()),\n );\n this.#writer = options.writer ?? consoleWriter(options.format ?? 'pretty');\n }\n\n get level(): LogLevel {\n return this.#state.level;\n }\n\n setLevel(level: LogLevel): this {\n assertLevel(level);\n this.#state.level = level;\n return this;\n }\n\n isEnabled(level: Exclude<LogLevel, 'silent'>): boolean {\n return priorities[level] >= priorities[this.#state.level];\n }\n\n child(scope: string): Logger {\n const childScope = this.#scope ? `${this.#scope}:${scope}` : scope;\n const child = new Logger({\n level: this.#state.level,\n scope: childScope,\n writer: this.#writer,\n redact: [...this.#redactions],\n });\n child.#state = this.#state;\n return child;\n }\n\n debug(message: string, context: LogContext = {}): void {\n this.#write('debug', message, context);\n }\n\n info(message: string, context: LogContext = {}): void {\n this.#write('info', message, context);\n }\n\n warn(message: string, context: LogContext = {}): void {\n this.#write('warn', message, context);\n }\n\n error(message: string, context: LogContext = {}): void {\n this.#write('error', message, context);\n }\n\n #write(\n level: Exclude<LogLevel, 'silent'>,\n message: string,\n context: LogContext,\n ): void {\n if (!this.isEnabled(level)) {\n return;\n }\n\n try {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n scope: this.#scope,\n message,\n context: normalizeContext(context, this.#redactions),\n };\n const result = this.#writer(entry);\n\n if (result instanceof Promise) {\n void result.catch(() => undefined);\n }\n } catch {\n return;\n }\n }\n}\n\nfunction assertLevel(level: LogLevel): void {\n if (!(level in priorities)) {\n throw new WhaNextError(\n 'ARGUMENT_INVALID',\n 'Logger level must be debug, info, warn, error or silent.',\n { context: { level } },\n );\n }\n}\n\nfunction consoleWriter(format: LogFormat): LogWriter {\n return (entry) => {\n const method = entry.level === 'debug'\n ? console.debug\n : entry.level === 'info'\n ? console.info\n : entry.level === 'warn'\n ? console.warn\n : console.error;\n\n if (format === 'json') {\n method(JSON.stringify(entry));\n return;\n }\n\n const details = Object.keys(entry.context).length > 0\n ? ` ${JSON.stringify(entry.context)}`\n : '';\n method(\n `[${entry.timestamp}] ${entry.level.toUpperCase()} ${entry.scope} ${entry.message}${details}`,\n );\n };\n}\n\nfunction normalizeContext(\n context: LogContext,\n redactions: ReadonlySet<string>,\n): LogContext {\n const seen = new WeakSet<object>();\n return Object.fromEntries(\n Object.entries(context).map(([key, value]) => [\n key,\n normalizeValue(value, key, redactions, seen),\n ]),\n );\n}\n\nfunction normalizeValue(\n value: unknown,\n key: string,\n redactions: ReadonlySet<string>,\n seen: WeakSet<object>,\n): unknown {\n if (isRedactedKey(key, redactions)) {\n return '[REDACTED]';\n }\n\n if (\n value === null\n || typeof value === 'string'\n || typeof value === 'number'\n || typeof value === 'boolean'\n || value === undefined\n ) {\n return value;\n }\n\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (value instanceof Error) {\n return {\n name: value.name,\n message: value.message,\n ...('code' in value ? { code: value.code } : {}),\n };\n }\n\n if (typeof value !== 'object') {\n return String(value);\n }\n\n if (seen.has(value)) {\n return '[Circular]';\n }\n\n seen.add(value);\n\n if (Array.isArray(value)) {\n return value.map((item) =>\n normalizeValue(item, '', redactions, seen));\n }\n\n return Object.fromEntries(\n Object.entries(value).map(([nestedKey, nestedValue]) => [\n nestedKey,\n normalizeValue(nestedValue, nestedKey, redactions, seen),\n ]),\n );\n}\n\nfunction isRedactedKey(\n key: string,\n redactions: ReadonlySet<string>,\n): boolean {\n const normalized = key.toLowerCase();\n return [...redactions].some((redaction) =>\n normalized === redaction\n || normalized.startsWith(redaction)\n || normalized.endsWith(redaction));\n}\n","import { WhaNextError } from '@/errors/error.js';\nimport { normalizeIdentity } from '@/models/identity.js';\nimport type { Message } from '@/models/message.js';\nimport { User } from '@/models/user.js';\nimport type {\n MuteStore,\n StoredMute,\n} from '@/mute/mute-store.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport interface AddMuteOptions {\n durationMs?: number;\n}\n\nexport interface MuteRecord {\n groupId: string;\n user: User;\n createdAt: Date;\n expiresAt: Date | null;\n}\n\nexport type AddMuteResult =\n | {\n ok: true;\n changed: true;\n state: 'muted' | 'updated';\n record: MuteRecord;\n }\n | {\n ok: true;\n changed: false;\n state: 'already_muted';\n record: MuteRecord;\n };\n\nexport type RemoveMuteResult =\n | {\n ok: true;\n changed: true;\n state: 'unmuted';\n }\n | {\n ok: true;\n changed: false;\n state: 'already_unmuted';\n };\n\nexport type MuteChangeResult = AddMuteResult | RemoveMuteResult;\n\nexport interface MuteEnforcement {\n message: Message;\n record: MuteRecord;\n}\n\nexport class MuteService {\n readonly #provider: WhatsAppProvider;\n readonly #store: MuteStore | undefined;\n\n constructor(provider: WhatsAppProvider, store?: MuteStore) {\n this.#provider = provider;\n this.#store = store;\n }\n\n get enabled(): boolean {\n return this.#store !== undefined;\n }\n\n async add(\n groupId: string,\n user: User,\n options: AddMuteOptions = {},\n ): Promise<AddMuteResult> {\n const store = this.#requireStore();\n const now = Date.now();\n\n if (options.durationMs !== undefined && options.durationMs <= 0) {\n throw new WhaNextError('ARGUMENT_INVALID', 'Mute duration must be greater than zero.');\n }\n\n const current = await this.#findActive(groupId, user.identities);\n\n if (current && current.expiresAt === null && options.durationMs === undefined) {\n return {\n ok: true,\n changed: false,\n state: 'already_muted',\n record: this.#record(current),\n };\n }\n\n const stored: StoredMute = {\n key: normalizeIdentity(user.id),\n groupId,\n user: user.toJSON(),\n identities: user.identities,\n createdAt: now,\n expiresAt: options.durationMs === undefined ? null : now + options.durationMs,\n };\n await this.#storage(\n 'upsert',\n () => store.upsert(stored),\n { groupId, userId: user.id },\n );\n return {\n ok: true,\n changed: true,\n state: current ? 'updated' : 'muted',\n record: this.#record(stored),\n };\n }\n\n async remove(groupId: string, user: User): Promise<RemoveMuteResult> {\n const store = this.#requireStore();\n const changed = await this.#storage(\n 'delete',\n () => store.delete(groupId, user.identities),\n { groupId, userId: user.id },\n );\n\n if (changed) {\n return {\n ok: true,\n changed: true,\n state: 'unmuted',\n };\n }\n\n return {\n ok: true,\n changed: false,\n state: 'already_unmuted',\n };\n }\n\n async get(groupId: string, user: User): Promise<MuteRecord | undefined> {\n this.#requireStore();\n const stored = await this.#findActive(groupId, user.identities);\n return stored ? this.#record(stored) : undefined;\n }\n\n async isMuted(groupId: string, user: User): Promise<boolean> {\n return (await this.get(groupId, user)) !== undefined;\n }\n\n async enforce(message: Message): Promise<MuteEnforcement | undefined> {\n if (!this.#store || !message.isGroup || message.keys.fromMe) {\n return undefined;\n }\n\n const stored = await this.#findActive(message.chatId, message.sender.identities);\n\n if (!stored) {\n return undefined;\n }\n\n try {\n await this.#provider.deleteMessage(message.keys);\n } catch (error) {\n throw new WhaNextError(\n 'PROVIDER_ERROR',\n 'Could not delete a message sent by a muted member.',\n {\n cause: error,\n context: {\n groupId: message.chatId,\n messageId: message.id,\n userId: message.sender.id,\n },\n recoverable: true,\n },\n );\n }\n\n return {\n message,\n record: this.#record(stored),\n };\n }\n\n async purgeExpired(): Promise<number> {\n const store = this.#requireStore();\n return this.#storage(\n 'purge',\n () => store.purgeExpired(Date.now()),\n );\n }\n\n async close(): Promise<void> {\n if (this.#store?.close) {\n await this.#storage('close', () => this.#store?.close?.());\n }\n }\n\n #record(stored: StoredMute): MuteRecord {\n return {\n groupId: stored.groupId,\n user: new User(stored.user),\n createdAt: new Date(stored.createdAt),\n expiresAt: stored.expiresAt === null ? null : new Date(stored.expiresAt),\n };\n }\n\n async #findActive(\n groupId: string,\n identities: readonly string[],\n ): Promise<StoredMute | undefined> {\n const stored = await this.#storage(\n 'find',\n () => this.#store?.find(groupId, identities),\n { groupId },\n );\n\n if (!stored) {\n return undefined;\n }\n\n if (stored.expiresAt !== null && stored.expiresAt <= Date.now()) {\n await this.#storage(\n 'delete_expired',\n () => this.#store?.delete(groupId, stored.identities),\n { groupId },\n );\n return undefined;\n }\n\n return stored;\n }\n\n #requireStore(): MuteStore {\n if (!this.#store) {\n throw new WhaNextError(\n 'MUTE_DISABLED',\n 'Mute is disabled. Enable it in create({ mute: { enabled: true } }).',\n );\n }\n\n return this.#store;\n }\n\n async #storage<Result>(\n action: string,\n operation: () => Result | Promise<Result>,\n context: Readonly<Record<string, unknown>> = {},\n ): Promise<Result> {\n try {\n return await operation();\n } catch (error) {\n throw new WhaNextError(\n 'STORAGE_ERROR',\n `Mute storage operation \"${action}\" failed.`,\n {\n cause: error,\n context: { action, ...context },\n recoverable: true,\n },\n );\n }\n }\n}\n","import { mkdirSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport {\n dirname,\n resolve,\n} from 'node:path';\nimport type { DatabaseSync as NodeDatabaseSync } from 'node:sqlite';\nimport { WhaNextError } from '@/errors/error.js';\nimport { normalizeIdentity } from '@/models/identity.js';\nimport type {\n MuteStore,\n StoredMute,\n} from '@/mute/mute-store.js';\n\ninterface MuteRow {\n mute_key: string;\n group_id: string;\n user_json: string;\n created_at: number;\n expires_at: number | null;\n}\n\nexport class SqliteMuteStore implements MuteStore {\n readonly #database: NodeDatabaseSync;\n\n constructor(path = './data/whanext.sqlite') {\n const databasePath = path === ':memory:' ? path : resolve(path);\n\n if (databasePath !== ':memory:') {\n mkdirSync(dirname(databasePath), { recursive: true });\n }\n\n let database: NodeDatabaseSync | undefined;\n\n try {\n const require = createRequire(import.meta.url);\n const sqlite = require('node:sqlite') as typeof import('node:sqlite');\n database = new sqlite.DatabaseSync(databasePath);\n database.exec('PRAGMA journal_mode = WAL');\n database.exec('PRAGMA busy_timeout = 5000');\n database.exec(`\n CREATE TABLE IF NOT EXISTS whanext_mutes (\n group_id TEXT NOT NULL,\n identity TEXT NOT NULL,\n mute_key TEXT NOT NULL,\n user_json TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n expires_at INTEGER,\n PRIMARY KEY (group_id, identity)\n ) STRICT;\n CREATE INDEX IF NOT EXISTS whanext_mutes_expiration\n ON whanext_mutes (expires_at);\n CREATE INDEX IF NOT EXISTS whanext_mutes_key\n ON whanext_mutes (group_id, mute_key);\n `);\n } catch (error) {\n database?.close();\n throw new WhaNextError(\n 'STORAGE_ERROR',\n 'Could not initialize the SQLite mute store.',\n {\n cause: error,\n context: { database: databasePath },\n },\n );\n }\n\n this.#database = database;\n }\n\n upsert(mute: StoredMute): void {\n const identities = this.#identities(mute.identities);\n const existingKeys = this.#matchingKeys(mute.groupId, identities);\n\n this.#transaction(() => {\n for (const key of existingKeys) {\n this.#database.prepare(\n 'DELETE FROM whanext_mutes WHERE group_id = ? AND mute_key = ?',\n ).run(mute.groupId, key);\n }\n\n const insert = this.#database.prepare(`\n INSERT OR REPLACE INTO whanext_mutes (\n group_id,\n identity,\n mute_key,\n user_json,\n created_at,\n expires_at\n ) VALUES (?, ?, ?, ?, ?, ?)\n `);\n\n for (const identity of identities) {\n insert.run(\n mute.groupId,\n identity,\n mute.key,\n JSON.stringify(mute.user),\n mute.createdAt,\n mute.expiresAt,\n );\n }\n });\n }\n\n find(groupId: string, identities: readonly string[]): StoredMute | undefined {\n const normalized = this.#identities(identities);\n\n if (normalized.length === 0) {\n return undefined;\n }\n\n const placeholders = normalized.map(() => '?').join(', ');\n const row = this.#database.prepare(`\n SELECT mute_key, group_id, user_json, created_at, expires_at\n FROM whanext_mutes\n WHERE group_id = ? AND identity IN (${placeholders})\n LIMIT 1\n `).get(groupId, ...normalized) as unknown as MuteRow | undefined;\n\n if (!row) {\n return undefined;\n }\n\n if (row.expires_at !== null && row.expires_at <= Date.now()) {\n this.#database.prepare(\n 'DELETE FROM whanext_mutes WHERE group_id = ? AND mute_key = ?',\n ).run(groupId, row.mute_key);\n return undefined;\n }\n\n const identityRows = this.#database.prepare(`\n SELECT identity\n FROM whanext_mutes\n WHERE group_id = ? AND mute_key = ?\n `).all(groupId, row.mute_key) as unknown as Array<{ identity: string }>;\n\n return {\n key: row.mute_key,\n groupId: row.group_id,\n user: JSON.parse(row.user_json) as StoredMute['user'],\n identities: identityRows.map(({ identity }) => identity),\n createdAt: row.created_at,\n expiresAt: row.expires_at,\n };\n }\n\n delete(groupId: string, identities: readonly string[]): boolean {\n const keys = this.#matchingKeys(groupId, this.#identities(identities));\n\n if (keys.length === 0) {\n return false;\n }\n\n this.#transaction(() => {\n const statement = this.#database.prepare(\n 'DELETE FROM whanext_mutes WHERE group_id = ? AND mute_key = ?',\n );\n\n for (const key of keys) {\n statement.run(groupId, key);\n }\n });\n return true;\n }\n\n purgeExpired(now: number): number {\n const result = this.#database.prepare(`\n DELETE FROM whanext_mutes\n WHERE expires_at IS NOT NULL AND expires_at <= ?\n `).run(now);\n return Number(result.changes);\n }\n\n close(): void {\n this.#database.close();\n }\n\n #matchingKeys(groupId: string, identities: readonly string[]): string[] {\n if (identities.length === 0) {\n return [];\n }\n\n const placeholders = identities.map(() => '?').join(', ');\n const rows = this.#database.prepare(`\n SELECT DISTINCT mute_key\n FROM whanext_mutes\n WHERE group_id = ? AND identity IN (${placeholders})\n `).all(groupId, ...identities) as unknown as Array<{ mute_key: string }>;\n return rows.map(({ mute_key }) => mute_key);\n }\n\n #identities(identities: readonly string[]): string[] {\n return [...new Set(identities.map(normalizeIdentity).filter(Boolean))];\n }\n\n #transaction(operation: () => void): void {\n this.#database.exec('BEGIN IMMEDIATE');\n\n try {\n operation();\n this.#database.exec('COMMIT');\n } catch (error) {\n this.#database.exec('ROLLBACK');\n throw error;\n }\n }\n}\n","export class TypedEventEmitter<Events extends object> {\n readonly #listeners = new Map<keyof Events, Set<(payload: never) => void | Promise<void>>>();\n\n on<Event extends keyof Events>(\n event: Event,\n listener: (payload: Events[Event]) => void | Promise<void>,\n ): () => void {\n const listeners = this.#listeners.get(event) ?? new Set();\n listeners.add(listener as (payload: never) => void | Promise<void>);\n this.#listeners.set(event, listeners);\n\n return () => listeners.delete(listener as (payload: never) => void | Promise<void>);\n }\n\n async emit<Event extends keyof Events>(event: Event, payload: Events[Event]): Promise<void> {\n const listeners = this.#listeners.get(event);\n\n if (!listeners) {\n return;\n }\n\n await Promise.all([...listeners].map((listener) => listener(payload as never)));\n }\n}\n","import type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport class ChatService {\n readonly #provider: WhatsAppProvider;\n\n constructor(provider: WhatsAppProvider) {\n this.#provider = provider;\n }\n\n typing(chatId: string): Promise<void> {\n return this.#provider.setPresence(chatId, 'typing');\n }\n\n recording(chatId: string): Promise<void> {\n return this.#provider.setPresence(chatId, 'recording');\n }\n\n stop(chatId: string): Promise<void> {\n return this.#provider.setPresence(chatId, 'paused');\n }\n\n stopTyping(chatId: string): Promise<void> {\n return this.stop(chatId);\n }\n\n rejectCall(callId: string, from: string): Promise<void> {\n return this.#provider.rejectCall(callId, from);\n }\n}\n","import type { CacheStore } from '@/cache/cache-store.js';\nimport type {\n ChangeResult,\n GroupAccess,\n GroupSnapshot,\n InviteResult,\n} from '@/models/group.js';\nimport { identitiesMatch } from '@/models/identity.js';\nimport type { MessageKey } from '@/models/message.js';\nimport { User } from '@/models/user.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport class GroupService {\n readonly #provider: WhatsAppProvider;\n readonly #cache: CacheStore;\n readonly #ttlMs: number;\n readonly #requests = new Map<string, Promise<GroupSnapshot>>();\n\n constructor(provider: WhatsAppProvider, cache: CacheStore, ttlMs = 300_000) {\n this.#provider = provider;\n this.#cache = cache;\n this.#ttlMs = ttlMs;\n }\n\n async open(groupId: string): Promise<ChangeResult<'open' | 'already_open'>> {\n const group = await this.metadata(groupId);\n\n if (group.access === 'open') {\n return { ok: true, changed: false, state: 'already_open' };\n }\n\n await this.#provider.setGroupAccess(groupId, 'open');\n await this.invalidate(groupId);\n return { ok: true, changed: true, state: 'open' };\n }\n\n async close(groupId: string): Promise<ChangeResult<'closed' | 'already_closed'>> {\n const group = await this.metadata(groupId);\n\n if (group.access === 'closed') {\n return { ok: true, changed: false, state: 'already_closed' };\n }\n\n await this.#provider.setGroupAccess(groupId, 'closed');\n await this.invalidate(groupId);\n return { ok: true, changed: true, state: 'closed' };\n }\n\n async invite(groupId: string): Promise<InviteResult> {\n const code = await this.#provider.getGroupInviteCode(groupId);\n return { ok: true, code, url: `https://chat.whatsapp.com/${code}` };\n }\n\n async revokeInvite(groupId: string): Promise<InviteResult> {\n const code = await this.#provider.revokeGroupInvite(groupId);\n return { ok: true, code, url: `https://chat.whatsapp.com/${code}` };\n }\n\n async pin(groupId: string, key: MessageKey): Promise<ChangeResult<'pinned'>> {\n await this.#provider.setMessagePin(groupId, key, true);\n return { ok: true, changed: true, state: 'pinned' };\n }\n\n async unpin(groupId: string, key: MessageKey): Promise<ChangeResult<'unpinned'>> {\n await this.#provider.setMessagePin(groupId, key, false);\n return { ok: true, changed: true, state: 'unpinned' };\n }\n\n async metadata(groupId: string, refresh = false): Promise<GroupSnapshot> {\n const key = this.#key(groupId);\n\n if (!refresh) {\n const cached = await this.#cache.get<GroupSnapshot>(key);\n\n if (cached) {\n return cached;\n }\n }\n\n const pending = this.#requests.get(key);\n\n if (pending) {\n return pending;\n }\n\n const request = this.#loadMetadata(key, groupId);\n this.#requests.set(key, request);\n\n try {\n return await request;\n } finally {\n this.#requests.delete(key);\n }\n }\n\n async isAdmin(\n groupId: string,\n memberIds: string | readonly string[],\n ): Promise<boolean> {\n if (!groupId.endsWith('@g.us')) {\n return false;\n }\n\n const group = await this.metadata(groupId);\n const identities = typeof memberIds === 'string' ? [memberIds] : memberIds;\n const participant = group.participants.find((item) =>\n this.#matchesParticipant(item, identities));\n return participant?.role === 'admin' || participant?.role === 'owner';\n }\n\n async isCurrentUserAdmin(groupId: string): Promise<boolean> {\n const ids = this.#provider.getCurrentUserIds();\n\n if (ids.length === 0 || !groupId.endsWith('@g.us')) {\n return false;\n }\n\n const group = await this.metadata(groupId);\n return group.participants.some((participant) =>\n this.#matchesParticipant(participant, ids)\n && (participant.role === 'admin' || participant.role === 'owner'));\n }\n\n async resolveUser(groupId: string, user: User): Promise<User> {\n if (!groupId.endsWith('@g.us')) {\n return user;\n }\n\n const group = await this.metadata(groupId);\n const participant = group.participants.find((item) =>\n this.#matchesParticipant(item, user.identities));\n\n if (!participant) {\n return user;\n }\n\n return new User({\n id: participant.id,\n identities: [\n participant.id,\n ...(participant.lid ? [participant.lid] : []),\n ...(participant.phoneNumber ? [participant.phoneNumber] : []),\n ],\n ...(participant.lid ? { lid: participant.lid } : {}),\n ...(participant.phoneNumber ? {\n jid: participant.phoneNumber,\n phoneNumber: participant.phoneNumber,\n } : {}),\n ...(user.name ? { name: user.name } : {}),\n });\n }\n\n invalidate(groupId: string): Promise<void> {\n return this.#cache.delete(this.#key(groupId));\n }\n\n #key(groupId: string): string {\n return `group:${groupId}`;\n }\n\n async #loadMetadata(key: string, groupId: string): Promise<GroupSnapshot> {\n const group = await this.#provider.getGroup(groupId);\n await this.#cache.set(key, group, this.#ttlMs);\n return group;\n }\n\n #matchesParticipant(\n participant: GroupSnapshot['participants'][number],\n identities: readonly string[],\n ): boolean {\n const participantIds = [participant.id, participant.lid, participant.phoneNumber]\n .filter((identity): identity is string => identity !== undefined);\n return identities.some((identity) =>\n participantIds.some((participantId) =>\n identitiesMatch(identity, participantId)));\n }\n}\n","import type {\n AudioContent,\n DownloadedMedia,\n ImageContent,\n Message,\n MessageKey,\n SentMessage,\n VideoContent,\n} from '@/models/message.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport class MediaService {\n readonly #provider: WhatsAppProvider;\n\n constructor(provider: WhatsAppProvider) {\n this.#provider = provider;\n }\n\n image(chatId: string, content: ImageContent): Promise<SentMessage> {\n return this.#provider.sendMessage(chatId, content);\n }\n\n video(chatId: string, content: VideoContent): Promise<SentMessage> {\n return this.#provider.sendMessage(chatId, content);\n }\n\n audio(chatId: string, content: AudioContent): Promise<SentMessage> {\n return this.#provider.sendMessage(chatId, content);\n }\n\n download(message: Message | MessageKey): Promise<DownloadedMedia> {\n const key = 'keys' in message ? message.keys : message;\n return this.#provider.downloadMedia(key);\n }\n}\n","import { WhaNextError } from '@/errors/error.js';\nimport type {\n ChangeResult,\n GroupParticipant,\n GroupSnapshot,\n MemberActionState,\n} from '@/models/group.js';\nimport { identitiesMatch } from '@/models/identity.js';\nimport type { User } from '@/models/user.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\nimport type { GroupService } from '@/services/group-service.js';\n\nexport class MemberService {\n readonly #provider: WhatsAppProvider;\n readonly #group: GroupService;\n\n constructor(provider: WhatsAppProvider, group: GroupService) {\n this.#provider = provider;\n this.#group = group;\n }\n\n async remove(groupId: string, member: string | User): Promise<ChangeResult<MemberActionState>> {\n const { group, participant } = await this.#participant(groupId, member);\n\n if (!participant) {\n return { ok: true, changed: false, state: 'already_removed' };\n }\n\n await this.#update(groupId, this.#actionId(group, participant), 'remove');\n await this.#group.invalidate(groupId);\n return { ok: true, changed: true, state: 'removed' };\n }\n\n async promote(groupId: string, member: string | User): Promise<ChangeResult<MemberActionState>> {\n const { group, participant } = await this.#participant(groupId, member);\n\n if (!participant) {\n return { ok: true, changed: false, state: 'not_in_group' };\n }\n\n if (participant.role === 'admin' || participant.role === 'owner') {\n return { ok: true, changed: false, state: 'already_admin' };\n }\n\n await this.#update(groupId, this.#actionId(group, participant), 'promote');\n await this.#group.invalidate(groupId);\n return { ok: true, changed: true, state: 'promoted' };\n }\n\n async demote(groupId: string, member: string | User): Promise<ChangeResult<MemberActionState>> {\n const { group, participant } = await this.#participant(groupId, member);\n\n if (!participant) {\n return { ok: true, changed: false, state: 'not_in_group' };\n }\n\n if (participant.role === 'member') {\n return { ok: true, changed: false, state: 'not_admin' };\n }\n\n await this.#update(groupId, this.#actionId(group, participant), 'demote');\n await this.#group.invalidate(groupId);\n return { ok: true, changed: true, state: 'demoted' };\n }\n\n async #participant(groupId: string, member: string | User): Promise<{\n group: GroupSnapshot;\n participant: GroupParticipant | undefined;\n }> {\n const group = await this.#group.metadata(groupId);\n const memberIds = typeof member === 'string' ? [member] : member.identities;\n const participant = group.participants.find((item) =>\n [item.id, item.lid, item.phoneNumber]\n .filter((identity): identity is string => identity !== undefined)\n .some((identity) =>\n memberIds.some((memberId) => identitiesMatch(identity, memberId))));\n return { group, participant };\n }\n\n #actionId(group: GroupSnapshot, participant: GroupParticipant): string {\n if (group.addressingMode === 'lid') {\n return participant.lid\n ?? (participant.id.endsWith('@lid')\n ? participant.id\n : participant.phoneNumber ?? participant.id);\n }\n\n return participant.phoneNumber\n ?? (participant.id.endsWith('@s.whatsapp.net')\n ? participant.id\n : participant.lid ?? participant.id);\n }\n\n async #update(\n groupId: string,\n memberId: string,\n action: 'remove' | 'promote' | 'demote',\n ): Promise<void> {\n const result = await this.#provider.updateParticipant(groupId, memberId, action);\n\n if (!result.success) {\n throw new WhaNextError(\n 'PROVIDER_ERROR',\n `WhatsApp rejected the member action with status ${result.status}.`,\n {\n context: { groupId, memberId, action, status: result.status },\n recoverable: true,\n },\n );\n }\n }\n}\n","import type {\n MentionTarget,\n Message,\n MessageContent,\n MessageKey,\n SentMessage,\n TextContent,\n} from '@/models/message.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport class MessageService {\n readonly #provider: WhatsAppProvider;\n\n constructor(provider: WhatsAppProvider) {\n this.#provider = provider;\n }\n\n send(chatId: string, content: MessageContent): Promise<SentMessage> {\n return this.#provider.sendMessage(chatId, content);\n }\n\n reply(message: Message, content: MessageContent): Promise<SentMessage> {\n return this.#provider.sendMessage(message.chatId, content, message.keys);\n }\n\n edit(message: Message | SentMessage | MessageKey, text: string): Promise<SentMessage> {\n const key = 'keys' in message ? message.keys : message;\n return this.#provider.editMessage(key, text);\n }\n\n delete(message: Message | SentMessage | MessageKey): Promise<void> {\n const key = 'keys' in message ? message.keys : message;\n return this.#provider.deleteMessage(key);\n }\n\n react(message: Message | SentMessage | MessageKey, emoji: string): Promise<SentMessage> {\n const key = 'keys' in message ? message.keys : message;\n return this.#provider.reactToMessage(key, emoji);\n }\n\n unreact(message: Message | SentMessage | MessageKey): Promise<SentMessage> {\n const key = 'keys' in message ? message.keys : message;\n return this.#provider.reactToMessage(key);\n }\n\n text(chatId: string, text: string, mentions?: MentionTarget[]): Promise<SentMessage> {\n const content: TextContent = { text };\n\n if (mentions !== undefined) {\n content.mentions = mentions;\n }\n\n return this.send(chatId, content);\n }\n}\n","import type { ArgsParser } from '@/commands/args-parser.js';\nimport type { Message } from '@/models/message.js';\nimport { User } from '@/models/user.js';\nimport type { GroupService } from '@/services/group-service.js';\n\nexport class UserService {\n readonly #group: GroupService;\n\n constructor(group: GroupService) {\n this.#group = group;\n }\n\n async resolve(message: Message, args: ArgsParser): Promise<User> {\n const mentioned = message.mentionedUsers[0];\n let user: User;\n\n if (mentioned) {\n if (args.peek()?.startsWith('@')) {\n args.skip();\n }\n\n user = mentioned;\n } else if (message.quoted?.sender) {\n user = message.quoted.sender;\n } else {\n user = args.user('membro');\n }\n\n return this.#group.resolveUser(message.chatId, user);\n }\n\n from(identity: string): User {\n if (!identity.includes('@')) {\n return User.fromPhoneNumber(identity);\n }\n\n return User.fromIdentities([identity]);\n }\n}\n","import type { CacheOptions } from '@/cache/cache-store.js';\nimport { MemoryCache } from '@/cache/memory-cache.js';\nimport {\n CommandRouter,\n type RouterOptions,\n} from '@/commands/router.js';\nimport {\n WhaNextError,\n toWhaNextError,\n} from '@/errors/error.js';\nimport {\n Logger,\n type LogLevel,\n type LoggerConfig,\n} from '@/logger/logger.js';\nimport type { CallEvent } from '@/models/call.js';\nimport type { GroupParticipantsChanged } from '@/models/group.js';\nimport type { Message } from '@/models/message.js';\nimport type { MuteOptions } from '@/mute/mute-store.js';\nimport {\n MuteService,\n type MuteEnforcement,\n} from '@/mute/mute-service.js';\nimport { SqliteMuteStore } from '@/mute/sqlite-mute-store.js';\nimport { TypedEventEmitter } from '@/provider/event-emitter.js';\nimport type {\n ConnectionUpdate,\n WhatsAppProvider,\n} from '@/provider/provider.js';\nimport { ChatService } from '@/services/chat-service.js';\nimport { GroupService } from '@/services/group-service.js';\nimport { MediaService } from '@/services/media-service.js';\nimport { MemberService } from '@/services/member-service.js';\nimport { MessageService } from '@/services/message-service.js';\nimport { UserService } from '@/services/user-service.js';\n\nexport interface AppEvents {\n message: Message;\n connection: ConnectionUpdate;\n error: WhaNextError;\n mute: MuteEnforcement;\n call: CallEvent;\n groupParticipantsChanged: GroupParticipantsChanged;\n}\n\nexport interface LoginOptions {\n onCode?: (code: string) => void | Promise<void>;\n timeoutMs?: number;\n}\n\nexport type AppHealthStatus = 'idle' | 'starting' | 'ready' | 'stopped';\n\nexport interface AppHealth {\n status: AppHealthStatus;\n state: ConnectionUpdate['state'];\n ready: boolean;\n uptimeMs: number;\n timestamp: Date;\n muteEnabled: boolean;\n logLevel: LogLevel;\n}\n\nexport interface WhaNextAppOptions {\n phone?: string;\n prefix?: string;\n cache?: CacheOptions;\n logger?: LoggerConfig;\n mute?: MuteOptions;\n router?: Omit<RouterOptions, 'prefix'>;\n}\n\nexport class WhaNextApp {\n readonly message: MessageService;\n readonly media: MediaService;\n readonly group: GroupService;\n readonly member: MemberService;\n readonly chat: ChatService;\n readonly user: UserService;\n readonly mute: MuteService;\n readonly logger: Logger;\n readonly #provider: WhatsAppProvider;\n readonly #phone: string | undefined;\n readonly #events = new TypedEventEmitter<AppEvents>();\n readonly #router: CommandRouter;\n readonly #startedAt = Date.now();\n #state: ConnectionUpdate['state'] = 'idle';\n\n constructor(\n provider: WhatsAppProvider,\n options: WhaNextAppOptions = {},\n logger = new Logger(options.logger),\n ) {\n this.#provider = provider;\n this.#phone = options.phone;\n this.logger = logger;\n const cache = options.cache?.store ?? new MemoryCache(\n options.cache?.memoryMaxEntries === undefined\n ? undefined\n : { maxEntries: options.cache.memoryMaxEntries },\n );\n this.group = new GroupService(provider, cache, options.cache?.groupTtlMs);\n this.member = new MemberService(provider, this.group);\n this.message = new MessageService(provider);\n this.media = new MediaService(provider);\n this.chat = new ChatService(provider);\n this.user = new UserService(this.group);\n const muteEnabled = options.mute?.enabled === true || options.mute?.store !== undefined;\n const muteStore = muteEnabled\n ? options.mute?.store ?? new SqliteMuteStore(options.mute?.database)\n : undefined;\n this.mute = new MuteService(provider, muteStore);\n this.#router = new CommandRouter(this.group, {\n ...options.router,\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n });\n this.#bind();\n this.logger.debug('Application initialized', {\n muteEnabled: this.mute.enabled,\n prefix: options.prefix ?? '!',\n });\n }\n\n get state(): ConnectionUpdate['state'] {\n return this.#state;\n }\n\n get isReady(): boolean {\n return this.#state === 'connected';\n }\n\n health(): AppHealth {\n return {\n status: this.#healthStatus(),\n state: this.#state,\n ready: this.isReady,\n uptimeMs: Date.now() - this.#startedAt,\n timestamp: new Date(),\n muteEnabled: this.mute.enabled,\n logLevel: this.logger.level,\n };\n }\n\n router(): CommandRouter {\n return this.#router;\n }\n\n on<Event extends keyof AppEvents>(\n event: Event,\n listener: (payload: AppEvents[Event]) => void | Promise<void>,\n ) {\n return this.#events.on(event, listener);\n }\n\n async login(options: LoginOptions = {}): Promise<void> {\n if (this.#state === 'connected') {\n return;\n }\n\n this.logger.info('Login started');\n\n let unsubscribe: () => void = () => undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const connected = new Promise<void>((resolve, reject) => {\n unsubscribe = this.#provider.on('connection', (update) => {\n if (update.state === 'connected') resolve();\n if (update.state === 'closed') {\n reject(\n new WhaNextError(\n 'CONNECTION_FAILED',\n 'WhatsApp closed the connection before login completed.',\n {\n cause: update.error,\n recoverable: true,\n },\n ),\n );\n }\n });\n\n timer = setTimeout(() => {\n reject(\n new WhaNextError(\n 'CONNECTION_FAILED',\n 'WhatsApp login timed out.',\n { recoverable: true },\n ),\n );\n }, options.timeoutMs ?? 300_000);\n });\n\n try {\n await this.#provider.connect();\n\n if (this.#phone) {\n const code = await this.#provider.requestPairingCode(this.#phone);\n\n if (code) {\n this.logger.info('Pairing code generated');\n\n if (options.onCode) {\n await options.onCode(code);\n }\n }\n }\n\n await connected;\n } finally {\n unsubscribe();\n if (timer) clearTimeout(timer);\n }\n }\n\n async disconnect(): Promise<void> {\n this.logger.info('Disconnecting application');\n\n try {\n await this.#provider.disconnect();\n } finally {\n await this.mute.close();\n }\n }\n\n #bind(): void {\n this.#provider.on('connection', async (update) => {\n this.#state = update.state;\n this.#logConnection(update);\n await this.#events.emit('connection', update);\n });\n\n this.#provider.on('groupChanged', ({ groupId }) => this.group.invalidate(groupId));\n\n this.#provider.on('groupParticipantsChanged', async (change) => {\n await this.group.invalidate(change.groupId);\n await this.#events.emit('groupParticipantsChanged', change);\n });\n\n this.#provider.on('call', async (call) => {\n this.logger.debug('Call received', {\n callId: call.id,\n from: call.from,\n status: call.status,\n });\n await this.#events.emit('call', call);\n });\n\n this.#provider.on('message', async (message) => {\n try {\n const enforcement = await this.mute.enforce(message);\n\n if (enforcement) {\n this.logger.info('Muted message deleted', {\n groupId: message.chatId,\n messageId: message.id,\n userId: message.sender.id,\n });\n await this.#events.emit('mute', enforcement);\n return;\n }\n } catch (error) {\n await this.#reportError(error, { messageId: message.id });\n return;\n }\n\n try {\n this.logger.debug('Message received', {\n chatId: message.chatId,\n messageId: message.id,\n senderId: message.sender.id,\n });\n await this.#events.emit('message', message);\n const dispatched = await this.#router.dispatch(message);\n\n if (dispatched) {\n this.logger.debug('Command dispatched', {\n chatId: message.chatId,\n messageId: message.id,\n });\n }\n } catch (error) {\n await this.#reportError(error, { messageId: message.id });\n }\n });\n }\n\n #healthStatus(): AppHealthStatus {\n if (this.#state === 'connected') {\n return 'ready';\n }\n\n if (this.#state === 'closed') {\n return 'stopped';\n }\n\n if (this.#state === 'connecting' || this.#state === 'reconnecting') {\n return 'starting';\n }\n\n return 'idle';\n }\n\n #logConnection(update: ConnectionUpdate): void {\n const context = {\n ...(update.attempt !== undefined ? { attempt: update.attempt } : {}),\n ...(update.error ? { error: update.error } : {}),\n };\n\n if (update.state === 'connected') {\n this.logger.info('WhatsApp connected');\n } else if (update.state === 'reconnecting') {\n this.logger.warn('WhatsApp reconnecting', context);\n } else if (update.state === 'closed' && update.error) {\n this.logger.warn('WhatsApp connection closed', context);\n } else if (update.state === 'closed') {\n this.logger.info('WhatsApp connection closed');\n } else {\n this.logger.debug('WhatsApp connecting', context);\n }\n }\n\n async #reportError(\n error: unknown,\n context: Readonly<Record<string, unknown>>,\n ): Promise<void> {\n const normalized = toWhaNextError(error, context);\n this.logger.error(normalized.message, {\n code: normalized.code,\n ...normalized.context,\n });\n await this.#events.emit('error', normalized);\n }\n}\n","export enum Browser {\n Windows = 'windows',\n MacOS = 'macos',\n Ubuntu = 'ubuntu',\n}","import {\n Browsers,\n DisconnectReason,\n downloadMediaMessage,\n makeWASocket,\n proto,\n useMultiFileAuthState,\n type AnyMessageContent,\n type WACallEvent,\n type WAMessage,\n type WAMessageKey,\n type WASocket,\n} from '@whiskeysockets/baileys';\nimport { Browser } from '@/auth/browser.js';\nimport { WhaNextError } from '@/errors/error.js';\nimport { Logger } from '@/logger/logger.js';\nimport type { CallEvent, CallStatus } from '@/models/call.js';\nimport type {\n GroupAccess,\n GroupParticipantsChanged,\n GroupSnapshot,\n} from '@/models/group.js';\nimport type {\n MediaSource,\n DownloadedMedia,\n MentionTarget,\n MessageContent,\n MessageKey,\n SentMessage,\n} from '@/models/message.js';\nimport {\n createBaileysLogger,\n} from '@/provider/baileys/baileys-logger.js';\nimport {\n normalizeBaileysMessage,\n normalizeKey,\n} from '@/provider/baileys/normalize-message.js';\nimport { TypedEventEmitter } from '@/provider/event-emitter.js';\nimport type {\n ParticipantAction,\n ParticipantUpdateResult,\n PresenceState,\n ProviderEvents,\n WhatsAppProvider,\n} from '@/provider/provider.js';\n\nexport interface BaileysProviderOptions {\n auth: string;\n browser: Browser;\n logger?: Logger;\n messageCacheSize?: number;\n reconnect?: {\n enabled?: boolean;\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n };\n}\n\nexport class BaileysProvider implements WhatsAppProvider {\n readonly #options: BaileysProviderOptions;\n readonly #events = new TypedEventEmitter<ProviderEvents>();\n readonly #logger: Logger;\n readonly #messageStore = new Map<string, WAMessage>();\n readonly #messageCacheSize: number;\n #socket: WASocket | undefined;\n #saveCredentials: (() => Promise<void>) | undefined;\n #saveQueue: Promise<void> = Promise.resolve();\n #intentionalClose = false;\n #reconnectAttempt = 0;\n #reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n #registered = false;\n\n constructor(options: BaileysProviderOptions) {\n this.#options = options;\n this.#logger = options.logger ?? new Logger('silent');\n this.#messageCacheSize = Math.max(1, options.messageCacheSize ?? 1_000);\n }\n\n on<Event extends keyof ProviderEvents>(\n event: Event,\n listener: (payload: ProviderEvents[Event]) => void | Promise<void>,\n ) {\n return this.#events.on(event, listener);\n }\n\n async connect(): Promise<void> {\n if (this.#socket) {\n return;\n }\n\n this.#intentionalClose = false;\n await this.#events.emit('connection', {\n state: this.#reconnectAttempt > 0 ? 'reconnecting' : 'connecting',\n attempt: this.#reconnectAttempt,\n });\n\n try {\n const { state, saveCreds } = await useMultiFileAuthState(this.#options.auth);\n this.#registered = state.creds.registered;\n this.#saveCredentials = saveCreds;\n const socket = makeWASocket({\n auth: state,\n browser: this.#browserDescription(),\n logger: createBaileysLogger(this.#logger.child('baileys')),\n markOnlineOnConnect: false,\n enableAutoSessionRecreation: true,\n enableRecentMessageCache: true,\n getMessage: async (key) => this.#messageStore.get(this.#messageStoreKey(key))?.message ?? undefined,\n });\n this.#socket = socket;\n this.#bind(socket);\n } catch (error) {\n this.#socket = undefined;\n throw new WhaNextError('CONNECTION_FAILED', 'Could not start the WhatsApp connection.', {\n cause: error,\n recoverable: true,\n });\n }\n }\n\n async disconnect(): Promise<void> {\n this.#intentionalClose = true;\n if (this.#reconnectTimer) clearTimeout(this.#reconnectTimer);\n const socket = this.#socket;\n this.#socket = undefined;\n\n if (socket) {\n await socket.end(undefined);\n }\n\n await this.#events.emit('connection', { state: 'closed' });\n }\n\n getCurrentUserIds(): string[] {\n const user = this.#socket?.user;\n\n if (!user) {\n return [];\n }\n\n return [user.id, user.lid, user.phoneNumber]\n .filter((id): id is string => Boolean(id))\n .filter((id, index, ids) => ids.indexOf(id) === index);\n }\n\n async requestPairingCode(phone: string): Promise<string> {\n const normalized = phone.replace(/\\D/g, '');\n\n if (normalized.length < 10) {\n throw new WhaNextError(\n 'AUTH_INVALID_PHONE',\n 'The phone number must include its country code.',\n );\n }\n\n if (this.#registered) {\n return '';\n }\n\n const socket = this.#requireSocket();\n\n try {\n await socket.waitForConnectionUpdate(async (update) => Boolean(update.qr), 60_000);\n\n if (socket !== this.#socket) {\n throw new WhaNextError(\n 'CONNECTION_CLOSED',\n 'The WhatsApp socket changed while preparing the pairing code.',\n {\n recoverable: true,\n },\n );\n }\n\n return await socket.requestPairingCode(normalized);\n } catch (error) {\n if (error instanceof WhaNextError) {\n throw error;\n }\n\n throw new WhaNextError(\n 'CONNECTION_FAILED',\n 'Could not request the pairing code after the authentication challenge.',\n {\n cause: error,\n context: { statusCode: this.#statusCode(error) },\n recoverable: this.#statusCode(error) === DisconnectReason.connectionClosed,\n },\n );\n }\n }\n\n async sendMessage(\n chatId: string,\n content: MessageContent,\n replyTo?: MessageKey,\n ): Promise<SentMessage> {\n const socket = this.#requireSocket();\n const options = replyTo\n ? {\n quoted: {\n key: this.#toWaKey(replyTo),\n message: { conversation: '' },\n } as WAMessage,\n }\n : undefined;\n const result = await socket.sendMessage(chatId, this.#toContent(content), options);\n return this.#sent(result);\n }\n\n async reactToMessage(key: MessageKey, emoji?: string): Promise<SentMessage> {\n const result = await this.#requireSocket().sendMessage(key.chatId, {\n react: {\n text: emoji ?? '',\n key: this.#toWaKey(key),\n },\n });\n return this.#sent(result);\n }\n\n async downloadMedia(key: MessageKey): Promise<DownloadedMedia> {\n const message = this.#messageStore.get(this.#messageStoreKey(key));\n\n if (!message?.message) {\n throw new WhaNextError(\n 'MEDIA_NOT_AVAILABLE',\n 'The media is unavailable. Download it from the received message event while it is cached.',\n { recoverable: true },\n );\n }\n\n const data = await downloadMediaMessage(message, 'buffer', {}, {\n reuploadRequest: (current) => this.#requireSocket().updateMediaMessage(current),\n logger: createBaileysLogger(this.#logger.child('media')),\n });\n const media = normalizeBaileysMessage(message)?.media;\n\n if (!media) {\n throw new WhaNextError('MEDIA_NOT_AVAILABLE', 'The selected message does not contain media.');\n }\n\n return {\n data,\n kind: media.kind,\n ...(media.mimetype ? { mimetype: media.mimetype } : {}),\n ...(media.fileName ? { fileName: media.fileName } : {}),\n };\n }\n\n async editMessage(key: MessageKey, content: string): Promise<SentMessage> {\n const result = await this.#requireSocket().sendMessage(key.chatId, {\n text: content,\n edit: this.#toWaKey(key),\n });\n return this.#sent(result);\n }\n\n async deleteMessage(key: MessageKey): Promise<void> {\n await this.#requireSocket().sendMessage(key.chatId, { delete: this.#toWaKey(key) });\n }\n\n async getGroup(groupId: string): Promise<GroupSnapshot> {\n const metadata = await this.#requireSocket().groupMetadata(groupId);\n return {\n id: metadata.id,\n subject: metadata.subject,\n access: metadata.announce ? 'closed' : 'open',\n addressingMode: metadata.addressingMode === 'lid' ? 'lid' : 'pn',\n fetchedAt: new Date(),\n participants: metadata.participants.map((participant) => ({\n id: participant.id,\n ...(participant.lid ? { lid: participant.lid } : {}),\n ...(participant.phoneNumber ? { phoneNumber: participant.phoneNumber } : {}),\n role: participant.admin === 'superadmin' || participant.isSuperAdmin\n ? 'owner'\n : participant.admin === 'admin' || participant.isAdmin\n ? 'admin'\n : 'member',\n })),\n };\n }\n\n async setGroupAccess(groupId: string, access: GroupAccess): Promise<void> {\n const setting = access === 'closed' ? 'announcement' : 'not_announcement';\n await this.#requireSocket().groupSettingUpdate(groupId, setting);\n }\n\n async getGroupInviteCode(groupId: string): Promise<string> {\n const code = await this.#requireSocket().groupInviteCode(groupId);\n if (!code) {\n throw new WhaNextError(\n 'PROVIDER_ERROR',\n 'WhatsApp did not return a group invite code.',\n );\n }\n return code;\n }\n\n async revokeGroupInvite(groupId: string): Promise<string> {\n const code = await this.#requireSocket().groupRevokeInvite(groupId);\n if (!code) {\n throw new WhaNextError(\n 'PROVIDER_ERROR',\n 'WhatsApp did not return a new group invite code.',\n );\n }\n return code;\n }\n\n async setMessagePin(groupId: string, key: MessageKey, pinned: boolean): Promise<void> {\n await this.#requireSocket().sendMessage(groupId, {\n pin: this.#toWaKey(key),\n type: pinned ? proto.PinInChat.Type.PIN_FOR_ALL : proto.PinInChat.Type.UNPIN_FOR_ALL,\n ...(pinned ? { time: 604800 as const } : {}),\n });\n }\n\n async updateParticipant(\n groupId: string,\n memberId: string,\n action: ParticipantAction,\n ): Promise<ParticipantUpdateResult> {\n const [result] = await this.#requireSocket()\n .groupParticipantsUpdate(groupId, [memberId], action);\n const status = result?.status ?? 'unknown';\n return {\n success: status === '200',\n status,\n ...(result?.jid ? { memberId: result.jid } : {}),\n };\n }\n\n async setPresence(chatId: string, state: PresenceState): Promise<void> {\n const socket = this.#requireSocket();\n const presence = state === 'typing'\n ? 'composing'\n : state === 'recording'\n ? 'recording'\n : 'paused';\n await socket.sendPresenceUpdate(presence, chatId);\n }\n\n async rejectCall(callId: string, from: string): Promise<void> {\n await this.#requireSocket().rejectCall(callId, from);\n }\n\n #bind(socket: WASocket): void {\n socket.ev.on('creds.update', (update) => {\n if (update.registered !== undefined) {\n this.#registered = update.registered;\n }\n\n this.#saveQueue = this.#saveQueue.then(() => this.#saveCredentials?.()).then(() => undefined);\n });\n\n socket.ev.on('messages.upsert', ({ messages, type }) => {\n if (type !== 'notify') return;\n\n for (const raw of messages) {\n if (raw.key.id && raw.message) this.#remember(raw);\n const message = normalizeBaileysMessage(raw);\n if (message) void this.#events.emit('message', message);\n }\n });\n\n socket.ev.on('groups.update', (groups) => {\n for (const group of groups) {\n if (group.id) void this.#events.emit('groupChanged', { groupId: group.id });\n }\n });\n\n socket.ev.on('group-participants.update', (update) => {\n const change = this.#groupParticipantsChanged(update);\n void this.#events.emit('groupParticipantsChanged', change);\n const { id } = update;\n void this.#events.emit('groupChanged', { groupId: id });\n });\n\n socket.ev.on('call', (calls) => {\n for (const call of calls) {\n void this.#events.emit('call', this.#normalizeCall(call));\n }\n });\n\n socket.ev.on('connection.update', (update) => {\n void this.#handleConnectionUpdate(socket, update.connection, update.lastDisconnect?.error);\n });\n }\n\n async #handleConnectionUpdate(\n socket: WASocket,\n connection?: 'open' | 'connecting' | 'close',\n error?: Error,\n ): Promise<void> {\n if (socket !== this.#socket || !connection) return;\n\n if (connection === 'open') {\n this.#reconnectAttempt = 0;\n await this.#events.emit('connection', { state: 'connected' });\n return;\n }\n\n if (connection === 'connecting') {\n await this.#events.emit('connection', {\n state: 'connecting',\n attempt: this.#reconnectAttempt,\n });\n return;\n }\n\n this.#socket = undefined;\n\n if (this.#intentionalClose || this.#isTerminal(error)) {\n await this.#events.emit('connection', { state: 'closed', ...(error ? { error } : {}) });\n return;\n }\n\n await this.#scheduleReconnect(error);\n }\n\n async #scheduleReconnect(error?: Error): Promise<void> {\n const options = this.#options.reconnect;\n const maxAttempts = options?.maxAttempts ?? 10;\n\n if (options?.enabled === false || this.#reconnectAttempt >= maxAttempts) {\n await this.#events.emit('connection', { state: 'closed', ...(error ? { error } : {}) });\n return;\n }\n\n this.#reconnectAttempt += 1;\n await this.#events.emit('connection', {\n state: 'reconnecting',\n attempt: this.#reconnectAttempt,\n ...(error ? { error } : {}),\n });\n const initial = options?.initialDelayMs ?? 1_000;\n const maximum = options?.maxDelayMs ?? 30_000;\n const delay = Math.min(maximum, initial * 2 ** (this.#reconnectAttempt - 1));\n this.#reconnectTimer = setTimeout(\n () => void this.connect(),\n delay + Math.floor(Math.random() * 250),\n );\n }\n\n #browserDescription(): [string, string, string] {\n if (this.#options.browser === Browser.MacOS) return Browsers.macOS('Chrome');\n if (this.#options.browser === Browser.Ubuntu) return Browsers.ubuntu('Chrome');\n return Browsers.windows('Chrome');\n }\n\n #isTerminal(error?: Error): boolean {\n const statusCode = this.#statusCode(error);\n return statusCode === DisconnectReason.loggedOut\n || statusCode === DisconnectReason.badSession\n || statusCode === DisconnectReason.connectionReplaced;\n }\n\n #statusCode(error: unknown): number | undefined {\n return (error as { output?: { statusCode?: number } } | undefined)?.output?.statusCode;\n }\n\n #requireSocket(): WASocket {\n if (!this.#socket) {\n throw new WhaNextError(\n 'CONNECTION_CLOSED',\n 'WhatsApp is not connected.',\n { recoverable: true },\n );\n }\n\n return this.#socket;\n }\n\n #toContent(content: MessageContent): AnyMessageContent {\n if ('text' in content) {\n return {\n text: content.text,\n ...(content.mentions\n ? { mentions: this.#mentions(content.mentions) }\n : {}),\n };\n }\n\n if ('image' in content) {\n return {\n image: this.#media(content.image),\n ...(content.caption !== undefined ? { caption: content.caption } : {}),\n ...(content.mentions\n ? { mentions: this.#mentions(content.mentions) }\n : {}),\n ...(content.viewOnce !== undefined\n ? { viewOnce: content.viewOnce }\n : {}),\n };\n }\n\n if ('video' in content) {\n return {\n video: this.#media(content.video),\n ...(content.caption !== undefined ? { caption: content.caption } : {}),\n ...(content.mentions\n ? { mentions: this.#mentions(content.mentions) }\n : {}),\n ...(content.viewOnce !== undefined\n ? { viewOnce: content.viewOnce }\n : {}),\n ...(content.gif !== undefined ? { gifPlayback: content.gif } : {}),\n };\n }\n\n return {\n audio: this.#media(content.audio),\n ...(content.mimetype ? { mimetype: content.mimetype } : {}),\n ...(content.voice !== undefined ? { ptt: content.voice } : {}),\n };\n }\n\n #media(source: MediaSource): Buffer | { url: string } {\n if (source instanceof Uint8Array) {\n return Buffer.from(source);\n }\n\n if ('url' in source) {\n return { url: source.url };\n }\n\n return { url: source.path };\n }\n\n #mentions(mentions: readonly MentionTarget[]): string[] {\n return mentions.map((mention) =>\n typeof mention === 'string' ? mention : mention.mentionId);\n }\n\n #toWaKey(key: MessageKey): WAMessageKey {\n return {\n id: key.id,\n remoteJid: key.chatId,\n fromMe: key.fromMe,\n ...(key.participantId ? { participant: key.participantId } : {}),\n };\n }\n\n #sent(message: WAMessage | undefined): SentMessage {\n if (!message?.key.id || !message.key.remoteJid) {\n throw new WhaNextError('PROVIDER_ERROR', 'WhatsApp did not confirm the sent message.');\n }\n\n if (message.message) this.#remember(message);\n return {\n id: message.key.id,\n chatId: message.key.remoteJid,\n keys: normalizeKey(message.key),\n timestamp: new Date(),\n };\n }\n\n #normalizeCall(call: WACallEvent): CallEvent {\n return {\n id: call.id,\n chatId: call.chatId,\n from: call.from,\n status: this.#callStatus(call.status),\n isVideo: Boolean(call.isVideo),\n isGroup: Boolean(call.isGroup),\n date: call.date ?? new Date(),\n };\n }\n\n #groupParticipantsChanged(change: {\n id: string;\n action: GroupParticipantsChanged['action'];\n participants: Array<{ id?: string | null }>;\n author?: string | null;\n }): GroupParticipantsChanged {\n const participantIds = change.participants\n .map((participant) => participant.id)\n .filter((id): id is string => Boolean(id));\n\n return {\n groupId: change.id,\n action: change.action,\n participantIds,\n ...(change.author ? { authorId: change.author } : {}),\n };\n }\n\n #callStatus(status: WACallEvent['status']): CallStatus {\n const known: readonly CallStatus[] = [\n 'offer',\n 'ringing',\n 'preaccept',\n 'timeout',\n 'reject',\n 'accept',\n ];\n return known.find((value) => value === status) ?? 'timeout';\n }\n\n #remember(message: WAMessage): void {\n const key = this.#messageStoreKey(message.key);\n this.#messageStore.delete(key);\n this.#messageStore.set(key, message);\n\n while (this.#messageStore.size > this.#messageCacheSize) {\n const oldest = this.#messageStore.keys().next().value as string | undefined;\n if (oldest) this.#messageStore.delete(oldest);\n }\n }\n\n #messageStoreKey(\n key: Pick<WAMessageKey, 'id' | 'remoteJid'> | MessageKey,\n ): string {\n const chatId = 'chatId' in key ? key.chatId : key.remoteJid;\n return `${chatId ?? ''}:${key.id ?? ''}`;\n }\n}\n","import type {\n LogContext,\n Logger,\n} from '@/logger/logger.js';\n\ninterface ProviderLogger {\n level: string;\n child(context: Record<string, unknown>): ProviderLogger;\n trace(value: unknown, message?: string): void;\n debug(value: unknown, message?: string): void;\n info(value: unknown, message?: string): void;\n warn(value: unknown, message?: string): void;\n error(value: unknown, message?: string): void;\n}\n\nexport function createBaileysLogger(logger: Logger): ProviderLogger {\n return {\n level: logger.level,\n\n child(context) {\n const name = typeof context.class === 'string'\n ? context.class\n : 'internal';\n return createBaileysLogger(logger.child(name));\n },\n\n trace(value, message) {\n logger.debug(resolveMessage(value, message, 'Provider trace'), safeContext(value));\n },\n\n debug(value, message) {\n logger.debug(resolveMessage(value, message, 'Provider debug'), safeContext(value));\n },\n\n info(value, message) {\n logger.debug(resolveMessage(value, message, 'Provider info'), safeContext(value));\n },\n\n warn(value, message) {\n logger.warn(resolveMessage(value, message, 'Provider warning'), safeContext(value));\n },\n\n error(value, message) {\n logger.error(resolveMessage(value, message, 'Provider error'), safeContext(value));\n },\n };\n}\n\nfunction resolveMessage(\n value: unknown,\n message: string | undefined,\n fallback: string,\n): string {\n if (message) {\n return message;\n }\n\n return typeof value === 'string' ? value : fallback;\n}\n\nfunction safeContext(value: unknown): LogContext {\n if (value instanceof Error) {\n return { error: value };\n }\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return {};\n }\n\n const source = value as Record<string, unknown>;\n const allowed = [\n 'location',\n 'reason',\n 'status',\n 'statusCode',\n 'type',\n ];\n\n return Object.fromEntries(\n allowed\n .filter((key) => source[key] !== undefined)\n .map((key) => [key, source[key]]),\n );\n}\n","import {\n extractMessageContent,\n getContentType,\n normalizeMessageContent,\n type WAMessage,\n type WAMessageContent,\n type WAMessageKey,\n type proto,\n} from '@whiskeysockets/baileys';\nimport { uniqueIdentities } from '@/models/identity.js';\nimport type {\n MediaKind,\n Message,\n MessageKey,\n MessageMedia,\n QuotedMessage,\n} from '@/models/message.js';\nimport { User } from '@/models/user.js';\n\nexport function normalizeBaileysMessage(input: WAMessage): Message | undefined {\n const chatId = input.key.remoteJid;\n const id = input.key.id;\n\n if (!chatId || !id || !input.message) {\n return undefined;\n }\n\n const normalized = normalizeMessageContent(input.message);\n const content = extractMessageContent(normalized);\n\n if (!content) {\n return undefined;\n }\n\n const type = getContentType(content);\n const node = type ? content[type] : undefined;\n const context = getContextInfo(node);\n const senderIds = uniqueIdentities([\n input.key.participant,\n input.key.participantAlt,\n input.key.participantUsername?.includes('@')\n ? input.key.participantUsername\n : undefined,\n ]);\n const senderJid = senderIds.find((identity) =>\n identity.endsWith('@s.whatsapp.net') || identity.endsWith('@c.us'));\n const senderLid = senderIds.find((identity) => identity.endsWith('@lid'));\n const senderId = senderJid ?? senderLid ?? senderIds[0] ?? chatId;\n const sender = new User({\n id: senderId,\n identities: senderIds.length > 0 ? senderIds : [senderId],\n ...(input.pushName ? { name: input.pushName } : {}),\n });\n const mentionedUsers = (context?.mentionedJid ?? []).map((identity) =>\n User.fromIdentities([identity]));\n const media = getMedia(type, node, Boolean(input.key.isViewOnce));\n const text = getText(content);\n const caption = getCaption(content);\n const quoted = getQuoted(context, chatId);\n\n const message: Message = {\n id,\n jid: chatId,\n chatId,\n senderId,\n senderIds: senderIds.length > 0 ? senderIds : [senderId],\n sender,\n keys: normalizeKey(input.key),\n mentions: [...(context?.mentionedJid ?? [])],\n mentionedUsers,\n timestamp: toDate(input.messageTimestamp),\n isGroup: chatId.endsWith('@g.us'),\n isReply: quoted !== undefined,\n isViewOnce: media?.viewOnce ?? false,\n hasMedia: media !== undefined,\n };\n\n if (senderJid !== undefined) message.senderJid = senderJid;\n if (senderLid !== undefined) {\n message.lid = senderLid;\n message.senderLid = senderLid;\n }\n if (text !== undefined) message.text = text;\n if (caption !== undefined) message.caption = caption;\n if (media !== undefined) message.media = media;\n if (quoted !== undefined) message.quoted = quoted;\n return message;\n}\n\nexport function normalizeKey(key: WAMessageKey): MessageKey {\n const normalized: MessageKey = {\n id: key.id ?? '',\n chatId: key.remoteJid ?? '',\n fromMe: key.fromMe ?? false,\n };\n\n const participantId = key.participant ?? key.participantAlt;\n\n if (participantId !== null && participantId !== undefined) {\n normalized.participantId = participantId;\n }\n\n return normalized;\n}\n\nfunction getText(content: WAMessageContent): string | undefined {\n return content.conversation\n ?? content.extendedTextMessage?.text\n ?? content.buttonsResponseMessage?.selectedDisplayText\n ?? content.listResponseMessage?.title\n ?? undefined;\n}\n\nfunction getCaption(content: WAMessageContent): string | undefined {\n return content.imageMessage?.caption\n ?? content.videoMessage?.caption\n ?? content.documentMessage?.caption\n ?? undefined;\n}\n\nfunction getContextInfo(node: unknown): proto.IContextInfo | undefined {\n if (typeof node !== 'object' || node === null || !('contextInfo' in node)) {\n return undefined;\n }\n\n return (node as { contextInfo?: proto.IContextInfo }).contextInfo;\n}\n\nfunction getMedia(\n type: keyof WAMessageContent | undefined,\n node: unknown,\n keyViewOnce: boolean,\n): MessageMedia | undefined {\n const mapping: Partial<Record<keyof WAMessageContent, MediaKind>> = {\n imageMessage: 'image',\n videoMessage: 'video',\n audioMessage: 'audio',\n documentMessage: 'document',\n stickerMessage: 'sticker',\n };\n\n const kind = type ? mapping[type] : undefined;\n\n if (!kind || typeof node !== 'object' || node === null) {\n return undefined;\n }\n\n const value = node as {\n mimetype?: string | null;\n fileName?: string | null;\n seconds?: number | LongLike | null;\n viewOnce?: boolean | null;\n };\n const media: MessageMedia = {\n kind,\n viewOnce: keyViewOnce || value.viewOnce === true,\n };\n if (value.mimetype) media.mimetype = value.mimetype;\n if (value.fileName) media.fileName = value.fileName;\n if (value.seconds !== undefined && value.seconds !== null) media.seconds = Number(value.seconds);\n return media;\n}\n\nfunction getQuoted(\n context: proto.IContextInfo | undefined,\n chatId: string,\n): QuotedMessage | undefined {\n if (!context?.stanzaId) {\n return undefined;\n }\n\n const quoted = context.quotedMessage;\n const normalized = normalizeMessageContent(quoted);\n const content = extractMessageContent(normalized);\n const result: QuotedMessage = {\n key: {\n id: context.stanzaId,\n chatId: context.remoteJid ?? chatId,\n fromMe: false,\n },\n hasMedia: Boolean(\n content\n && getMedia(\n getContentType(content),\n content[getContentType(content) ?? 'conversation'],\n false,\n ),\n ),\n };\n\n if (context.participant) {\n result.senderId = context.participant;\n result.sender = User.fromIdentities([context.participant]);\n result.key.participantId = context.participant;\n }\n\n if (content) {\n const text = getText(content) ?? getCaption(content);\n if (text !== undefined) result.text = text;\n }\n\n return result;\n}\n\ninterface LongLike {\n toString(): string;\n}\n\nfunction toDate(value: number | LongLike | null | undefined): Date {\n const seconds = value === null || value === undefined ? Date.now() / 1_000 : Number(value);\n return new Date(seconds * 1_000);\n}\n","import { WhaNextApp } from '@/app/whanext-app.js';\nimport { Browser } from '@/auth/browser.js';\nimport type { CacheOptions } from '@/cache/cache-store.js';\nimport type { RouterOptions } from '@/commands/router.js';\nimport {\n Logger,\n type LoggerConfig,\n} from '@/logger/logger.js';\nimport type { MuteOptions } from '@/mute/mute-store.js';\nimport { BaileysProvider } from '@/provider/baileys/baileys-provider.js';\nimport type { WhatsAppProvider } from '@/provider/provider.js';\n\nexport interface ReconnectOptions {\n enabled?: boolean;\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n}\n\nexport interface CreateOptions {\n phone?: string;\n browser?: Browser;\n auth?: string;\n prefix?: string;\n cache?: CacheOptions;\n logger?: LoggerConfig;\n mute?: MuteOptions;\n router?: Omit<RouterOptions, 'prefix'>;\n reconnect?: ReconnectOptions;\n messageCacheSize?: number;\n provider?: WhatsAppProvider;\n}\n\nexport async function create(options: CreateOptions = {}): Promise<WhaNextApp> {\n const logger = new Logger(options.logger);\n const provider = options.provider ?? new BaileysProvider({\n auth: options.auth ?? './session',\n browser: options.browser ?? Browser.Windows,\n logger: logger.child('provider'),\n ...(options.messageCacheSize !== undefined\n ? { messageCacheSize: options.messageCacheSize }\n : {}),\n ...(options.reconnect ? { reconnect: options.reconnect } : {}),\n });\n\n return new WhaNextApp(provider, {\n ...(options.phone ? { phone: options.phone } : {}),\n ...(options.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options.cache ? { cache: options.cache } : {}),\n ...(options.logger ? { logger: options.logger } : {}),\n ...(options.mute ? { mute: options.mute } : {}),\n ...(options.router ? { router: options.router } : {}),\n }, logger);\n}\n","import type { ArgsParser } from '@/commands/args-parser.js';\nimport type { Message } from '@/models/message.js';\n\nexport interface CommandDefinition {\n name: string;\n description: string;\n aliases?: readonly string[];\n onlyGroup?: boolean;\n onlyPrivate?: boolean;\n onlyAdmin?: boolean;\n botMustBeAdmin?: boolean;\n execute(message: Message, args: ArgsParser): void | Promise<void>;\n}\n\nexport function defineCommand<const Command extends CommandDefinition>(command: Command): Command {\n return command;\n}\n\nexport function defineCommands<const Commands extends readonly CommandDefinition[]>(\n ...commands: Commands\n): Commands {\n return commands;\n}\n","import type { Dirent } from 'node:fs';\nimport { readdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport type { CommandDefinition } from '@/commands/command.js';\nimport { WhaNextError } from '@/errors/error.js';\n\nexport interface CommandRegistrar {\n command(definition: CommandDefinition): unknown;\n}\n\nexport interface LoadCommandsOptions {\n extensions?: readonly string[];\n recursive?: boolean;\n}\n\nexport interface LoadCommandsResult {\n loaded: readonly string[];\n skipped: readonly string[];\n commands: readonly LoadedCommand[];\n}\n\nexport interface LoadedCommand {\n name: string;\n filePath: string;\n}\n\nconst DEFAULT_EXTENSIONS = ['.js', '.mjs', '.cjs'] as const;\n\nexport async function loadCommands(\n registrar: CommandRegistrar,\n dirPath: string,\n options: LoadCommandsOptions = {},\n): Promise<LoadCommandsResult> {\n const extensions = options.extensions ?? DEFAULT_EXTENSIONS;\n const recursive = options.recursive ?? true;\n\n const entries = await readEntries(dirPath, recursive);\n const loaded: string[] = [];\n const skipped: string[] = [];\n const commands: LoadedCommand[] = [];\n\n for (const filePath of entries) {\n if (!extensions.includes(path.extname(filePath))) {\n skipped.push(filePath);\n continue;\n }\n\n const definitions = await importCommands(filePath);\n\n for (const definition of definitions) {\n registrar.command(definition);\n commands.push({ name: definition.name, filePath });\n }\n\n loaded.push(filePath);\n }\n\n return { loaded, skipped, commands };\n}\n\nasync function readEntries(dirPath: string, recursive: boolean): Promise<string[]> {\n let dirents: Dirent[];\n\n try {\n dirents = await readdir(dirPath, { recursive, withFileTypes: true });\n } catch (error) {\n throw new WhaNextError('COMMAND_LOAD_FAILED', `Could not read the commands directory \"${dirPath}\".`, {\n cause: error,\n context: { dirPath },\n });\n }\n\n return dirents\n .filter((dirent) => dirent.isFile())\n .map((dirent) => path.join(dirent.parentPath, dirent.name))\n .sort((left, right) => left.localeCompare(right));\n}\n\nasync function importCommands(filePath: string): Promise<CommandDefinition[]> {\n let module: Record<string, unknown>;\n\n try {\n module = await import(pathToFileURL(filePath).href);\n } catch (error) {\n throw new WhaNextError('COMMAND_LOAD_FAILED', `Could not import the command file \"${filePath}\".`, {\n cause: error,\n context: { filePath },\n });\n }\n\n const definitions: CommandDefinition[] = [];\n const seen = new Set<CommandDefinition>();\n const exports = [\n module.default,\n ...Object.entries(module)\n .filter(([name]) => name !== 'default')\n .map(([, value]) => value),\n ];\n\n for (const value of exports) {\n const candidates = Array.isArray(value) ? value : [value];\n\n for (const candidate of candidates) {\n if (isCommandDefinition(candidate) && !seen.has(candidate)) {\n seen.add(candidate);\n definitions.push(candidate);\n }\n }\n }\n\n if (definitions.length === 0) {\n throw new WhaNextError('COMMAND_LOAD_FAILED', `The file \"${filePath}\" does not export any valid commands.`, {\n context: { filePath },\n });\n }\n\n return definitions;\n}\n\nfunction isCommandDefinition(value: unknown): value is CommandDefinition {\n return (\n typeof value === 'object'\n && value !== null\n && typeof (value as CommandDefinition).name === 'string'\n && typeof (value as CommandDefinition).execute === 'function'\n );\n}\n"],"mappings":"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","names":["path","require","resolve","Browser"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whanext/core",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "A modern, high-level WhatsApp SDK for TypeScript with commands, groups, media, moderation and structured logging.",
5
5
  "type": "module",
6
6
  "sideEffects": false,