@whanext/core 0.14.0 → 0.14.1

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,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.14.1
4
+
5
+ ### Corrigido
6
+
7
+ - A normalização agora preserva corretamente o envelope de visualização única (`viewOnceMessage`, `viewOnceMessageV2` e `viewOnceMessageV2Extension`) antes de desembrulhar a mídia.
8
+ - `message.isViewOnce` passa a ser verdadeiro mesmo quando o Baileys representa a visualização única apenas pelo wrapper externo.
9
+ - Mensagens citadas agora expõem `quoted.isViewOnce`, `quoted.contentKind` e `quoted.media`, permitindo distinguir mídia normal de visualização única sem heurísticas na aplicação.
10
+ - `app.media.download()` aceita diretamente uma `QuotedMessage`, permitindo `app.media.download(message.quoted)` quando houver mídia citada.
11
+ - `app.account.jid`, `app.account.lid`, `app.account.phoneNumber` e `app.account.selfChatId` expõem identidades canônicas da própria conta. `selfChatId` prioriza PN JID sem sufixo de dispositivo antes de usar LID.
12
+
13
+ ### Compatibilidade
14
+
15
+ - Os novos campos de `QuotedMessage` são opcionais no contrato público para não quebrar providers customizados ou objetos criados manualmente. O provider Baileys oficial os preenche nas mensagens normalizadas.
16
+ - `app.media.download(message)` e `app.media.download(message.keys)` continuam funcionando sem alteração.
17
+
3
18
  ## 0.14.0
4
19
 
5
20
  ### Adicionado
package/README.md CHANGED
@@ -373,7 +373,21 @@ const downloaded = await app.media.download(message);
373
373
  await writeFile(`./downloads/${downloaded.fileName ?? message.id}`, downloaded.data);
374
374
  ```
375
375
 
376
- `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.
376
+ `download()` aceita a `Message` recebida, uma `QuotedMessage` ou uma `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.
377
+
378
+ Para visualização única citada, o provider oficial preserva os metadados do envelope sem expor tipos do Baileys:
379
+
380
+ ```ts
381
+ if (message.quoted?.isViewOnce && message.quoted.hasMedia) {
382
+ const media = await app.media.download(message.quoted);
383
+
384
+ console.log(message.quoted.contentKind); // image | video | audio
385
+ console.log(message.quoted.media?.kind);
386
+ console.log(media.mimetype);
387
+ }
388
+ ```
389
+
390
+ Isso também funciona quando a mídia de visualização única aparece dentro de envelopes `viewOnceMessageV2` ou `viewOnceMessageV2Extension`.
377
391
 
378
392
  Stickers aceitam `Uint8Array`, URL ou caminho local e devem estar em WebP, inclusive para animações. Texto, imagem e vídeo aceitam `User` diretamente em `mentions`.
379
393
 
@@ -559,6 +573,17 @@ if (ctx.isOwner) {
559
573
  }
560
574
  ```
561
575
 
576
+ A identidade da própria conta também pode ser consultada sem escolher manualmente entre JID e LID:
577
+
578
+ ```ts
579
+ console.log(app.account.jid); // 5531...@s.whatsapp.net
580
+ console.log(app.account.lid); // ...@lid
581
+ console.log(app.account.phoneNumber); // 5531...
582
+ console.log(app.account.selfChatId); // destino preferencial para falar consigo mesmo
583
+ ```
584
+
585
+ `selfChatId` prioriza o PN JID canônico e remove automaticamente sufixos de dispositivo como `:12@s.whatsapp.net`.
586
+
562
587
  Na API legada, use `onlyOwner: true`:
563
588
 
564
589
  ```ts
package/dist/index.d.ts CHANGED
@@ -86,6 +86,15 @@ interface QuotedMessage {
86
86
  senderId?: string;
87
87
  sender?: User;
88
88
  hasMedia: boolean;
89
+ /**
90
+ * Indica se a mensagem citada foi enviada como visualização única.
91
+ * O provider oficial sempre preenche este campo.
92
+ */
93
+ isViewOnce?: boolean;
94
+ /** Classificação normalizada do conteúdo citado. */
95
+ contentKind?: MessageContentKind;
96
+ /** Metadados da mídia citada, quando houver. */
97
+ media?: MessageMedia;
89
98
  }
90
99
  interface Message {
91
100
  id: string;
@@ -428,7 +437,7 @@ declare class MediaService {
428
437
  video(chatId: string, content: VideoContent): Promise<SentMessage>;
429
438
  audio(chatId: string, content: AudioContent): Promise<SentMessage>;
430
439
  sticker(chatId: string, content: StickerContent): Promise<SentMessage>;
431
- download(message: Message | MessageKey): Promise<DownloadedMedia>;
440
+ download(message: Message | QuotedMessage | MessageKey): Promise<DownloadedMedia>;
432
441
  }
433
442
 
434
443
  declare class MemberService {
@@ -715,6 +724,10 @@ declare class AccountService {
715
724
  readonly id: string | undefined;
716
725
  constructor(provider: WhatsAppProvider, id?: string);
717
726
  get ids(): readonly string[];
727
+ get jid(): string | undefined;
728
+ get lid(): string | undefined;
729
+ get phoneNumber(): string | undefined;
730
+ get selfChatId(): string | undefined;
718
731
  isOwner(message: Pick<Message, 'keys' | 'senderIds'>): boolean;
719
732
  }
720
733
 
package/dist/index.js CHANGED
@@ -1726,6 +1726,25 @@ var AccountService = class {
1726
1726
  get ids() {
1727
1727
  return uniqueIdentities(this.#provider.getCurrentUserIds());
1728
1728
  }
1729
+ get jid() {
1730
+ const identity = this.ids.find((candidate) => candidate.endsWith("@s.whatsapp.net") || candidate.endsWith("@c.us"));
1731
+ if (identity) {
1732
+ return normalizeIdentity(identity);
1733
+ }
1734
+ const phone = this.ids.map((candidate) => identityPhoneNumber(candidate)).find((candidate) => candidate !== void 0);
1735
+ return phone ? `${phone}@s.whatsapp.net` : void 0;
1736
+ }
1737
+ get lid() {
1738
+ const identity = this.ids.find((candidate) => candidate.endsWith("@lid"));
1739
+ return identity ? normalizeIdentity(identity) : void 0;
1740
+ }
1741
+ get phoneNumber() {
1742
+ const jid = this.jid;
1743
+ return jid ? identityPhoneNumber(jid) : void 0;
1744
+ }
1745
+ get selfChatId() {
1746
+ return this.jid ?? this.lid ?? this.ids[0];
1747
+ }
1729
1748
  isOwner(message) {
1730
1749
  if (message.keys.fromMe) {
1731
1750
  return true;
@@ -1900,7 +1919,7 @@ var MediaService = class {
1900
1919
  return this.#provider.sendMessage(chatId, content);
1901
1920
  }
1902
1921
  download(message) {
1903
- const key = "keys" in message ? message.keys : message;
1922
+ const key = "keys" in message ? message.keys : "key" in message ? message.key : message;
1904
1923
  return this.#provider.downloadMedia(key);
1905
1924
  }
1906
1925
  };
@@ -2331,6 +2350,13 @@ function unwrapMessageContent(input) {
2331
2350
  const nested = content.ephemeralMessage?.message ?? content.viewOnceMessage?.message ?? content.viewOnceMessageV2?.message ?? content.viewOnceMessageV2Extension?.message;
2332
2351
  return nested ? unwrapMessageContent(nested) : content;
2333
2352
  }
2353
+ function isViewOnceContent(input) {
2354
+ if (!input) return false;
2355
+ if (input.viewOnceMessage?.message || input.viewOnceMessageV2?.message || input.viewOnceMessageV2Extension?.message) {
2356
+ return true;
2357
+ }
2358
+ return isViewOnceContent(input.ephemeralMessage?.message);
2359
+ }
2334
2360
  function extractQuotedBaileysMessage(input) {
2335
2361
  const chatId = input.key.remoteJid;
2336
2362
  const content = unwrapMessageContent(input.message);
@@ -2376,7 +2402,8 @@ function normalizeBaileysMessage(input) {
2376
2402
  ...input.pushName ? { name: input.pushName } : {}
2377
2403
  });
2378
2404
  const mentionedUsers = (context?.mentionedJid ?? []).map((identity) => User.fromIdentities([identity]));
2379
- const media = getMedia(type, node, Boolean(input.key.isViewOnce));
2405
+ const viewOnce = Boolean(input.key.isViewOnce) || isViewOnceContent(input.message);
2406
+ const media = getMedia(type, node, viewOnce);
2380
2407
  const contentKind = getContentKind(type);
2381
2408
  const text = getText(content);
2382
2409
  const caption = getCaption(content);
@@ -2496,21 +2523,26 @@ function getQuoted(context, chatId) {
2496
2523
  return void 0;
2497
2524
  }
2498
2525
  const quoted = context.quotedMessage;
2526
+ const quotedIsViewOnce = isViewOnceContent(quoted);
2499
2527
  const content = unwrapMessageContent(quoted);
2528
+ const type = content ? getContentType(content) : void 0;
2529
+ const node = type && content ? content[type] : void 0;
2530
+ const media = getMedia(type, node, quotedIsViewOnce);
2500
2531
  const result = {
2501
2532
  key: {
2502
2533
  id: context.stanzaId,
2503
2534
  chatId: context.remoteJid ?? chatId,
2504
2535
  fromMe: false
2505
2536
  },
2506
- hasMedia: Boolean(
2507
- content && getMedia(
2508
- getContentType(content),
2509
- content[getContentType(content) ?? "conversation"],
2510
- false
2511
- )
2512
- )
2537
+ hasMedia: media !== void 0,
2538
+ isViewOnce: media?.viewOnce ?? quotedIsViewOnce
2513
2539
  };
2540
+ if (content) {
2541
+ result.contentKind = getContentKind(type);
2542
+ }
2543
+ if (media) {
2544
+ result.media = media;
2545
+ }
2514
2546
  if (context.participant) {
2515
2547
  result.senderId = context.participant;
2516
2548
  result.sender = User.fromIdentities([context.participant]);