@bot-wa/baileys 0.0.0-stage → 0.2.0-alpha.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/lib/browser.js ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Browser identity for the Baileys handshake.
3
+ *
4
+ * The `browser` tuple (`[os, browserName, osVersion]`) feeds three parts of the
5
+ * WhatsApp Web handshake: the registration `DeviceProps.platformType`, the
6
+ * companion web-client type sent with QR/pairing codes, and the login
7
+ * `webInfo`. Since late July 2026 WhatsApp closes non-standard clients with
8
+ * 428 "Connection Terminated" before the QR is shown; Baileys 7.0.0-rc14 ships
9
+ * the refreshed handshake and its default identity is `Browsers.macOS('Chrome')`.
10
+ *
11
+ * The old presets used `'Desktop'` (DeviceProps DESKTOP / companion ELECTRON) and
12
+ * `'Bot'` (DeviceProps falls back to CHROME but the companion type becomes
13
+ * OTHER_WEB_CLIENT), i.e. identities that disagree with what rc14 sends by
14
+ * default. Every preset now resolves to Chrome on the chosen OS so all three
15
+ * handshake fields agree.
16
+ */
17
+ import { Browsers } from '@whiskeysockets/baileys';
18
+ /** The browser name every preset advertises; matches Baileys' own default. */
19
+ const BROWSER_NAME = 'Chrome';
20
+ /**
21
+ * Resolve the `browser` socket option.
22
+ *
23
+ * - `undefined` → `undefined`: the caller must then OMIT the `browser` key so
24
+ * Baileys' default (`Browsers.macOS('Chrome')`) applies. `makeWASocket` spreads
25
+ * the user config over its defaults, so even `browser: undefined` would clobber it.
26
+ * - a preset → `Browsers.<os>('Chrome')`.
27
+ * - a tuple → returned verbatim (escape hatch, e.g. `Browsers.macOS('Desktop')`
28
+ * for full-history desktop emulation). WhatsApp may reject it.
29
+ */
30
+ export function resolveBrowser(browser) {
31
+ if (browser === undefined)
32
+ return undefined;
33
+ if (Array.isArray(browser))
34
+ return browser;
35
+ switch (browser) {
36
+ case 'macOS': return Browsers.macOS(BROWSER_NAME);
37
+ case 'ubuntu': return Browsers.ubuntu(BROWSER_NAME);
38
+ case 'windows': return Browsers.windows(BROWSER_NAME);
39
+ case 'appropriate': return Browsers.appropriate(BROWSER_NAME);
40
+ }
41
+ }
@@ -0,0 +1,52 @@
1
+ export declare class IdentityStore {
2
+ /** Bidirectional: lid→pn AND pn→lid (see {@link putBounded}). */
3
+ private map;
4
+ /**
5
+ * Record a `primary`/`alt` pair from an inbound key. `alt` is the PN twin of
6
+ * `primary` (or vice-versa); the pair is stored only when one side is a LID and
7
+ * the other a PN. Null/empty inputs are ignored.
8
+ */
9
+ observe(primary?: string | null, alt?: string | null): void;
10
+ /**
11
+ * Map a LID to its learned PN. Returns `jid` unchanged when it is not a LID, or
12
+ * when no PN twin has been learned yet (best-effort: it stabilises once learned).
13
+ */
14
+ canonical(jid: string): string;
15
+ /** True if a PN twin is already known for this LID (skips redundant async lookups). */
16
+ knowsPnFor(lid: string): boolean;
17
+ /** The learned twin of a user JID (the PN of a LID or the LID of a PN), if any. */
18
+ alias(jid: string): string | undefined;
19
+ /**
20
+ * Canonical id for a bare user/chat JID carried by a non-message event
21
+ * (presence, call, group participant). Learns `alt`, the twin the event
22
+ * carries alongside (`callerPn`, `authorPn`, a participant's `phoneNumber`),
23
+ * then applies the same rule as messages: learned LID → PN, device suffix
24
+ * stripped. Group/broadcast JIDs pass through normalised.
25
+ */
26
+ resolve(jid?: string | null, alt?: string | null): string;
27
+ }
28
+ /** The key fields canonicalisation reads; matches `WAMessageKey` and Baileys' reaction/vote keys. */
29
+ export interface IdentityKey {
30
+ remoteJid?: string | null;
31
+ remoteJidAlt?: string | null;
32
+ participant?: string | null;
33
+ participantAlt?: string | null;
34
+ fromMe?: boolean | null;
35
+ }
36
+ /**
37
+ * The single LID/PN rule for a message key, shared by every emitted event
38
+ * (messages, reactions, poll votes) so one person never shows up as a LID on
39
+ * one event type and as a PN on another.
40
+ *
41
+ * Learns the LID↔PN pairs the key exposes, prefers the PN twin, maps a learned
42
+ * LID back to its PN and strips device suffixes. `participant` overrides
43
+ * `key.participant` (Baileys puts broadcast senders on `WAMessage.participant`).
44
+ * For a `fromMe` DM key `senderId` is the chat partner, as for messages; callers
45
+ * that need the author of their own action substitute the bot's id.
46
+ */
47
+ export declare function canonicalKey(key: IdentityKey, identity: IdentityStore, participant?: string | null): {
48
+ chatId: string;
49
+ senderId: string;
50
+ isGroup: boolean;
51
+ rawParticipant: string | null;
52
+ };
@@ -0,0 +1,107 @@
1
+ /**
2
+ * IdentityStore — stabilises Baileys 7 LID/PN identity across messages.
3
+ *
4
+ * Baileys 7 addresses a DM partner (or group participant) by their opaque LID
5
+ * (`…@lid`) and rides the phone-number twin (`…@s.whatsapp.net`, "PN") alongside
6
+ * in `remoteJidAlt`/`participantAlt`. That twin is NOT present on every message:
7
+ * the same partner can arrive as `LID + PN twin` on one message and as a bare
8
+ * `LID` on the next. Because the conversation runtime keys active flows by
9
+ * identity, an inconsistent identity silently splits one person across two keys —
10
+ * the active `ask` never receives the answer and the flow re-prompts forever
11
+ * (the "flujos tienen líos" bug seen live).
12
+ *
13
+ * This store LEARNS a LID↔PN pairing the first time it sees both forms together,
14
+ * then CANONICALISES any later bare LID back to its PN. With it, all three
15
+ * representations (PN-only, LID+twin, bare-LID-once-learned) collapse to a single
16
+ * stable PN identity, so `keyFor()` never flips mid-conversation.
17
+ */
18
+ import { normalize, normalizeInboundKey, isLidUser, isPnUser } from './jid.js';
19
+ import { putBounded } from './boundedMap.js';
20
+ /** Cap on stored pairs — one bot rarely talks to more than a few thousand LIDs. */
21
+ const IDENTITY_MAX = 4000;
22
+ export class IdentityStore {
23
+ /** Bidirectional: lid→pn AND pn→lid (see {@link putBounded}). */
24
+ map = new Map();
25
+ /**
26
+ * Record a `primary`/`alt` pair from an inbound key. `alt` is the PN twin of
27
+ * `primary` (or vice-versa); the pair is stored only when one side is a LID and
28
+ * the other a PN. Null/empty inputs are ignored.
29
+ */
30
+ observe(primary, alt) {
31
+ if (!primary || !alt)
32
+ return;
33
+ const p = normalize(primary);
34
+ const a = normalize(alt);
35
+ if (isLidUser(p) && isPnUser(a))
36
+ putBounded(this.map, p, a, IDENTITY_MAX);
37
+ else if (isPnUser(p) && isLidUser(a))
38
+ putBounded(this.map, a, p, IDENTITY_MAX);
39
+ }
40
+ /**
41
+ * Map a LID to its learned PN. Returns `jid` unchanged when it is not a LID, or
42
+ * when no PN twin has been learned yet (best-effort: it stabilises once learned).
43
+ */
44
+ canonical(jid) {
45
+ if (!jid || !isLidUser(jid))
46
+ return jid;
47
+ const pn = this.map.get(normalize(jid));
48
+ return pn && isPnUser(pn) ? pn : jid;
49
+ }
50
+ /** True if a PN twin is already known for this LID (skips redundant async lookups). */
51
+ knowsPnFor(lid) {
52
+ if (!lid || !isLidUser(lid))
53
+ return false;
54
+ const pn = this.map.get(normalize(lid));
55
+ return !!pn && isPnUser(pn);
56
+ }
57
+ /** The learned twin of a user JID (the PN of a LID or the LID of a PN), if any. */
58
+ alias(jid) {
59
+ if (!jid)
60
+ return undefined;
61
+ return this.map.get(normalize(jid));
62
+ }
63
+ /**
64
+ * Canonical id for a bare user/chat JID carried by a non-message event
65
+ * (presence, call, group participant). Learns `alt`, the twin the event
66
+ * carries alongside (`callerPn`, `authorPn`, a participant's `phoneNumber`),
67
+ * then applies the same rule as messages: learned LID → PN, device suffix
68
+ * stripped. Group/broadcast JIDs pass through normalised.
69
+ */
70
+ resolve(jid, alt) {
71
+ const primary = jid || alt;
72
+ if (!primary)
73
+ return '';
74
+ this.observe(jid, alt);
75
+ return this.canonical(normalize(primary) || primary);
76
+ }
77
+ }
78
+ /**
79
+ * The single LID/PN rule for a message key, shared by every emitted event
80
+ * (messages, reactions, poll votes) so one person never shows up as a LID on
81
+ * one event type and as a PN on another.
82
+ *
83
+ * Learns the LID↔PN pairs the key exposes, prefers the PN twin, maps a learned
84
+ * LID back to its PN and strips device suffixes. `participant` overrides
85
+ * `key.participant` (Baileys puts broadcast senders on `WAMessage.participant`).
86
+ * For a `fromMe` DM key `senderId` is the chat partner, as for messages; callers
87
+ * that need the author of their own action substitute the bot's id.
88
+ */
89
+ export function canonicalKey(key, identity, participant) {
90
+ const isGroup = (key.remoteJid ?? '').endsWith('@g.us');
91
+ const rawParticipant = participant ?? key.participant ?? null;
92
+ identity.observe(key.remoteJid, key.remoteJidAlt);
93
+ identity.observe(rawParticipant, key.participantAlt);
94
+ const { chat, sender } = normalizeInboundKey({
95
+ remoteJid: key.remoteJid,
96
+ remoteJidAlt: key.remoteJidAlt,
97
+ participant: rawParticipant,
98
+ participantAlt: key.participantAlt,
99
+ fromMe: key.fromMe,
100
+ }, isGroup);
101
+ return {
102
+ chatId: normalize(identity.canonical(chat) ?? chat),
103
+ senderId: normalize(identity.canonical(sender) ?? sender),
104
+ isGroup,
105
+ rawParticipant,
106
+ };
107
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @bot-wa/baileys — WhatsApp transport for @bot-wa/core (Baileys 7, IProvider v2).
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { Bot } from '@bot-wa/core'
7
+ * import { BaileysProvider } from '@bot-wa/baileys'
8
+ *
9
+ * const bot = new Bot({ provider: new BaileysProvider({ session: 'demo', qr: { terminal: true } }) })
10
+ * await bot.start()
11
+ * ```
12
+ */
13
+ export { BaileysProvider } from './BaileysProvider.js';
14
+ export type { BaileysProviderConfig, QrConfig } from './BaileysProvider.js';
15
+ export { toBaileysLogger, isBaileysLogger } from './logger.js';
16
+ export type { BaileysLogger } from './logger.js';
17
+ export type { BrowserConfig, BrowserPreset } from './browser.js';
18
+ export type { PollStore, StoredPoll, PollOption } from './polls.js';
19
+ export { IdentityStore } from './identity.js';
20
+ export { toJid, sanitizeNumber, normalize as normalizeJid, parseJid, buildJid, shortJid, isGroup, isBroadcast, isStatus, isNewsletter, isPn, isLid, sameUser, toUserId, toChatId, isValidJid, } from './jid.js';
21
+ export type { JID, JidInput } from './jid.js';
22
+ export { RateLimiter, RateLimiterTimeout } from './RateLimiter.js';
23
+ export type { RateLimitConfig, RateLimitBucketConfig, RateLimitJitterConfig } from './RateLimiter.js';
24
+ export { toMediaUpload, toBuffer as mediaToBuffer, makeSticker, transcodeToOpus, resolveRemoteMedia, REMOTE_MEDIA_MAX_BYTES } from './MediaProcessor.js';
25
+ export type { StickerOptions, RemoteMediaConfig, WAMediaUpload } from './MediaProcessor.js';
26
+ export { toInbound } from './toInbound.js';
27
+ export { toOutbound } from './toOutbound.js';
28
+ export { classifyDisconnect, backoffDelay, MAX_RECONNECT_ATTEMPTS } from './reconnect.js';
29
+ export type { DisconnectAction } from './reconnect.js';
30
+ export { assertSessionDirectorySafe, removeSessionDirectory, resolveSessionDirectory, } from './sessionPath.js';
package/lib/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @bot-wa/baileys — WhatsApp transport for @bot-wa/core (Baileys 7, IProvider v2).
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { Bot } from '@bot-wa/core'
7
+ * import { BaileysProvider } from '@bot-wa/baileys'
8
+ *
9
+ * const bot = new Bot({ provider: new BaileysProvider({ session: 'demo', qr: { terminal: true } }) })
10
+ * await bot.start()
11
+ * ```
12
+ */
13
+ export { BaileysProvider } from './BaileysProvider.js';
14
+ export { toBaileysLogger, isBaileysLogger } from './logger.js';
15
+ // Identity + JID helpers (WhatsApp-specific; advanced users)
16
+ export { IdentityStore } from './identity.js';
17
+ export { toJid, sanitizeNumber, normalize as normalizeJid, parseJid, buildJid, shortJid, isGroup, isBroadcast, isStatus, isNewsletter, isPn, isLid, sameUser, toUserId, toChatId, isValidJid, } from './jid.js';
18
+ // Anti-ban rate limiter
19
+ export { RateLimiter, RateLimiterTimeout } from './RateLimiter.js';
20
+ // Media processing (sticker/opus/upload)
21
+ export { toMediaUpload, toBuffer as mediaToBuffer, makeSticker, transcodeToOpus, resolveRemoteMedia, REMOTE_MEDIA_MAX_BYTES } from './MediaProcessor.js';
22
+ // Low-level normalizers (advanced)
23
+ export { toInbound } from './toInbound.js';
24
+ export { toOutbound } from './toOutbound.js';
25
+ // reconnect classification (advanced)
26
+ export { classifyDisconnect, backoffDelay, MAX_RECONNECT_ATTEMPTS } from './reconnect.js';
27
+ // Session path validation (advanced/self-hosted tooling)
28
+ export { assertSessionDirectorySafe, removeSessionDirectory, resolveSessionDirectory, } from './sessionPath.js';
package/lib/jid.d.ts ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * JID utilities — PN/LID aware for Baileys 7.x.
3
+ *
4
+ * The user should never have to handle PN/LID duality manually; these helpers
5
+ * wrap Baileys' own jid functions with friendly names.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { toJid, isGroup, isPn } from '@bot-wa/core'
10
+ *
11
+ * const jid = toJid('573001234567') // '573001234567@s.whatsapp.net'
12
+ * const isGroupChat = isGroup(jid) // false
13
+ * const isPrivate = isPn(jid) // true
14
+ * ```
15
+ */
16
+ import { isJidGroup, isJidBroadcast, isJidStatusBroadcast, isJidNewsletter, isPnUser as baileysIsPnUser, isLidUser as baileysIsLidUser, areJidsSameUser } from '@whiskeysockets/baileys';
17
+ /** WhatsApp JID — `number@s.whatsapp.net`, `id@g.us`, `status@broadcast`, `…@lid`. */
18
+ export type JID = string;
19
+ import type { ChatId, UserId } from '@bot-wa/core';
20
+ export type { ChatId, UserId };
21
+ /** Anything that can be turned into a JID: full JID, plain number, or `{ groupId, userId }`. */
22
+ export type JidInput = string | number | {
23
+ groupId: string;
24
+ userId?: string;
25
+ };
26
+ export { isJidGroup as isGroup, isJidBroadcast as isBroadcast, isJidStatusBroadcast as isStatus, isJidNewsletter as isNewsletter, baileysIsPnUser as isPn, baileysIsLidUser as isLid, areJidsSameUser as sameUser, };
27
+ /** Format a raw phone number/string into a valid JID. */
28
+ export declare function toJid(input: JidInput, kind?: 'user' | 'group' | 'broadcast'): JID;
29
+ /** Extract just the digits (no '+', '-', spaces, '@...'). */
30
+ export declare function sanitizeNumber(value: string | number): string;
31
+ /** Strip device suffix & lowercase — canonical identifier. */
32
+ export declare function normalize(jid: JID): JID;
33
+ /** Parse a JID into components. */
34
+ export declare function parseJid(jid: JID): {
35
+ user: string | null;
36
+ server: string | null;
37
+ device: number | undefined;
38
+ domainType: number | undefined;
39
+ };
40
+ /** Re-encode components as JID. Accept plain strings for simplicity. */
41
+ export declare function buildJid(user: string, server: string): JID;
42
+ /** Quick string form for display: hides long LIDs/jids. */
43
+ export declare function shortJid(jid: JID): string;
44
+ /** Coerce any input to a `UserId`. */
45
+ export declare function toUserId(input: JidInput): UserId;
46
+ /** Coerce any input to a `ChatId` (keeps group/broadcast if present). */
47
+ export declare function toChatId(input: JidInput): ChatId;
48
+ /** Validate basic JID shape (cheap, not exhaustive). */
49
+ export declare function isValidJid(value: string): boolean;
50
+ /** True if `jid` is a phone-number-form user JID (`…@s.whatsapp.net`). */
51
+ export declare function isPnUser(jid: string): boolean;
52
+ /** True if `jid` is a LID-form user JID (`…@lid`) — Baileys 7's opaque identity. */
53
+ export declare function isLidUser(jid: string): boolean;
54
+ /**
55
+ * Normalize an inbound message key to PN-preferred `chat`/`sender` identifiers.
56
+ *
57
+ * - DM: `chat` prefers `remoteJidAlt` (PN) when `remoteJid` arrived as a LID.
58
+ * - Group: `chat` is always the group JID (`remoteJid`, never a LID); `sender`
59
+ * prefers `participantAlt` (PN) over the raw `participant` (possibly a LID).
60
+ */
61
+ export declare function normalizeInboundKey(key: {
62
+ remoteJid?: string | null;
63
+ remoteJidAlt?: string | null;
64
+ participant?: string | null;
65
+ participantAlt?: string | null;
66
+ fromMe?: boolean | null;
67
+ }, isGroup: boolean): {
68
+ chat: string;
69
+ sender: string;
70
+ };
package/lib/jid.js ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * JID utilities — PN/LID aware for Baileys 7.x.
3
+ *
4
+ * The user should never have to handle PN/LID duality manually; these helpers
5
+ * wrap Baileys' own jid functions with friendly names.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { toJid, isGroup, isPn } from '@bot-wa/core'
10
+ *
11
+ * const jid = toJid('573001234567') // '573001234567@s.whatsapp.net'
12
+ * const isGroupChat = isGroup(jid) // false
13
+ * const isPrivate = isPn(jid) // true
14
+ * ```
15
+ */
16
+ import { jidNormalizedUser, jidDecode, jidEncode, isJidGroup, isJidBroadcast, isJidStatusBroadcast, isJidNewsletter, isPnUser as baileysIsPnUser, isLidUser as baileysIsLidUser, areJidsSameUser, } from '@whiskeysockets/baileys';
17
+ export { isJidGroup as isGroup, isJidBroadcast as isBroadcast, isJidStatusBroadcast as isStatus, isJidNewsletter as isNewsletter, baileysIsPnUser as isPn, baileysIsLidUser as isLid, areJidsSameUser as sameUser, };
18
+ /** Format a raw phone number/string into a valid JID. */
19
+ export function toJid(input, kind = 'user') {
20
+ if (typeof input === 'object') {
21
+ if (kind === 'group' || input.userId) {
22
+ const num = sanitizeNumber(input.groupId);
23
+ const uid = input.userId ? sanitizeNumber(input.userId) : '';
24
+ return uid ? `${num}@g.us:${uid}` : `${num}@g.us`;
25
+ }
26
+ }
27
+ const raw = String(input);
28
+ if (raw.includes('@'))
29
+ return raw;
30
+ return kind === 'group'
31
+ ? `${sanitizeNumber(raw)}@g.us`
32
+ : kind === 'broadcast'
33
+ ? `${sanitizeNumber(raw)}@broadcast`
34
+ : `${sanitizeNumber(raw)}@s.whatsapp.net`;
35
+ }
36
+ /** Extract just the digits (no '+', '-', spaces, '@...'). */
37
+ export function sanitizeNumber(value) {
38
+ return String(value).replace(/[^\d]/g, '');
39
+ }
40
+ /** Strip device suffix & lowercase — canonical identifier. */
41
+ export function normalize(jid) {
42
+ return jidNormalizedUser(jid);
43
+ }
44
+ /** Parse a JID into components. */
45
+ export function parseJid(jid) {
46
+ const d = (jidDecode(jid) ?? {});
47
+ return {
48
+ user: d.user ?? null,
49
+ server: d.server ?? null,
50
+ device: d.device,
51
+ domainType: d.domainType,
52
+ };
53
+ }
54
+ /** Re-encode components as JID. Accept plain strings for simplicity. */
55
+ export function buildJid(user, server) {
56
+ return jidEncode(user, server);
57
+ }
58
+ /** Quick string form for display: hides long LIDs/jids. */
59
+ export function shortJid(jid) {
60
+ const { user, server } = parseJid(jid);
61
+ if (!user || !server)
62
+ return jid;
63
+ const short = user.length > 8 ? user.slice(-8) : user;
64
+ return `…${short}@${server}`;
65
+ }
66
+ /** Coerce any input to a `UserId`. */
67
+ export function toUserId(input) {
68
+ return toJid(input, 'user');
69
+ }
70
+ /** Coerce any input to a `ChatId` (keeps group/broadcast if present). */
71
+ export function toChatId(input) {
72
+ const raw = String(input);
73
+ if (raw.includes('@'))
74
+ return raw;
75
+ return toJid(raw, 'user');
76
+ }
77
+ /** Validate basic JID shape (cheap, not exhaustive). */
78
+ export function isValidJid(value) {
79
+ try {
80
+ return Boolean(jidDecode(value));
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
86
+ /* ============================================================================
87
+ * LID/PN IDENTITY (Baileys 7)
88
+ * ============================================================================
89
+ *
90
+ * Baileys 7 migrated WhatsApp's user identity to LIDs (`@lid`) — an opaque,
91
+ * per-account identifier that replaces the phone-number JID (`@s.whatsapp.net`,
92
+ * "PN") as the primary identity. Inbound events still carry the PN twin
93
+ * alongside the LID (`remoteJidAlt`/`participantAlt`), and the wrapper always
94
+ * prefers the PN form for anything user-facing (`ctx.from`, `ctx.sender`).
95
+ * ========================================================================== */
96
+ /** True if `jid` is a phone-number-form user JID (`…@s.whatsapp.net`). */
97
+ export function isPnUser(jid) {
98
+ return jid.endsWith('@s.whatsapp.net');
99
+ }
100
+ /** True if `jid` is a LID-form user JID (`…@lid`) — Baileys 7's opaque identity. */
101
+ export function isLidUser(jid) {
102
+ return jid.endsWith('@lid');
103
+ }
104
+ /**
105
+ * Normalize an inbound message key to PN-preferred `chat`/`sender` identifiers.
106
+ *
107
+ * - DM: `chat` prefers `remoteJidAlt` (PN) when `remoteJid` arrived as a LID.
108
+ * - Group: `chat` is always the group JID (`remoteJid`, never a LID); `sender`
109
+ * prefers `participantAlt` (PN) over the raw `participant` (possibly a LID).
110
+ */
111
+ export function normalizeInboundKey(key, isGroup) {
112
+ const remote = key.remoteJid ?? '';
113
+ if (isGroup) {
114
+ const sender = (key.participantAlt && isPnUser(key.participantAlt) ? key.participantAlt : key.participant) ?? '';
115
+ return { chat: remote, sender };
116
+ }
117
+ const chat = key.remoteJidAlt && isPnUser(key.remoteJidAlt) && isLidUser(remote) ? key.remoteJidAlt : remote;
118
+ return { chat, sender: chat };
119
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Logger adapter — `BaileysProviderConfig.logger` takes any core `LoggerLike`
3
+ * (pino, `console`, a custom object), but Baileys' own functions (`makeWASocket`,
4
+ * `makeCacheableSignalKeyStore`, `downloadMediaMessage`) need its `ILogger`
5
+ * shape: a string `level`, `child()` and `trace()`. {@link toBaileysLogger} passes a
6
+ * pino-shaped logger through untouched and wraps anything else.
7
+ */
8
+ import type { LoggerLike } from '@bot-wa/core';
9
+ /**
10
+ * Structural copy of Baileys' `ILogger` (its main entry does not re-export it).
11
+ * pino's `Logger` satisfies it.
12
+ */
13
+ export interface BaileysLogger {
14
+ level: string;
15
+ child(obj: Record<string, unknown>): BaileysLogger;
16
+ trace(obj: unknown, msg?: string): void;
17
+ debug(obj: unknown, msg?: string): void;
18
+ info(obj: unknown, msg?: string): void;
19
+ warn(obj: unknown, msg?: string): void;
20
+ error(obj: unknown, msg?: string): void;
21
+ }
22
+ /** Already shaped like Baileys' `ILogger` (pino and friends): a string `level`, `child()` and `trace()`. */
23
+ export declare function isBaileysLogger(logger: LoggerLike): logger is LoggerLike & BaileysLogger;
24
+ /**
25
+ * The logger handed to Baileys. A logger that already has Baileys' shape (pino) is returned
26
+ * as is, byte-for-byte the previous behaviour. Anything else is wrapped:
27
+ * - `trace` forwards to the logger's own `trace` when it has one, else it is a no-op
28
+ * (Baileys' trace output is far too chatty to map onto `debug`);
29
+ * - `level` is the logger's string `level` when it has one, else `fallbackLevel`
30
+ * (Baileys only compares it with `'trace'`);
31
+ * - `child(bindings)` wraps `logger.child(bindings)` when available, else the same logger
32
+ * (the bindings are dropped).
33
+ */
34
+ export declare function toBaileysLogger(logger: LoggerLike, fallbackLevel?: string): BaileysLogger;
package/lib/logger.js ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Logger adapter — `BaileysProviderConfig.logger` takes any core `LoggerLike`
3
+ * (pino, `console`, a custom object), but Baileys' own functions (`makeWASocket`,
4
+ * `makeCacheableSignalKeyStore`, `downloadMediaMessage`) need its `ILogger`
5
+ * shape: a string `level`, `child()` and `trace()`. {@link toBaileysLogger} passes a
6
+ * pino-shaped logger through untouched and wraps anything else.
7
+ */
8
+ /** Already shaped like Baileys' `ILogger` (pino and friends): a string `level`, `child()` and `trace()`. */
9
+ export function isBaileysLogger(logger) {
10
+ const l = logger;
11
+ return typeof l.level === 'string' && typeof l.child === 'function' && typeof l.trace === 'function';
12
+ }
13
+ /**
14
+ * The logger handed to Baileys. A logger that already has Baileys' shape (pino) is returned
15
+ * as is, byte-for-byte the previous behaviour. Anything else is wrapped:
16
+ * - `trace` forwards to the logger's own `trace` when it has one, else it is a no-op
17
+ * (Baileys' trace output is far too chatty to map onto `debug`);
18
+ * - `level` is the logger's string `level` when it has one, else `fallbackLevel`
19
+ * (Baileys only compares it with `'trace'`);
20
+ * - `child(bindings)` wraps `logger.child(bindings)` when available, else the same logger
21
+ * (the bindings are dropped).
22
+ */
23
+ export function toBaileysLogger(logger, fallbackLevel = 'info') {
24
+ if (isBaileysLogger(logger))
25
+ return logger;
26
+ const extras = logger;
27
+ const level = typeof extras.level === 'string' ? extras.level : fallbackLevel;
28
+ const trace = typeof extras.trace === 'function'
29
+ ? (...a) => { extras.trace.apply(logger, a); }
30
+ : () => { };
31
+ return {
32
+ level,
33
+ child(bindings) {
34
+ const child = typeof logger.child === 'function' ? logger.child(bindings) : logger;
35
+ return toBaileysLogger(child, level);
36
+ },
37
+ trace,
38
+ // Forward only the arguments Baileys passed (a trailing `undefined` would print on console).
39
+ debug: (...a) => logger.debug(...a),
40
+ info: (...a) => logger.info(...a),
41
+ warn: (...a) => logger.warn(...a),
42
+ error: (...a) => logger.error(...a),
43
+ };
44
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Durable media references for the Baileys transport (`IProvider.serializeMediaRef` /
3
+ * `rehydrateMediaRef`).
4
+ *
5
+ * A Baileys `MediaRef.token` is the live `WAMessage`. For the durable inbox it is reduced to
6
+ * what a download needs: the media content (CDN url, direct path, media key and hashes,
7
+ * WITHOUT thumbnails, captions or quoted context) as protobuf bytes, plus the raw message key,
8
+ * which only the re-upload request (`sock.updateMediaMessage`) uses when the CDN copy expired.
9
+ * The key is never used for identity, keying or routing (LID/PN rules are untouched).
10
+ *
11
+ * The stored value is UNTRUSTED when read back: every field is validated and a malformed,
12
+ * oversized, unknown-version or mismatching value is rejected with a `ProviderError`.
13
+ */
14
+ import { type WAMessage, type WAMessageKey } from '@whiskeysockets/baileys';
15
+ import { type MediaRef, type SerializedMediaRef } from '@bot-wa/core';
16
+ /** Format version written by {@link serializeBaileysMediaRef}. */
17
+ export declare const BAILEYS_MEDIA_REF_VERSION = 1;
18
+ /** The journaled data of format v1. */
19
+ export interface BaileysMediaRefV1 {
20
+ /** The raw WhatsApp message key (re-upload requests only). */
21
+ key: {
22
+ remoteJid: string;
23
+ id: string;
24
+ fromMe?: boolean;
25
+ participant?: string;
26
+ };
27
+ /** Base64 `proto.Message` holding exactly one media content. */
28
+ m: string;
29
+ /** `messageTimestamp` (seconds). */
30
+ t?: number;
31
+ }
32
+ /** Options of {@link serializeBaileysMediaRef}. */
33
+ export interface SerializeMediaOptions {
34
+ /** Journal view-once media too (its key then lives at rest). Default `false`. */
35
+ viewOnce?: boolean;
36
+ }
37
+ /**
38
+ * The durable reference of an inbound media message, or `undefined` when it must not (or
39
+ * cannot) be journaled: view-once media (unless `options.viewOnce`), no media key or path,
40
+ * an unexpected shape. Never throws.
41
+ */
42
+ export declare function serializeBaileysMediaRef(ref: MediaRef, options?: SerializeMediaOptions): SerializedMediaRef | undefined;
43
+ /**
44
+ * Decode and validate a journaled reference into the message key and a `WAMessage` holding
45
+ * only the media content. @throws {ProviderError} on anything unexpected.
46
+ */
47
+ export declare function parseBaileysMediaRef(stored: SerializedMediaRef, kind: MediaRef['kind']): {
48
+ key: WAMessageKey;
49
+ message: WAMessage;
50
+ };