zapo-js 1.6.0 → 1.6.2

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.
@@ -8,8 +8,13 @@ const KEEPALIVE_DEFAULT_MIN_JITTER_MS = 250;
8
8
  const KEEPALIVE_MAX_JITTER_RATIO = 0.5;
9
9
  /**
10
10
  * Periodically pings the server with a ping IQ to detect dead sockets and
11
- * measure clock skew. Skips when the orchestrator has other traffic in
12
- * flight; recovers a queued/dropped ping via the configured `getComms()`.
11
+ * measure clock skew. A ping is skipped while another ping is in flight, or
12
+ * while other queries are pending and the socket shows recent inbound
13
+ * activity. A socket silent past the dead-socket timeout is pinged even with
14
+ * queries pending: pending queries on a silent socket are evidence of a dead
15
+ * connection, so steady outbound traffic must not starve detection. On ping
16
+ * failure it rejects pending queries and resumes the socket via the
17
+ * configured `getComms()`.
13
18
  */
14
19
  class WaKeepAlive {
15
20
  constructor(options) {
@@ -71,14 +76,25 @@ class WaKeepAlive {
71
76
  this.schedule(generation);
72
77
  return;
73
78
  }
74
- if (this.inFlight || this.nodeOrchestrator.hasPending()) {
75
- this.logger.trace('keepalive skipped: in-flight or pending queries', {
76
- inFlight: this.inFlight,
77
- pendingQueries: this.nodeOrchestrator.hasPending()
78
- });
79
+ if (this.inFlight) {
80
+ this.logger.trace('keepalive skipped: ping already in flight');
79
81
  this.schedule(generation);
80
82
  return;
81
83
  }
84
+ if (this.nodeOrchestrator.hasPending()) {
85
+ const inboundIdleMs = Date.now() - comms.getLastInboundAtMs();
86
+ if (inboundIdleMs < this.timeoutMs) {
87
+ this.logger.trace('keepalive skipped: pending queries with recent inbound', {
88
+ inboundIdleMs
89
+ });
90
+ this.schedule(generation);
91
+ return;
92
+ }
93
+ this.logger.debug('keepalive pinging despite pending queries: inbound is silent', {
94
+ inboundIdleMs,
95
+ timeoutMs: this.timeoutMs
96
+ });
97
+ }
82
98
  this.inFlight = true;
83
99
  const startedAt = Date.now();
84
100
  try {
@@ -111,6 +127,7 @@ class WaKeepAlive {
111
127
  this.logger.warn('keepalive ping failed, reconnecting socket', {
112
128
  message: (0, primitives_1.toError)(error).message
113
129
  });
130
+ this.nodeOrchestrator.clearPending(new Error('socket resume requested by keepalive ping failure'));
114
131
  try {
115
132
  await comms.closeSocketAndResume();
116
133
  }
@@ -4,4 +4,29 @@ export declare function buildGetPrivacySettingsIq(): BinaryNode;
4
4
  export declare function buildSetPrivacyCategoryIq(category: WaPrivacyCategory, value: WaPrivacyValue): BinaryNode;
5
5
  export declare function buildGetPrivacyDisallowedListIq(category: WaPrivacyCategory): BinaryNode;
6
6
  export declare function buildGetBlocklistIq(): BinaryNode;
7
- export declare function buildBlocklistChangeIq(jid: string, action: 'block' | 'unblock'): BinaryNode;
7
+ /**
8
+ * Blocklist target in both addressing forms. At least one side is always
9
+ * present: LID-migrated accounts carry `lidJid` (plus `pnJid` when known),
10
+ * non-migrated accounts carry only `pnJid`.
11
+ */
12
+ export type WaBlocklistTarget = {
13
+ readonly lidJid: string;
14
+ readonly pnJid: string | null;
15
+ } | {
16
+ readonly lidJid: null;
17
+ readonly pnJid: string;
18
+ };
19
+ /**
20
+ * Builds the blocklist `set` IQ for a block action. LID-migrated targets are
21
+ * addressed by the LID jid plus an identifier attribute: `pn_jid` when the
22
+ * phone jid is known, else `unknown_identifier="true"`. Non-migrated targets
23
+ * are addressed by the phone jid alone. The server rejects a block that
24
+ * addresses a migrated account by phone jid or omits the identifier
25
+ * (`400: bad-request`).
26
+ */
27
+ export declare function buildBlocklistBlockIq(target: WaBlocklistTarget): BinaryNode;
28
+ /**
29
+ * Builds the blocklist `set` IQ for an unblock action. The server keys
30
+ * migrated entries by LID, so `jid` must be the LID jid when one exists.
31
+ */
32
+ export declare function buildBlocklistUnblockIq(jid: string): BinaryNode;
@@ -4,7 +4,8 @@ exports.buildGetPrivacySettingsIq = buildGetPrivacySettingsIq;
4
4
  exports.buildSetPrivacyCategoryIq = buildSetPrivacyCategoryIq;
5
5
  exports.buildGetPrivacyDisallowedListIq = buildGetPrivacyDisallowedListIq;
6
6
  exports.buildGetBlocklistIq = buildGetBlocklistIq;
7
- exports.buildBlocklistChangeIq = buildBlocklistChangeIq;
7
+ exports.buildBlocklistBlockIq = buildBlocklistBlockIq;
8
+ exports.buildBlocklistUnblockIq = buildBlocklistUnblockIq;
8
9
  const defaults_1 = require("../../../protocol/defaults");
9
10
  const nodes_1 = require("../../../protocol/nodes");
10
11
  const privacy_1 = require("../../../protocol/privacy");
@@ -45,11 +46,41 @@ function buildGetPrivacyDisallowedListIq(category) {
45
46
  function buildGetBlocklistIq() {
46
47
  return (0, query_1.buildIqNode)(nodes_1.WA_IQ_TYPES.GET, defaults_1.WA_DEFAULTS.HOST_DOMAIN, nodes_1.WA_XMLNS.BLOCKLIST);
47
48
  }
48
- function buildBlocklistChangeIq(jid, action) {
49
+ /**
50
+ * Builds the blocklist `set` IQ for a block action. LID-migrated targets are
51
+ * addressed by the LID jid plus an identifier attribute: `pn_jid` when the
52
+ * phone jid is known, else `unknown_identifier="true"`. Non-migrated targets
53
+ * are addressed by the phone jid alone. The server rejects a block that
54
+ * addresses a migrated account by phone jid or omits the identifier
55
+ * (`400: bad-request`).
56
+ */
57
+ function buildBlocklistBlockIq(target) {
58
+ let attrs;
59
+ if (target.lidJid !== null) {
60
+ attrs =
61
+ target.pnJid !== null
62
+ ? { action: 'block', jid: target.lidJid, pn_jid: target.pnJid }
63
+ : { action: 'block', jid: target.lidJid, unknown_identifier: 'true' };
64
+ }
65
+ else {
66
+ attrs = { action: 'block', jid: target.pnJid };
67
+ }
49
68
  return (0, query_1.buildIqNode)(nodes_1.WA_IQ_TYPES.SET, defaults_1.WA_DEFAULTS.HOST_DOMAIN, nodes_1.WA_XMLNS.BLOCKLIST, [
50
69
  {
51
70
  tag: 'item',
52
- attrs: { jid, action }
71
+ attrs
72
+ }
73
+ ]);
74
+ }
75
+ /**
76
+ * Builds the blocklist `set` IQ for an unblock action. The server keys
77
+ * migrated entries by LID, so `jid` must be the LID jid when one exists.
78
+ */
79
+ function buildBlocklistUnblockIq(jid) {
80
+ return (0, query_1.buildIqNode)(nodes_1.WA_IQ_TYPES.SET, defaults_1.WA_DEFAULTS.HOST_DOMAIN, nodes_1.WA_XMLNS.BLOCKLIST, [
81
+ {
82
+ tag: 'item',
83
+ attrs: { jid, action: 'unblock' }
53
84
  }
54
85
  ]);
55
86
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zapo-js",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "description": "High-performance WhatsApp Web TypeScript library",
5
5
  "license": "MIT",
6
6
  "author": "vinikjkkj <contact@vinicius.email> (https://github.com/vinikjkkj)",