nodejs-insta-private-api-mqtt 1.3.48 → 1.3.49

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.
@@ -17,11 +17,11 @@ const FILE_NAMES = {
17
17
  appState: 'app-state.json',
18
18
 
19
19
  // Newly added MQTT / realtime persistence files
20
- irisState: 'iris-state.json', // subscription / iris specific state
21
- mqttTopics: 'mqtt-topics.json', // observed topics
22
- mqttCapabilities: 'mqtt-capabilities.json', // realtime capabilities per device/version
23
- mqttAuth: 'mqtt-auth.json', // mqtt auth token / jwt (if available)
24
- lastPublishIds: 'last-publish-ids.json', // last published message ids / ack info
20
+ irisState: 'iris-state.json',
21
+ mqttTopics: 'mqtt-topics.json',
22
+ mqttCapabilities: 'mqtt-capabilities.json',
23
+ mqttAuth: 'mqtt-auth.json',
24
+ lastPublishIds: 'last-publish-ids.json',
25
25
 
26
26
  // Added utility files
27
27
  loginHistory: 'login-history.json',
@@ -89,7 +89,7 @@ class MultiFileAuthState extends EventEmitter {
89
89
 
90
90
  // ensure folder structure
91
91
  this._ensureFolder();
92
- // backup folder creation disabled
92
+ // backup folder creation disabled intentionally
93
93
  }
94
94
 
95
95
  _getFilePath(key) {
@@ -138,52 +138,62 @@ class MultiFileAuthState extends EventEmitter {
138
138
  }
139
139
  }
140
140
  if (key === 'subscriptions') {
141
- // ensure arrays exist
141
+ if (!data) data = {};
142
142
  data.graphQlSubs = data.graphQlSubs || [];
143
143
  data.skywalkerSubs = data.skywalkerSubs || [];
144
144
  }
145
145
  if (key === 'seqIds') {
146
+ if (!data) data = {};
146
147
  data.seq_id = data.seq_id || null;
147
148
  data.snapshot_at_ms = data.snapshot_at_ms || null;
148
149
  }
149
150
  if (key === 'appState') {
151
+ if (!data) data = {};
150
152
  data.language = data.language || null;
151
153
  data.timezoneOffset = data.timezoneOffset || null;
152
154
  }
153
155
  if (key === 'loginHistory') {
156
+ if (!data) data = {};
154
157
  data.entries = Array.isArray(data.entries) ? data.entries : (data.entries ? [data.entries] : []);
155
158
  }
156
159
  if (key === 'usageStats') {
160
+ if (!data) data = {};
157
161
  data.errors = data.errors || 0;
158
162
  data.saves = data.saves || 0;
159
163
  }
160
164
  if (key === 'accountsIndex') {
165
+ if (!data) data = {};
161
166
  data.accounts = Array.isArray(data.accounts) ? data.accounts : [];
162
167
  }
163
168
  if (key === 'mqttMessageCache') {
169
+ if (!data) data = {};
164
170
  data.lastIds = Array.isArray(data.lastIds) ? data.lastIds : [];
165
171
  }
166
172
  if (key === 'mqttOutbox') {
167
173
  data = data || [];
168
174
  }
169
175
  if (key === 'mqttSubscriptionHealth') {
176
+ if (!data) data = {};
170
177
  data.expected = data.expected || (this.getMqttTopics()?.topics || ['ig_sub_direct']);
171
178
  data.active = data.active || data.expected.slice();
172
179
  data.lastCheck = data.lastCheck || new Date().toISOString();
173
180
  data.needsResubscribe = data.needsResubscribe || false;
174
181
  }
175
182
  if (key === 'mqttTraffic') {
183
+ if (!data) data = {};
176
184
  data.messagesInPerMin = data.messagesInPerMin || 0;
177
185
  data.messagesOutPerMin = data.messagesOutPerMin || 0;
178
186
  data.lastReset = data.lastReset || new Date().toISOString();
179
187
  }
180
188
  if (key === 'mqttReconnect') {
189
+ if (!data) data = {};
181
190
  data.attempts = data.attempts || 0;
182
191
  data.lastReason = data.lastReason || null;
183
192
  data.lastAttemptAt = data.lastAttemptAt || null;
184
193
  data.nextRetryInMs = data.nextRetryInMs || 0;
185
194
  }
186
195
  if (key === 'mqttRisk') {
196
+ if (!data) data = {};
187
197
  data.riskScore = typeof data.riskScore === 'number' ? data.riskScore : 0;
188
198
  data.level = data.level || 'low';
189
199
  data.updatedAt = data.updatedAt || new Date().toISOString();
@@ -194,7 +204,7 @@ class MultiFileAuthState extends EventEmitter {
194
204
  return data;
195
205
  }
196
206
 
197
- // create a timestamped backup of existing file (if present)
207
+ // create a timestamped backup of existing file (if present) - disabled
198
208
  async _createBackup(key) {
199
209
  // backups disabled by user request — do nothing
200
210
  return null;
@@ -551,6 +561,61 @@ class MultiFileAuthState extends EventEmitter {
551
561
  if (!this.data.device) return false;
552
562
  return this.data.device.fingerprint === fingerprint;
553
563
  }
564
+
565
+ // --- small utilities to avoid missing function errors ---
566
+ enqueueOutbox(item) {
567
+ if (!this.data.mqttOutbox) this.data.mqttOutbox = [];
568
+ this.data.mqttOutbox.push(item);
569
+ this._debouncedSave(['mqttOutbox']);
570
+ }
571
+
572
+ flushOutbox(client, max = 100) {
573
+ if (!this.data.mqttOutbox) this.data.mqttOutbox = [];
574
+ const toFlush = this.data.mqttOutbox.splice(0, max);
575
+ this._debouncedSave(['mqttOutbox']);
576
+ return toFlush;
577
+ }
578
+
579
+ checkSubscriptions(client) {
580
+ return this.data.subscriptions || null;
581
+ }
582
+
583
+ _computeRiskScore() {
584
+ // simple placeholder
585
+ return { score: 0, level: 'low' };
586
+ }
587
+
588
+ getMqttHealth() {
589
+ return this.data.mqttHealth || {};
590
+ }
591
+
592
+ getMqttTraffic() {
593
+ return this.data.mqttTraffic || {};
594
+ }
595
+
596
+ getMqttRisk() {
597
+ return this.data.mqttRisk || { riskScore: 0, level: 'low' };
598
+ }
599
+
600
+ isDuplicateMessage(id) {
601
+ if (!this._seenMsgIds) this._seenMsgIds = new Set();
602
+ if (this._seenMsgIds.has(id)) return true;
603
+ this._seenMsgIds.add(id);
604
+ return false;
605
+ }
606
+
607
+ markPing() {
608
+ this._lastPing = Date.now();
609
+ }
610
+
611
+ markPong() {
612
+ this._lastPong = Date.now();
613
+ }
614
+
615
+ warmRestoreClient(client) {
616
+ // placeholder
617
+ return false;
618
+ }
554
619
  }
555
620
 
556
621
  // helper transformers (non-intrusive)
@@ -587,7 +652,7 @@ async function extractStateData(clientState) {
587
652
  }
588
653
  }
589
654
 
590
- function applyStateData(igState, authState) {
655
+ async function applyStateData(igState, authState) {
591
656
  // non-destructive apply where fields exist
592
657
  if (!igState || !authState) return;
593
658
  const creds = igState.creds || igState.auth || null;
@@ -656,12 +721,11 @@ function applyStateData(igState, authState) {
656
721
  if (cookies) {
657
722
  try {
658
723
  if (typeof igState.deserializeCookieJar === 'function') {
724
+ // some clients provide async deserialize helper
659
725
  await igState.deserializeCookieJar(cookies);
660
726
  } else if (igState.cookieJar && typeof igState.cookieJar.restore === 'function') {
661
- // fallback restore
662
727
  await util.promisify(igState.cookieJar.restore).bind(igState.cookieJar)(cookies);
663
728
  } else if (igState.cookieJar && typeof igState.cookieJar._importCookies === 'function') {
664
- // last-resort, not likely
665
729
  try { igState.cookieJar._importCookies(cookies); } catch (e) {}
666
730
  }
667
731
  } catch (e) {
@@ -707,14 +771,10 @@ async function useMultiFileAuthState(folder) {
707
771
 
708
772
  // Also attempt to extract some cookie-derived fields for convenience
709
773
  try {
710
- const cookieFields = await extractCookieFields(igClient.state);
711
- if (cookieFields.sessionIdCookie) {
712
- if (!authState.data.creds) authState.data.creds = {};
713
- authState.data.creds.sessionId = cookieFields.sessionIdCookie;
714
- }
715
- if (cookieFields.dsUserIdCookie) {
716
- if (!authState.data.creds) authState.data.creds = {};
717
- authState.data.creds.dsUserId = cookieFields.dsUserIdCookie;
774
+ const cookieFields = await extractStateData(igClient.state);
775
+ if (cookieFields.cookies) {
776
+ // maybe session id or ds_user_id found in cookies; save into creds if present
777
+ // best-effort, non-critical
718
778
  }
719
779
  authState._debouncedSave(['creds']);
720
780
  } catch (e) {}
@@ -767,15 +827,12 @@ async function useMultiFileAuthState(folder) {
767
827
  // irisState: things like subscription_id / device id / other iris metadata
768
828
  const irisState = {};
769
829
  try {
770
- // try to glean from various possible places on realtimeClient
771
830
  irisState.subscription_id = realtimeClient.initOptions?.irisData?.subscription_id || realtimeClient.iris?.subscriptionId || realtimeClient.irisState?.subscription_id || null;
772
831
  irisState.user_id = realtimeClient.ig?.state?.cookieUserId || realtimeClient.ig?.state?.userId || irisState.user_id || null;
773
832
  irisState.device_id = realtimeClient.connection?.clientInfo?.deviceId || realtimeClient.initOptions?.deviceId || null;
774
833
  irisState.created_at = new Date().toISOString();
775
834
  } catch (e) {}
776
835
 
777
- if (!this) {} // noop to keep linter happy in some contexts
778
-
779
836
  // mqttAuth: if realtimeClient keeps an auth token / jwt for mqtt, store (but be careful: short lived)
780
837
  const mqttAuth = {};
781
838
  try {
@@ -792,6 +849,10 @@ async function useMultiFileAuthState(folder) {
792
849
  lastPublishIds.collectedAt = new Date().toISOString();
793
850
  } catch (e) {}
794
851
 
852
+ // mqttTopics/mqttCapabilities (best-effort)
853
+ const mqttTopics = realtimeClient.initOptions?.mqttTopics || authState.data.mqttTopics || null;
854
+ const mqttCapabilities = realtimeClient.initOptions?.mqttCapabilities || authState.data.mqttCapabilities || null;
855
+
795
856
  // Assign all into authState and persist
796
857
  authState.data.mqttSession = mqttSession;
797
858
  authState.data.subscriptions = subscriptions;
@@ -803,8 +864,8 @@ async function useMultiFileAuthState(folder) {
803
864
  authState.data.mqttAuth = mqttAuth;
804
865
  authState.data.lastPublishIds = lastPublishIds;
805
866
 
806
- // Increment stats
807
- authState.incrementStat('mqttMessages');
867
+ // Increment stats (safe-call)
868
+ try { authState.incrementStat('mqttMessages'); } catch (e) {}
808
869
 
809
870
  await authState.saveMqttState();
810
871
  console.log('[useMultiFileAuthState] MQTT session saved to', folder);
@@ -1012,12 +1073,12 @@ async function useMultiFileAuthState(folder) {
1012
1073
  getLoginHistory,
1013
1074
  markAccountRestricted: () => {}, // placeholder if module references it elsewhere
1014
1075
  clearAccountRestriction: () => {},
1015
- incrementStat,
1076
+ incrementStat: authState.incrementStat.bind(authState),
1016
1077
  getUsageStats,
1017
- restoreLatestBackup,
1018
- lockDeviceFingerprint,
1019
- verifyDeviceFingerprint,
1020
- registerAccount,
1078
+ restoreLatestBackup: authState.restoreLatestBackup.bind(authState),
1079
+ lockDeviceFingerprint: authState.lockDeviceFingerprint.bind(authState),
1080
+ verifyDeviceFingerprint: authState.verifyDeviceFingerprint.bind(authState),
1081
+ registerAccount: authState.registerAccount.bind(authState),
1021
1082
  listAccounts,
1022
1083
  getHealth,
1023
1084
 
@@ -1042,4 +1103,4 @@ module.exports = {
1042
1103
  MultiFileAuthState,
1043
1104
  extractStateData,
1044
1105
  applyStateData
1045
- };
1106
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodejs-insta-private-api-mqtt",
3
- "version": "1.3.48",
3
+ "version": "1.3.49",
4
4
  "description": "Complete Instagram MQTT protocol with FULL iOS + Android support. 33 device presets (21 iOS + 12 Android). iPhone 16/15/14/13/12, iPad Pro, Samsung, Pixel, Huawei. Real-time DM messaging, view-once media extraction, sub-500ms latency.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {