nodejs-insta-private-api-mqt 1.4.5 → 1.4.6

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.
@@ -295,14 +295,18 @@ class AccountRepository extends Repository {
295
295
  }
296
296
 
297
297
  /**
298
- * Resolves a valid User-Agent from state / realistic fallback.
299
- * IMPORTANT: IG version, build number and bloksVersionId must be
300
- * in sync. Update all three when Instagram updates.
298
+ * Resolves a valid User-Agent from state / dynamically generated fallback.
299
+ * Priority:
300
+ * 1. state.userAgent / state.appUserAgent / request.userAgent / state.deviceString
301
+ * 2. Built dynamically from state device parameters (androidRelease, manufacturer, model, etc.)
302
+ * 3. Last-resort realistic static fallback
303
+ * This way the user-agent always reflects the emulated device set in state.
301
304
  */
302
305
  _resolveUserAgent() {
303
306
  const state = this.client.state || {};
304
307
  const req = this.client.request || {};
305
308
 
309
+ // 1) Explicit user-agent already set in state
306
310
  const candidates = [
307
311
  state.userAgent,
308
312
  state.appUserAgent,
@@ -310,17 +314,35 @@ class AccountRepository extends Repository {
310
314
  state.deviceString,
311
315
  ].filter(Boolean);
312
316
 
313
- let userAgent = candidates.length > 0 ? candidates[0] : null;
314
-
315
- if (!userAgent) {
316
- // FIX: real existing version — 415.0.0.36.76 (build 580610226)
317
- // Keep in sync with bloksVersionId below.
318
- userAgent =
319
- 'Instagram 415.0.0.36.76 Android (35/15; 480dpi; 1280x2856; Google; Pixel 9 Pro; caiman; google; en_US; 580610226)';
317
+ if (candidates.length > 0) {
318
+ this.client.state.userAgent = candidates[0];
319
+ return candidates[0];
320
320
  }
321
321
 
322
- this.client.state.userAgent = userAgent;
323
- return userAgent;
322
+ // 2) Build dynamically from device parameters stored in state
323
+ try {
324
+ const igVersion = state.appVersion || state.igVersion || '415.0.0.36.76';
325
+ const buildNumber = state.appVersionCode || state.buildNumber || '580610226';
326
+ const androidApi = state.androidVersion || state.androidApiLevel || '35';
327
+ const androidRel = state.androidRelease || state.androidOsVersion || '15';
328
+ const dpi = state.dpi || state.screenDpi || '480dpi';
329
+ const resolution = state.resolution || state.screenResolution || '1080x2400';
330
+ const manufacturer = state.manufacturer || state.deviceManufacturer || 'Google';
331
+ const brand = state.brand || state.deviceBrand || manufacturer;
332
+ const model = state.model || state.deviceModel || 'Pixel 7';
333
+ const device = state.device || state.deviceName || 'panther';
334
+ const cpu = state.cpu || state.deviceCpu || 'gs201';
335
+ const lang = (state.language || 'en_US').replace('-', '_');
336
+
337
+ const ua = `Instagram ${igVersion} Android (${androidApi}/${androidRel}; ${dpi}; ${resolution}; ${brand}/${manufacturer}; ${model}; ${device}; ${cpu}; ${lang}; ${buildNumber})`;
338
+ this.client.state.userAgent = ua;
339
+ return ua;
340
+ } catch (e) {}
341
+
342
+ // 3) Last-resort static fallback
343
+ const fallback = 'Instagram 415.0.0.36.76 Android (35/15; 480dpi; 1280x2856; Google; Pixel 9 Pro; caiman; google; en_US; 580610226)';
344
+ this.client.state.userAgent = fallback;
345
+ return fallback;
324
346
  }
325
347
 
326
348
  async ensureCsrfToken() {
@@ -885,7 +907,7 @@ class AccountRepository extends Repository {
885
907
  try { await this._phoneNumberPrefill(); } catch (e) {}
886
908
  try { await this._prefetchOauthTokenForLogin(username); } catch (e) {}
887
909
 
888
- return this.requestWithRetry(async () => {
910
+ const loginResult = await this.requestWithRetry(async () => {
889
911
  const nowSec = Math.floor(Date.now() / 1000);
890
912
  const aacInitTimestamp = nowSec - Math.floor(Math.random() * 50);
891
913
  const aacjid = crypto.randomUUID ? crypto.randomUUID() : require('uuid').v4();
@@ -1261,6 +1283,126 @@ class AccountRepository extends Repository {
1261
1283
 
1262
1284
  return body;
1263
1285
  });
1286
+
1287
+ // Post-login: set E2EE eligibility (as real app does after login)
1288
+ try { await this._setE2eeEligibility(); } catch (e) {}
1289
+
1290
+ return loginResult;
1291
+ }
1292
+
1293
+ async _setE2eeEligibility(eligibility = 4) {
1294
+ const state = this.client.state || {};
1295
+ const lang = state.language || 'ro_RO';
1296
+ const acceptLanguage = `${lang.replace('_', '-')}, en-US`;
1297
+ const userAgent = this._resolveUserAgent();
1298
+ const bloksVersionId =
1299
+ state.bloksVersionId ||
1300
+ '5e47baf35c5a270b44c8906c8b99063564b30ef69779f3dee0b828bee2e4ef5b';
1301
+ const networkProps = buildNetworkProperties();
1302
+ const nowSec = Math.floor(Date.now() / 1000);
1303
+
1304
+ const androidDeviceId =
1305
+ state.androidDeviceId ||
1306
+ state.deviceId ||
1307
+ `android-${crypto.randomBytes(8).toString('hex')}`;
1308
+ const familyDeviceId =
1309
+ state.phoneId ||
1310
+ state.familyDeviceId ||
1311
+ (crypto.randomUUID ? crypto.randomUUID() : require('uuid').v4());
1312
+ const qeDeviceId =
1313
+ state.deviceId ||
1314
+ state.qeDeviceId ||
1315
+ (crypto.randomUUID ? crypto.randomUUID() : require('uuid').v4());
1316
+ const machineId =
1317
+ state.mid ||
1318
+ state.machineId ||
1319
+ `aZ${crypto.randomBytes(8).toString('hex')}`;
1320
+
1321
+ const headers = {
1322
+ 'accept-language': acceptLanguage,
1323
+ 'authorization': state.authorization || '',
1324
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
1325
+ 'ig-intended-user-id': String(state.cookieUserId || '0'),
1326
+ 'ig-u-ds-user-id': String(state.cookieUserId || '0'),
1327
+ 'priority': 'u=3',
1328
+ 'x-bloks-is-layout-rtl': 'false',
1329
+ 'x-bloks-prism-ax-base-colors-enabled': 'false',
1330
+ 'x-bloks-prism-button-version': 'CONTROL',
1331
+ 'x-bloks-prism-colors-enabled': 'true',
1332
+ 'x-bloks-prism-font-enabled': 'false',
1333
+ 'x-bloks-prism-indigo-link-version': '0',
1334
+ 'x-bloks-version-id': bloksVersionId,
1335
+ 'x-fb-client-ip': 'True',
1336
+ 'x-fb-connection-type': 'MOBILE.UNKNOWN',
1337
+ 'x-fb-friendly-name': 'IgApi: direct_v2/set_e2ee_eligibility/',
1338
+ 'x-fb-network-properties': networkProps,
1339
+ 'x-fb-request-analytics-tags': JSON.stringify({
1340
+ network_tags: {
1341
+ product: String(state.fbAnalyticsApplicationId || '567067343352427'),
1342
+ purpose: 'fetch',
1343
+ surface: 'undefined',
1344
+ request_category: 'api',
1345
+ retry_attempt: '0',
1346
+ },
1347
+ }),
1348
+ 'x-fb-server-cluster': 'True',
1349
+ 'x-ig-android-id': androidDeviceId,
1350
+ 'x-ig-app-id': String(state.fbAnalyticsApplicationId || '567067343352427'),
1351
+ 'x-ig-app-locale': lang,
1352
+ 'x-ig-bandwidth-speed-kbps': (Math.random() * 1500 + 800).toFixed(3),
1353
+ 'x-ig-bandwidth-totalbytes-b': '0',
1354
+ 'x-ig-bandwidth-totaltime-ms': '0',
1355
+ 'x-ig-capabilities': '3brTv10=',
1356
+ 'x-ig-client-endpoint': 'empty',
1357
+ 'x-ig-connection-type': 'MOBILE(UNKNOWN)',
1358
+ 'x-ig-device-id': qeDeviceId,
1359
+ 'x-ig-device-languages': `{"system_languages":"${lang}"}`,
1360
+ 'x-ig-device-locale': lang,
1361
+ 'x-ig-family-device-id': familyDeviceId,
1362
+ 'x-ig-mapped-locale': lang,
1363
+ 'x-ig-nav-chain': 'LockoutFragment:dogfooding_lockout:1:cold_start',
1364
+ 'x-ig-salt-ids': state.igSaltIds || '220140399,332020310,974466465,974460658',
1365
+ 'x-ig-timezone-offset': String(
1366
+ typeof state.timezoneOffset === 'number' ? state.timezoneOffset : 7200
1367
+ ),
1368
+ 'x-ig-www-claim': state.igWWWClaim || '0',
1369
+ 'x-mid': machineId,
1370
+ 'x-pigeon-rawclienttime': `${nowSec}.${Math.floor(Math.random() * 1000).toString().padStart(3, '0')}`,
1371
+ 'x-pigeon-session-id':
1372
+ state.pigeonSessionId ||
1373
+ `UFS-${crypto.randomBytes(16).toString('hex')}-3`,
1374
+ 'x-tigon-is-retry': 'False',
1375
+ 'accept-encoding': 'gzip, deflate',
1376
+ 'user-agent': userAgent,
1377
+ 'x-fb-conn-uuid-client': crypto.randomBytes(16).toString('hex'),
1378
+ 'x-fb-http-engine': 'MNS/TCP',
1379
+ 'x-fb-rmd': 'state=URL_ELIGIBLE',
1380
+ };
1381
+
1382
+ if (state.igURur) headers['ig-u-rur'] = state.igURur;
1383
+
1384
+ try {
1385
+ const response = await this.client.request.send({
1386
+ method: 'POST',
1387
+ url: '/api/v1/direct_v2/set_e2ee_eligibility/',
1388
+ form: {
1389
+ _uuid: qeDeviceId,
1390
+ e2ee_eligibility: String(eligibility),
1391
+ },
1392
+ headers,
1393
+ });
1394
+
1395
+ debugWrite('e2ee-eligibility-debug.json', {
1396
+ at: new Date().toISOString(),
1397
+ statusCode: response.statusCode || response.status || null,
1398
+ headers: response.headers || null,
1399
+ body: response.body || null,
1400
+ });
1401
+
1402
+ return response.body;
1403
+ } catch (e) {
1404
+ return null;
1405
+ }
1264
1406
  }
1265
1407
 
1266
1408
  async twoFactorLogin(username, verificationCode, twoFactorIdentifier, verificationMethod = '1') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodejs-insta-private-api-mqt",
3
- "version": "1.4.5",
3
+ "version": "1.4.6",
4
4
  "description": "Complete Instagram MQTT protocol with full-featured REALTIME and REST API — all in one project.",
5
5
 
6
6
  "main": "dist/dist/index.js",