@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 +25 -0
- package/CONTRIBUTING.md +3 -0
- package/README.md +38 -4
- package/SECURITY.md +1 -1
- package/dist/index.d.ts +27 -2
- package/dist/index.js +109 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
537
|
-
| `app.media` |
|
|
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
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
|
|
983
|
-
|
|
984
|
-
|
|
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) =>
|
|
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
|
|
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", (
|
|
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
|
|
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(
|
|
1983
|
-
this.#
|
|
1984
|
-
|
|
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