@whanext/core 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Adicionado
6
+
7
+ - `guards.owner()` para restringir comandos à própria conta conectada ao WhatsApp.
8
+ - `onlyOwner: true` para manter o mesmo recurso disponível na API legada de comandos.
9
+ - `ctx.isOwner` e `ctx.account` no contexto moderno; em multi-account, `ctx.account.id` identifica qual conta executou o comando.
10
+ - `app.account` com os identificadores atuais da conta e `isOwner(message)` sem exigir JID, LID ou número manual.
11
+ - `createMulti()` e `WhaNextMultiApp` para manter várias contas independentes no mesmo processo.
12
+ - `multi.commands` para registrar comandos, middleware, handlers de erro e autoload em todas as contas da instância.
13
+ - `multi.login()`, `multi.disconnect()`, `multi.health()`, `multi.get()`, `multi.ids()` e `multi.isReady` para operar as contas em conjunto.
14
+ - `multi.on()` para observar eventos de todas as contas com `accountId`, aplicação e payload de origem.
15
+ - Sessões automáticas isoladas em `./sessions/<id>` quando `auth` não é informado.
16
+ - Banco de mute automático separado por conta (`./data/whanext-<id>.sqlite`) quando o mute é habilitado sem banco/store explícito.
17
+
18
+ ### Segurança e compatibilidade
19
+
20
+ - IDs de contas multi-account são validados para impedir caminhos de sessão inseguros.
21
+ - Diretórios `auth` duplicados são rejeitados entre contas que usam o provider padrão.
22
+ - `create()` e toda a API de uma única conta continuam compatíveis.
23
+ - Cada conta mantém provider, socket, sessão, cache, reconexão e identidade próprios; nenhuma sessão ativa é compartilhada entre contas.
24
+
25
+ ## 0.13.1
26
+
27
+ - Corrigido download de mídias para mensagens visualização única citadas, através do cache do payload citado carregado em `contextInfo`.
28
+ - Adicionado desempacotamento explícito para envelopes de mensagens efêmeras e de visualização única, incluindo `viewOnceMessageV2Extension`.
29
+
3
30
  ## 0.13.0
4
31
 
5
32
  - Adicionado `MessageService.repost()` para republicar qualquer mensagem do WhatsApp recebida recentemente, sem criar uma resposta.
package/README.md CHANGED
@@ -33,7 +33,9 @@ await app.login({
33
33
 
34
34
  - API pública sem objetos ou tipos crus do Baileys.
35
35
  - Login por pairing code, sessão persistente e reconexão automática.
36
+ - Uma ou várias contas independentes no mesmo processo com `createMulti()`.
36
37
  - Prefixo global e comandos declarativos com argumentos tipados.
38
+ - Comandos exclusivos da conta conectada com `guards.owner()` ou `onlyOwner`.
37
39
  - Usuários normalizados entre JID, LID e PN.
38
40
  - Mensagens, replies, edição, exclusão, menções, mídias e download normalizado.
39
41
  - Operações de grupos e membros com resultados idempotentes.
@@ -101,6 +103,62 @@ await app.login({
101
103
 
102
104
  O prefixo é definido uma vez. O router identifica o comando, remove o prefixo e cria o `ArgsParser` automaticamente.
103
105
 
106
+ ## Múltiplas contas
107
+
108
+ Para manter duas, três ou mais contas de WhatsApp no mesmo processo, use `createMulti()`. Cada conta possui conexão, sessão, cache, reconexão e identidade próprios. A instância conjunta apenas coordena essas aplicações independentes.
109
+
110
+ ```ts
111
+ import {
112
+ Browser,
113
+ createMulti,
114
+ defineCommand,
115
+ guards,
116
+ } from '@whanext/core';
117
+
118
+ const multi = await createMulti({
119
+ prefix: ';',
120
+ browser: Browser.Windows,
121
+ authRoot: './sessions',
122
+ logger: 'info',
123
+ accounts: [
124
+ { id: 'principal', phone: process.env.PHONE_1 },
125
+ { id: 'secundaria', phone: process.env.PHONE_2 },
126
+ { id: 'terceira', phone: process.env.PHONE_3 },
127
+ ],
128
+ });
129
+
130
+ multi.commands.command(defineCommand({
131
+ name: 'painel',
132
+ description: 'Exibe um painel exclusivo do dono.',
133
+ guards: [guards.owner()],
134
+ async execute(ctx) {
135
+ await ctx.reply(`Conta: ${ctx.account.id}`);
136
+ },
137
+ }));
138
+
139
+ await multi.login({
140
+ onCode(accountId, code) {
141
+ console.log(`[${accountId}] Código de pareamento:`, code);
142
+ },
143
+ });
144
+ ```
145
+
146
+ Quando `auth` não é informado na conta, o WhaNext cria automaticamente caminhos separados como `./sessions/principal`, `./sessions/secundaria` e `./sessions/terceira`. O mesmo diretório de sessão não pode ser usado por duas contas do provider padrão.
147
+
148
+ Uma conta específica continua sendo um `WhaNextApp` completo:
149
+
150
+ ```ts
151
+ const principal = multi.get('principal');
152
+
153
+ if (principal?.isReady) {
154
+ await principal.message.send('5511999999999@s.whatsapp.net', {
155
+ text: 'Olá pela conta principal.',
156
+ });
157
+ }
158
+ ```
159
+
160
+ `multi.commands.command()`, `use()`, `onError()` e `load()` aplicam a mesma configuração de comandos a todas as contas. Dentro de um comando, `ctx.account.id` informa qual conta recebeu e executou aquela interação. Eventos também podem ser observados em conjunto com `multi.on()`.
161
+
104
162
  ## Logging
105
163
 
106
164
  O nível padrão é `info`. Estão disponíveis `debug`, `info`, `warn`, `error` e `silent`.
@@ -477,6 +535,45 @@ app.commands.command(
477
535
  );
478
536
  ```
479
537
 
538
+ ### Comandos exclusivos do dono
539
+
540
+ O dono é a própria conta conectada naquela aplicação. Não é necessário salvar número, JID ou LID manualmente. O provider usa a marca de mensagem enviada pela própria conta e, quando necessário, compara as identidades normalizadas da sessão.
541
+
542
+ ```ts
543
+ app.commands.command(defineCommand({
544
+ name: 'chay',
545
+ description: 'Comando privado da conta conectada.',
546
+ guards: [guards.owner()],
547
+
548
+ async execute(ctx) {
549
+ await ctx.reply('💣 *Comando autorizado*');
550
+ },
551
+ }));
552
+ ```
553
+
554
+ No contexto moderno também é possível consultar a informação diretamente:
555
+
556
+ ```ts
557
+ if (ctx.isOwner) {
558
+ console.log(ctx.account.ids);
559
+ }
560
+ ```
561
+
562
+ Na API legada, use `onlyOwner: true`:
563
+
564
+ ```ts
565
+ app.router().command(defineCommand({
566
+ name: 'interno',
567
+ description: 'Comando exclusivo do dono.',
568
+ onlyOwner: true,
569
+ execute(message) {
570
+ return app.message.reply(message, { text: 'Autorizado.' });
571
+ },
572
+ }));
573
+ ```
574
+
575
+ Em uma instância criada com `createMulti()`, o dono é resolvido separadamente para cada conta. Uma mensagem enviada pela conta `principal` não passa automaticamente como dona da conta `secundaria`.
576
+
480
577
  ### Subcomandos
481
578
 
482
579
  ```ts
@@ -579,6 +676,7 @@ Restrições disponíveis:
579
676
  - `onlyPrivate`
580
677
  - `onlyAdmin`
581
678
  - `botMustBeAdmin`
679
+ - `onlyOwner`
582
680
 
583
681
  `ArgsParser` possui `string`, `number`, `boolean`, `enum`, `user`, `duration`, `peek`, `skip` e `rest`. `args.user()` retorna `User`, nunca uma string crua.
584
682
 
package/SECURITY.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  | Versão | Suporte |
6
6
  | --- | --- |
7
- | 0.8.x | Sim |
7
+ | 0.14.x | Sim |
8
8
  | anteriores | Não |
9
9
 
10
10
  ## Reportando uma vulnerabilidade
package/dist/index.d.ts CHANGED
@@ -129,9 +129,7 @@ type MediaSource = Uint8Array | {
129
129
  path: string;
130
130
  };
131
131
  type MentionTarget = string | User;
132
- /** Options for reposting a previously received message without quoting it. */
133
132
  interface RepostMessageOptions {
134
- /** Hidden or visible mentions injected into the reposted payload. */
135
133
  mentions?: readonly MentionTarget[];
136
134
  }
137
135
  interface TextContent {
@@ -470,7 +468,13 @@ interface CommandCatalogView {
470
468
  has(path: string): boolean;
471
469
  find(path: string): RegisteredCommand | undefined;
472
470
  }
471
+ interface CommandAccountContext {
472
+ readonly id: string | undefined;
473
+ readonly ids: readonly string[];
474
+ isOwner(message: Pick<Message, 'keys' | 'senderIds'>): boolean;
475
+ }
473
476
  interface CommandRuntimeServices {
477
+ account: CommandAccountContext;
474
478
  messages: MessageService;
475
479
  media: MediaService;
476
480
  groups: GroupService;
@@ -495,6 +499,8 @@ interface ReplyOptions {
495
499
  interface CommandContext<Schema extends CommandOptionSchema = CommandOptionSchema> extends Message {
496
500
  readonly message: Message;
497
501
  readonly user: User;
502
+ readonly account: CommandAccountContext;
503
+ readonly isOwner: boolean;
498
504
  readonly chat: CommandChatContext;
499
505
  readonly group: CommandGroupContext | undefined;
500
506
  readonly command: RegisteredCommand;
@@ -548,6 +554,7 @@ interface GuardResult {
548
554
  }
549
555
  type CommandGuard = (context: CommandContext) => boolean | void | GuardResult | Promise<boolean | void | GuardResult>;
550
556
  declare const guards: {
557
+ owner(): CommandGuard;
551
558
  group(): CommandGuard;
552
559
  private(): CommandGuard;
553
560
  userAdmin(): CommandGuard;
@@ -596,6 +603,7 @@ interface CommandMetadata {
596
603
  onlyPrivate?: boolean;
597
604
  onlyAdmin?: boolean;
598
605
  botMustBeAdmin?: boolean;
606
+ onlyOwner?: boolean;
599
607
  }
600
608
  interface ExecutableCommandDefinition<Schema extends CommandOptionSchema = CommandOptionSchema> extends CommandMetadata {
601
609
  options?: Schema;
@@ -702,6 +710,14 @@ declare class Logger {
702
710
  error(message: string, context?: LogContext): void;
703
711
  }
704
712
 
713
+ declare class AccountService {
714
+ #private;
715
+ readonly id: string | undefined;
716
+ constructor(provider: WhatsAppProvider, id?: string);
717
+ get ids(): readonly string[];
718
+ isOwner(message: Pick<Message, 'keys' | 'senderIds'>): boolean;
719
+ }
720
+
705
721
  interface AppEvents {
706
722
  message: Message;
707
723
  connection: ConnectionUpdate;
@@ -731,9 +747,11 @@ interface WhaNextAppOptions {
731
747
  logger?: LoggerConfig;
732
748
  mute?: MuteOptions;
733
749
  router?: Omit<RouterOptions, 'prefix'>;
750
+ accountId?: string;
734
751
  }
735
752
  declare class WhaNextApp {
736
753
  #private;
754
+ readonly account: AccountService;
737
755
  readonly message: MessageService;
738
756
  readonly media: MediaService;
739
757
  readonly group: GroupService;
@@ -777,9 +795,58 @@ interface CreateOptions {
777
795
  reconnect?: ReconnectOptions;
778
796
  messageCacheSize?: number;
779
797
  provider?: WhatsAppProvider;
798
+ accountId?: string;
780
799
  }
781
800
  declare function create(options?: CreateOptions): Promise<WhaNextApp>;
782
801
 
802
+ interface MultiAccountOptions extends Omit<CreateOptions, 'accountId'> {
803
+ id: string;
804
+ }
805
+ interface CreateMultiOptions extends Omit<CreateOptions, 'accountId' | 'auth' | 'phone' | 'provider'> {
806
+ accounts: readonly MultiAccountOptions[];
807
+ authRoot?: string;
808
+ }
809
+ interface MultiLoginOptions extends Omit<LoginOptions, 'onCode'> {
810
+ onCode?: (accountId: string, code: string) => void | Promise<void>;
811
+ }
812
+ interface MultiAppHealth extends AppHealth {
813
+ accountId: string;
814
+ }
815
+ interface MultiAppEvent<Event extends keyof AppEvents> {
816
+ accountId: string;
817
+ app: WhaNextApp;
818
+ payload: AppEvents[Event];
819
+ }
820
+ interface MultiLoadCommandsResult {
821
+ accountId: string;
822
+ result: LoadCommandsResult;
823
+ }
824
+ declare class MultiCommandRouter {
825
+ #private;
826
+ constructor(apps: ReadonlyMap<string, WhaNextApp>);
827
+ command(definition: CommandDefinition): this;
828
+ use(middleware: CommandMiddleware): this;
829
+ onError(handler: CommandErrorHandler): () => void;
830
+ load(dirPath: string | URL, options?: LoadCommandsOptions): Promise<readonly MultiLoadCommandsResult[]>;
831
+ }
832
+ declare class WhaNextMultiApp {
833
+ #private;
834
+ readonly commands: MultiCommandRouter;
835
+ constructor(apps: ReadonlyMap<string, WhaNextApp>);
836
+ get size(): number;
837
+ get isReady(): boolean;
838
+ ids(): readonly string[];
839
+ has(accountId: string): boolean;
840
+ get(accountId: string): WhaNextApp | undefined;
841
+ values(): readonly WhaNextApp[];
842
+ router(): MultiCommandRouter;
843
+ on<Event extends keyof AppEvents>(event: Event, listener: (entry: MultiAppEvent<Event>) => void | Promise<void>): () => void;
844
+ health(): readonly MultiAppHealth[];
845
+ login(options?: MultiLoginOptions): Promise<void>;
846
+ disconnect(): Promise<void>;
847
+ }
848
+ declare function createMulti(options: CreateMultiOptions): Promise<WhaNextMultiApp>;
849
+
783
850
  interface MemoryCacheStats {
784
851
  size: number;
785
852
  maxEntries: number;
@@ -812,4 +879,4 @@ declare class SqliteMuteStore implements MuteStore {
812
879
  close(): void;
813
880
  }
814
881
 
815
- export { type AddMuteOptions, type AddMuteResult, type AppEvents, type AppHealth, type AppHealthStatus, ArgsParser, type AudioContent, type BooleanOption, Browser, type CacheOptions, type CacheStore, type CallEvent, type CallStatus, type ChangeResult, type CommandCatalogOptions, type CommandCatalogView, type CommandChatContext, type CommandConcurrency, type CommandContext, type CommandCooldown, type CommandDefinition, type CommandErrorHandler, type CommandGroupContext, type CommandGroupDefinition, type CommandGuard, type CommandHelpOptions, type CommandHooks, type CommandLocalization, type CommandMetadata, type CommandMiddleware, type CommandOptionDefinition, type CommandOptionSchema, type CommandOptionValue, type CommandOptionValues, type CommandRegistrar, CommandRouter, type CommandRuntimeServices, type CommandScope, type ConcurrencyStrategy, type ConnectionState, type ConnectionUpdate, type CreateOptions, DeferredReply, type DownloadedMedia, type DurationOption, type EnumOption, type ExecutableCommandDefinition, type GroupAccess, type GroupAddressingMode, type GroupParticipant, type GroupParticipantAction, type GroupParticipantsChanged, type GroupRole, type GroupSnapshot, type GuardResult, 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 MemoryCacheStats, type MentionTarget, type Message, type MessageContent, type MessageContentKind, type MessageKey, type MessageMedia, type MuteChangeResult, type MuteEnforcement, type MuteOptions, type MuteRecord, MuteService, type MuteStore, type NumberOption, ParsedCommandOptions, type ParticipantUpdateResult, type PresenceState, type QuotedMessage, type ReconnectOptions, type RegisteredCommand, type RemoveMuteResult, type ReplyOptions, type RepostMessageOptions, type RouterOptions, type SentMessage, SqliteMuteStore, type StickerContent, type StoredMute, type StringOption, type TextContent, User, type UserData, type UserOption, type VideoContent, WhaNextApp, WhaNextError, type WhaNextErrorCode, type WhatsAppProvider, create, defineCommand, defineCommandGroup, defineCommands, defineSubcommand, guards, isCommandGroup, loadCommands, option, toWhaNextError };
882
+ export { AccountService, type AddMuteOptions, type AddMuteResult, type AppEvents, type AppHealth, type AppHealthStatus, ArgsParser, type AudioContent, type BooleanOption, Browser, type CacheOptions, type CacheStore, type CallEvent, type CallStatus, type ChangeResult, type CommandAccountContext, type CommandCatalogOptions, type CommandCatalogView, type CommandChatContext, type CommandConcurrency, type CommandContext, type CommandCooldown, type CommandDefinition, type CommandErrorHandler, type CommandGroupContext, type CommandGroupDefinition, type CommandGuard, type CommandHelpOptions, type CommandHooks, type CommandLocalization, type CommandMetadata, type CommandMiddleware, type CommandOptionDefinition, type CommandOptionSchema, type CommandOptionValue, type CommandOptionValues, type CommandRegistrar, CommandRouter, type CommandRuntimeServices, type CommandScope, type ConcurrencyStrategy, type ConnectionState, type ConnectionUpdate, type CreateMultiOptions, type CreateOptions, DeferredReply, type DownloadedMedia, type DurationOption, type EnumOption, type ExecutableCommandDefinition, type GroupAccess, type GroupAddressingMode, type GroupParticipant, type GroupParticipantAction, type GroupParticipantsChanged, type GroupRole, type GroupSnapshot, type GuardResult, 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 MemoryCacheStats, type MentionTarget, type Message, type MessageContent, type MessageContentKind, type MessageKey, type MessageMedia, type MultiAccountOptions, type MultiAppEvent, type MultiAppHealth, MultiCommandRouter, type MultiLoadCommandsResult, type MultiLoginOptions, type MuteChangeResult, type MuteEnforcement, type MuteOptions, type MuteRecord, MuteService, type MuteStore, type NumberOption, ParsedCommandOptions, type ParticipantUpdateResult, type PresenceState, type QuotedMessage, type ReconnectOptions, type RegisteredCommand, type RemoveMuteResult, type ReplyOptions, type RepostMessageOptions, type RouterOptions, type SentMessage, SqliteMuteStore, type StickerContent, type StoredMute, type StringOption, type TextContent, User, type UserData, type UserOption, type VideoContent, WhaNextApp, WhaNextError, type WhaNextErrorCode, WhaNextMultiApp, type WhatsAppProvider, create, createMulti, defineCommand, defineCommandGroup, defineCommands, defineSubcommand, guards, isCommandGroup, loadCommands, option, toWhaNextError };