@ezychat/wa 0.1.42 → 0.1.44

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.
@@ -91,6 +91,7 @@ export declare class BaileysAdapter extends EventEmitter implements WaAdapter {
91
91
  sendPresence(chatJid: string, presence: 'composing' | 'paused'): Promise<void>;
92
92
  downloadMedia(messageId: string): Promise<Buffer | null>;
93
93
  getGroupInfo(groupJid: string): Promise<WaGroupInfo>;
94
+ checkNumber(phone: string): Promise<string | null>;
94
95
  getAbout(jid: string): Promise<string | null>;
95
96
  getProfilePicture(jid: string): Promise<string | null>;
96
97
  }
@@ -8,6 +8,7 @@ import { Lru } from './lru.js';
8
8
  import { jidType, mapWAMessage, toMs } from './mapping.js';
9
9
  import { quotedForChat, quotedFromRef } from './quoted.js';
10
10
  import { contactAliasPair, normalizeContactJid } from './contact-aliases.js';
11
+ import { checkedNumberJid } from './number-check.js';
11
12
  import { profilePhoto } from './photos.js';
12
13
  import { aboutFromStatusResult, mapGroupMetadata } from './groups.js';
13
14
  const RAW_CACHE_MAX = 2000;
@@ -326,7 +327,11 @@ export class BaileysAdapter extends EventEmitter {
326
327
  qr: null,
327
328
  lastError: null,
328
329
  me: user
329
- ? { jid: jidNormalizedUser(user.id), name: user.name ?? user.notify ?? null }
330
+ ? {
331
+ jid: jidNormalizedUser(user.id),
332
+ name: user.name ?? user.notify ?? null,
333
+ lid: user.lid ? jidNormalizedUser(user.lid) : null,
334
+ }
330
335
  : null,
331
336
  });
332
337
  }
@@ -673,6 +678,13 @@ export class BaileysAdapter extends EventEmitter {
673
678
  const sock = this.requireOpen();
674
679
  return mapGroupMetadata(await sock.groupMetadata(groupJid));
675
680
  }
681
+ async checkNumber(phone) {
682
+ const sock = this.requireOpen();
683
+ const jid = await checkedNumberJid(phone, (j) => sock.onWhatsApp(j));
684
+ // Result only, never the number: whether WhatsApp knows it.
685
+ this.logger.info({ found: jid !== null }, 'number check');
686
+ return jid;
687
+ }
676
688
  async getAbout(jid) {
677
689
  if (!this.sock || this._status.state !== 'open')
678
690
  throw new WaUnavailableError();
@@ -0,0 +1,10 @@
1
+ type OnWhatsApp = (jid: string) => Promise<Array<{
2
+ jid: string;
3
+ exists: boolean;
4
+ }> | undefined>;
5
+ /**
6
+ * The phone JID of a number that has WhatsApp, or null when it has none (or is not a number). `lookup`
7
+ * is the socket's `onWhatsApp`; it answers only for numbers with an account, so an empty list is "no".
8
+ */
9
+ export declare function checkedNumberJid(phone: string, lookup: OnWhatsApp): Promise<string | null>;
10
+ export {};
@@ -0,0 +1,11 @@
1
+ import { jidNormalizedUser } from 'baileys';
2
+ /**
3
+ * The phone JID of a number that has WhatsApp, or null when it has none (or is not a number). `lookup`
4
+ * is the socket's `onWhatsApp`; it answers only for numbers with an account, so an empty list is "no".
5
+ */
6
+ export async function checkedNumberJid(phone, lookup) {
7
+ if (!/^\d{6,15}$/.test(phone))
8
+ return null;
9
+ const [hit] = (await lookup(`${phone}@s.whatsapp.net`)) ?? [];
10
+ return hit?.exists ? jidNormalizedUser(hit.jid) : null;
11
+ }
@@ -23,6 +23,7 @@ export declare class FakeWaAdapter extends EventEmitter implements WaAdapter {
23
23
  private readonly media;
24
24
  private readonly groups;
25
25
  private readonly abouts;
26
+ private readonly notOnWhatsApp;
26
27
  /** Every getGroupInfo / getAbout call, for tests that check caching. */
27
28
  readonly groupInfoCalls: string[];
28
29
  readonly aboutCalls: string[];
@@ -61,6 +62,9 @@ export declare class FakeWaAdapter extends EventEmitter implements WaAdapter {
61
62
  getContactAliases(_jids: string[]): Promise<WaContactAlias[]>;
62
63
  getGroupInfo(groupJid: string): Promise<WaGroupInfo>;
63
64
  getAbout(jid: string): Promise<string | null>;
65
+ checkNumber(phone: string): Promise<string | null>;
66
+ /** checkNumber answers null for this number (every other valid number has an account). */
67
+ setNotOnWhatsApp(phone: string): void;
64
68
  /** Make the next getAbout calls fail, as a WhatsApp request error would. */
65
69
  aboutFails: boolean;
66
70
  /** What getGroupInfo returns for this group (members as WhatsApp lists them, no names). */
@@ -15,6 +15,7 @@ export class FakeWaAdapter extends EventEmitter {
15
15
  media = new Map();
16
16
  groups = new Map();
17
17
  abouts = new Map();
18
+ notOnWhatsApp = new Set();
18
19
  /** Every getGroupInfo / getAbout call, for tests that check caching. */
19
20
  groupInfoCalls = [];
20
21
  aboutCalls = [];
@@ -137,6 +138,17 @@ export class FakeWaAdapter extends EventEmitter {
137
138
  throw new Error('About lookup failed');
138
139
  return this.abouts.get(jid) ?? null;
139
140
  }
141
+ checkNumber(phone) {
142
+ if (this._status.state !== 'open')
143
+ return Promise.reject(new WaUnavailableError());
144
+ if (!/^\d{6,15}$/.test(phone) || this.notOnWhatsApp.has(phone))
145
+ return Promise.resolve(null);
146
+ return Promise.resolve(`${phone}@s.whatsapp.net`);
147
+ }
148
+ /** checkNumber answers null for this number (every other valid number has an account). */
149
+ setNotOnWhatsApp(phone) {
150
+ this.notOnWhatsApp.add(phone);
151
+ }
140
152
  /** Make the next getAbout calls fail, as a WhatsApp request error would. */
141
153
  aboutFails = false;
142
154
  // ---- test helpers ----
package/dist/types.d.ts CHANGED
@@ -148,6 +148,11 @@ export interface WaAdapter {
148
148
  getGroupInfo(groupJid: string): Promise<WaGroupInfo>;
149
149
  /** A person's WhatsApp "About" text; null when hidden or unset. Throws when it cannot be read. */
150
150
  getAbout(jid: string): Promise<string | null>;
151
+ /**
152
+ * Ask WhatsApp whether a phone number (digits with country code, no `+`) has an account: its phone
153
+ * JID, or null when it has none. Throws WaUnavailableError when offline.
154
+ */
155
+ checkNumber(phone: string): Promise<string | null>;
151
156
  /** Resolve existing local phone/LID mappings only; must not query WhatsApp. */
152
157
  getContactAliases(jids: string[]): Promise<WaContactAlias[]>;
153
158
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezychat/wa",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "type": "module",
5
5
  "description": "EzyChat core: WhatsApp adapter interface, Baileys adapter and fake adapter.",
6
6
  "license": "MIT",
@@ -37,7 +37,7 @@
37
37
  "typecheck": "tsc --noEmit"
38
38
  },
39
39
  "dependencies": {
40
- "@ezychat/shared": "0.1.42",
40
+ "@ezychat/shared": "0.1.44",
41
41
  "baileys": "^7.0.0-rc14",
42
42
  "pino": "^10.4.0",
43
43
  "qrcode": "^1.5.4"