nodejs-insta-private-api-mqtt 1.3.17 → 1.3.18

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.
@@ -6,7 +6,7 @@ const fbns_device_auth_1 = require("./fbns.device-auth");
6
6
  const shared_1 = require("../shared");
7
7
  const mqttot_1 = require("../mqttot");
8
8
  const chance_1 = require("chance");
9
- const mqtts_1 = require("mqtts");
9
+ const mqtts_1 = require("../mqtt-shim");
10
10
  const errors_1 = require("../errors");
11
11
  const eventemitter3_1 = require("eventemitter3");
12
12
  const fbns_utilities_1 = require("./fbns.utilities");
@@ -0,0 +1,96 @@
1
+ import { EventEmitter } from 'events';
2
+
3
+ export class PacketType {
4
+ static Connect: number;
5
+ static ConnAck: number;
6
+ static Publish: number;
7
+ static PubAck: number;
8
+ static Subscribe: number;
9
+ static SubAck: number;
10
+ static Unsubscribe: number;
11
+ static UnsubAck: number;
12
+ static PingReq: number;
13
+ static PingResp: number;
14
+ static Disconnect: number;
15
+ }
16
+
17
+ export class ConnectResponsePacket {
18
+ ackFlags: number;
19
+ returnCode: number;
20
+ payload?: Buffer;
21
+ get isSuccess(): boolean;
22
+ get errorName(): string | null;
23
+ constructor(ackFlags: number, returnCode: number, payload?: Buffer);
24
+ }
25
+
26
+ export class IllegalStateError extends Error {}
27
+
28
+ export interface MqttMessage {
29
+ topic: string;
30
+ payload: Buffer;
31
+ qosLevel?: number;
32
+ }
33
+
34
+ export interface MqttMessageOutgoing {
35
+ topic: string;
36
+ payload: Buffer;
37
+ qosLevel?: number;
38
+ }
39
+
40
+ export interface PacketFlowFunc {
41
+ (success: (packet: any) => void, error: (error: Error) => void): {
42
+ start: () => any;
43
+ accept: (packet: any) => boolean;
44
+ next: (packet: any) => void;
45
+ };
46
+ }
47
+
48
+ export class MqttClient extends EventEmitter {
49
+ constructor(options: any);
50
+ connect(options?: any): Promise<void>;
51
+ publish(message: MqttMessageOutgoing): Promise<any>;
52
+ subscribe(topic: string, qos?: number): Promise<void>;
53
+ disconnect(): void;
54
+ topicMap: Map<string, any>;
55
+ }
56
+
57
+ export class TlsTransport { constructor(options: any); }
58
+ export class SocksTlsTransport { constructor(options: any); }
59
+
60
+ export class PacketStream {
61
+ constructor(buffer: Buffer);
62
+ readByte(): number;
63
+ readStringAsBuffer(): Buffer;
64
+ readWord(): number;
65
+ }
66
+
67
+ export const DefaultPacketReadMap: any;
68
+ export const DefaultPacketWriteMap: any;
69
+ export function isConnAck(packet: any): boolean;
70
+
71
+ export interface ConnectRequestOptions {
72
+ payload?: Buffer;
73
+ keepAlive?: number;
74
+ [key: string]: any;
75
+ }
76
+
77
+ export interface DefaultPacketReadResultMap {
78
+ [key: number]: (stream: PacketStream, length: number) => any;
79
+ }
80
+
81
+ export interface DefaultPacketWriteOptions {
82
+ [key: string]: any;
83
+ }
84
+
85
+ export interface PacketWriteResult {
86
+ [key: string]: any;
87
+ }
88
+
89
+ export enum ConnectReturnCode {
90
+ ACCEPTED = 0,
91
+ UNACCEPTABLE_PROTOCOL_VERSION = 1,
92
+ IDENTIFIER_REJECTED = 2,
93
+ SERVER_UNAVAILABLE = 3,
94
+ BAD_USERNAME_OR_PASSWORD = 4,
95
+ NOT_AUTHORIZED = 5,
96
+ }
@@ -0,0 +1,337 @@
1
+ const EventEmitter = require('events');
2
+ const tls = require('tls');
3
+ const net = require('net');
4
+ let SocksClient;
5
+ try { SocksClient = require('socks').SocksClient; } catch (e) {}
6
+
7
+ class PacketType {
8
+ static Connect = 1;
9
+ static ConnAck = 2;
10
+ static Publish = 3;
11
+ static PubAck = 4;
12
+ static Subscribe = 8;
13
+ static SubAck = 9;
14
+ static Unsubscribe = 10;
15
+ static UnsubAck = 11;
16
+ static PingReq = 12;
17
+ static PingResp = 13;
18
+ static Disconnect = 14;
19
+ }
20
+
21
+ class ConnectResponsePacket {
22
+ constructor(ackFlags, returnCode, payload) {
23
+ this.ackFlags = ackFlags;
24
+ this.returnCode = returnCode;
25
+ this.payload = payload;
26
+ }
27
+ get isSuccess() { return this.returnCode === 0; }
28
+ get errorName() { return this.returnCode !== 0 ? 'Connection Refused' : null; }
29
+ }
30
+
31
+ class IllegalStateError extends Error {
32
+ constructor(msg) { super(msg); this.name = 'IllegalStateError'; }
33
+ }
34
+
35
+ class PacketStream {
36
+ constructor(buffer) {
37
+ this.buffer = buffer;
38
+ this.offset = 0;
39
+ }
40
+ readByte() {
41
+ if (this.offset >= this.buffer.length) return 0;
42
+ return this.buffer[this.offset++];
43
+ }
44
+ readStringAsBuffer() {
45
+ const len = this.readWord();
46
+ if (this.offset + len > this.buffer.length) return Buffer.alloc(0);
47
+ const buf = this.buffer.slice(this.offset, this.offset + len);
48
+ this.offset += len;
49
+ return buf;
50
+ }
51
+ readWord() {
52
+ if (this.offset + 2 > this.buffer.length) return 0;
53
+ const w = this.buffer.readUInt16BE(this.offset);
54
+ this.offset += 2;
55
+ return w;
56
+ }
57
+ }
58
+
59
+ class PacketWriter {
60
+ constructor() { this.chunks = []; }
61
+ writeByte(b) { const buf = Buffer.alloc(1); buf.writeUInt8(b); this.chunks.push(buf); return this; }
62
+ writeWord(w) { const buf = Buffer.alloc(2); buf.writeUInt16BE(w); this.chunks.push(buf); return this; }
63
+ writeString(s) { this.writeWord(s.length); this.chunks.push(Buffer.from(s)); return this; }
64
+ write(buf) { this.chunks.push(buf); return this; }
65
+ toBuffer() { return Buffer.concat(this.chunks); }
66
+ }
67
+
68
+ class MqttClient extends EventEmitter {
69
+ constructor(options) {
70
+ super();
71
+ this.options = options || {};
72
+ this.readMap = options.readMap || {};
73
+ this.writeMap = options.writeMap || {};
74
+ this.socket = null;
75
+ this.topicMap = new Map();
76
+ this.packetIdCounter = 1;
77
+ this.pendingPublishes = new Map(); // PacketID -> {resolve, reject, timer}
78
+ this.pingTimer = null;
79
+ this.keepAliveInterval = 60000;
80
+ }
81
+
82
+ getNextPacketId() {
83
+ const id = this.packetIdCounter;
84
+ this.packetIdCounter++;
85
+ if (this.packetIdCounter > 65535) this.packetIdCounter = 1;
86
+ return id;
87
+ }
88
+
89
+ async connect(opts) {
90
+ return new Promise(async (resolve, reject) => {
91
+ const port = 443;
92
+ const host = this.options.transport && this.options.transport.host ? this.options.transport.host : 'edge-mqtt.facebook.com';
93
+ const connectOpts = opts || {};
94
+
95
+ const onConnect = () => {
96
+ // Setup Ping Timer
97
+ this._setupPingTimer();
98
+
99
+ try {
100
+ const writer = new PacketWriter();
101
+ const writeFunc = this.writeMap[PacketType.Connect];
102
+ if (writeFunc) {
103
+ writeFunc(writer, {
104
+ ...this.options,
105
+ ...connectOpts,
106
+ payload: this.connectPayload || connectOpts.payload,
107
+ keepAlive: 60
108
+ });
109
+ const packetData = writer.toBuffer();
110
+ let remLen = packetData.length;
111
+ const fixedHeader = [ (PacketType.Connect << 4) ];
112
+ do {
113
+ let byte = remLen % 128;
114
+ remLen = Math.floor(remLen / 128);
115
+ if (remLen > 0) byte = byte | 128;
116
+ fixedHeader.push(byte);
117
+ } while (remLen > 0);
118
+
119
+ this.socket.write(Buffer.concat([Buffer.from(fixedHeader), packetData]));
120
+ } else {
121
+ this.emit('error', new Error('No write handler for CONNECT'));
122
+ }
123
+ } catch (e) {
124
+ this.emit('error', e);
125
+ }
126
+ };
127
+
128
+ try {
129
+ if (this.options.transport instanceof SocksTlsTransport && SocksClient) {
130
+ // SOCKS Proxy Connection
131
+ const proxyOpts = this.options.transport.proxyOptions;
132
+ const info = {
133
+ proxy: {
134
+ host: proxyOpts.host || proxyOpts.ipaddress,
135
+ port: parseInt(proxyOpts.port),
136
+ type: 5
137
+ },
138
+ command: 'connect',
139
+ destination: {
140
+ host: host,
141
+ port: port
142
+ }
143
+ };
144
+
145
+ if (proxyOpts.username) {
146
+ info.proxy.userId = proxyOpts.username;
147
+ info.proxy.password = proxyOpts.password;
148
+ }
149
+
150
+ const { socket: proxySocket } = await SocksClient.createConnection(info);
151
+ this.socket = tls.connect({
152
+ socket: proxySocket,
153
+ rejectUnauthorized: false,
154
+ servername: host
155
+ }, onConnect);
156
+ } else {
157
+ // Direct TLS Connection
158
+ this.socket = tls.connect(port, host, { rejectUnauthorized: false }, onConnect);
159
+ }
160
+
161
+ this.socket.on('data', (data) => this._handleData(data));
162
+ this.socket.on('error', (err) => {
163
+ this._clearPingTimer();
164
+ this.emit('error', err);
165
+ });
166
+ this.socket.on('close', () => {
167
+ this._clearPingTimer();
168
+ this.emit('disconnect');
169
+ });
170
+
171
+ this.once('connect_success', resolve);
172
+ } catch (e) {
173
+ reject(e);
174
+ }
175
+ });
176
+ }
177
+
178
+ _setupPingTimer() {
179
+ this._clearPingTimer();
180
+ this.pingTimer = setInterval(() => {
181
+ if (this.socket && !this.socket.destroyed) {
182
+ this.socket.write(Buffer.from([0xC0, 0x00])); // PINGREQ (12 << 4), Length 0
183
+ }
184
+ }, this.keepAliveInterval);
185
+ }
186
+
187
+ _clearPingTimer() {
188
+ if (this.pingTimer) clearInterval(this.pingTimer);
189
+ this.pingTimer = null;
190
+ }
191
+
192
+ _handleData(data) {
193
+ let offset = 0;
194
+ while(offset < data.length) {
195
+ const first = data[offset++];
196
+ const type = first >> 4;
197
+ let multiplier = 1;
198
+ let length = 0;
199
+ let digit;
200
+ do {
201
+ if (offset >= data.length) break;
202
+ digit = data[offset++];
203
+ length += (digit & 127) * multiplier;
204
+ multiplier *= 128;
205
+ } while ((digit & 128) !== 0);
206
+
207
+ if (offset + length > data.length) break;
208
+
209
+ const payload = data.slice(offset, offset + length);
210
+ offset += length;
211
+
212
+ if (type === PacketType.ConnAck) {
213
+ const readFunc = this.readMap[PacketType.ConnAck];
214
+ if (readFunc) {
215
+ const stream = new PacketStream(payload);
216
+ const packet = readFunc(stream, length);
217
+ if (packet.isSuccess) this.emit('connect_success');
218
+ this.emit('connect', { payload: packet.payload });
219
+ }
220
+ } else if (type === PacketType.Publish) {
221
+ try {
222
+ const topicLen = payload.readUInt16BE(0);
223
+ const topic = payload.slice(2, 2 + topicLen).toString();
224
+ const qos = (first & 0x06) >> 1;
225
+ let msgPayload;
226
+ if (qos > 0) {
227
+ // Skip Packet ID (2 bytes)
228
+ msgPayload = payload.slice(2 + topicLen + 2);
229
+ } else {
230
+ msgPayload = payload.slice(2 + topicLen);
231
+ }
232
+ this.emit('message', { topic, payload: msgPayload, qosLevel: qos });
233
+ } catch (e) {}
234
+ } else if (type === PacketType.PubAck) {
235
+ // Handle PubAck (QoS 1)
236
+ if (payload.length >= 2) {
237
+ const packetId = payload.readUInt16BE(0);
238
+ const pending = this.pendingPublishes.get(packetId);
239
+ if (pending) {
240
+ pending.resolve();
241
+ this.pendingPublishes.delete(packetId);
242
+ }
243
+ }
244
+ } else if (type === PacketType.PingResp) {
245
+ // Pong received, good
246
+ }
247
+ }
248
+ }
249
+
250
+ async publish(msg) {
251
+ if (!this.socket) return;
252
+ return new Promise((resolve, reject) => {
253
+ const writer = new PacketWriter();
254
+ writer.writeString(msg.topic);
255
+ let packetId = 0;
256
+ if (msg.qosLevel > 0) {
257
+ packetId = this.getNextPacketId();
258
+ writer.writeWord(packetId);
259
+ }
260
+ writer.write(msg.payload);
261
+
262
+ const packetData = writer.toBuffer();
263
+ const fixedHeader = [ (PacketType.Publish << 4) | (msg.qosLevel ? 2 : 0) ];
264
+ let remLen = packetData.length;
265
+ do {
266
+ let byte = remLen % 128;
267
+ remLen = Math.floor(remLen / 128);
268
+ if (remLen > 0) byte = byte | 128;
269
+ fixedHeader.push(byte);
270
+ } while (remLen > 0);
271
+
272
+ try {
273
+ this.socket.write(Buffer.concat([Buffer.from(fixedHeader), packetData]));
274
+ if (msg.qosLevel > 0) {
275
+ this.pendingPublishes.set(packetId, { resolve, reject });
276
+ // Timeout fallback for ack?
277
+ setTimeout(() => {
278
+ if (this.pendingPublishes.has(packetId)) {
279
+ this.pendingPublishes.delete(packetId);
280
+ resolve(); // Resolve anyway to not block logic
281
+ }
282
+ }, 5000);
283
+ } else {
284
+ resolve();
285
+ }
286
+ } catch (e) {
287
+ reject(e);
288
+ }
289
+ });
290
+ }
291
+
292
+ async subscribe(topic, qos = 0) {
293
+ if (!this.socket) return;
294
+ const writer = new PacketWriter();
295
+ writer.writeWord(this.getNextPacketId());
296
+ writer.writeString(topic);
297
+ writer.writeByte(qos);
298
+
299
+ const packetData = writer.toBuffer();
300
+ const fixedHeader = [ (PacketType.Subscribe << 4) | 2 ];
301
+ let remLen = packetData.length;
302
+ do {
303
+ let byte = remLen % 128;
304
+ remLen = Math.floor(remLen / 128);
305
+ if (remLen > 0) byte = byte | 128;
306
+ fixedHeader.push(byte);
307
+ } while (remLen > 0);
308
+
309
+ this.socket.write(Buffer.concat([Buffer.from(fixedHeader), packetData]));
310
+ }
311
+
312
+ disconnect() {
313
+ this._clearPingTimer();
314
+ if (this.socket) this.socket.end();
315
+ }
316
+ }
317
+
318
+ class TlsTransport { constructor(opts) { Object.assign(this, opts); } }
319
+ class SocksTlsTransport { constructor(opts) { Object.assign(this, opts); } }
320
+
321
+ function isConnAck(p) { return true; }
322
+
323
+ const DefaultPacketReadMap = {};
324
+ const DefaultPacketWriteMap = {};
325
+
326
+ module.exports = {
327
+ MqttClient,
328
+ PacketType,
329
+ ConnectResponsePacket,
330
+ IllegalStateError,
331
+ TlsTransport,
332
+ SocksTlsTransport,
333
+ DefaultPacketReadMap,
334
+ DefaultPacketWriteMap,
335
+ isConnAck,
336
+ PacketStream
337
+ };
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
3
  import { MQTToTConnectPacketOptions } from './mqttot.connect.request.packet';
4
- import { ConnectRequestOptions, DefaultPacketReadResultMap, DefaultPacketWriteOptions, MqttClient, MqttMessage, MqttMessageOutgoing, PacketFlowFunc, PacketType } from 'mqtts';
4
+ import * as mqtts_1 from '../mqtt-shim';
5
5
  import { MQTToTConnectResponsePacket } from './mqttot.connect.response.packet';
6
6
  import { SocksProxy } from 'socks';
7
7
  import { ConnectionOptions } from 'tls';
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mqttotConnectFlow = exports.MQTToTClient = void 0;
4
4
  const shared_1 = require("../shared");
5
5
  const mqttot_connect_request_packet_1 = require("./mqttot.connect.request.packet");
6
- const mqtts_1 = require("mqtts");
6
+ const mqtts_1 = require("../mqtt-shim");
7
7
  const errors_1 = require("../errors");
8
8
  const mqttot_connect_response_packet_1 = require("./mqttot.connect.response.packet");
9
9
  class MQTToTClient extends mqtts_1.MqttClient {
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { PacketStream, PacketWriteResult } from 'mqtts';
2
+ import * as mqtts_1 from '../mqtt-shim';
3
3
  export interface MQTToTConnectPacketOptions {
4
4
  keepAlive: number;
5
5
  payload: Buffer;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { ConnectResponsePacket, PacketStream, ConnectReturnCode } from 'mqtts';
2
+ import * as mqtts_1 from '../mqtt-shim';
3
3
  export declare class MQTToTConnectResponsePacket extends ConnectResponsePacket {
4
4
  readonly payload: Buffer;
5
5
  constructor(ackFlags: number, returnCode: ConnectReturnCode, payload: Buffer);
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.readConnectResponsePacket = exports.MQTToTConnectResponsePacket = void 0;
4
- const mqtts_1 = require("mqtts");
4
+ const mqtts_1 = require("../mqtt-shim");
5
5
  class MQTToTConnectResponsePacket extends mqtts_1.ConnectResponsePacket {
6
6
  constructor(ackFlags, returnCode, payload) {
7
7
  super(ackFlags, returnCode);
package/dist/package.json CHANGED
@@ -33,7 +33,7 @@
33
33
  "eventemitter3": "^5.0.1",
34
34
  "form-data": "^4.0.0",
35
35
  "lodash": "^4.17.21",
36
- "mqtts": "^1.5.0",
36
+ "mqtt": "^5.10.3",
37
37
  "node-persist": "^4.0.4",
38
38
  "pako": "^2.1.0",
39
39
  "protobufjs": "^7.5.4",
@@ -1,6 +1,6 @@
1
1
  import { Topic } from '../../topic';
2
2
  import { MQTToTClient } from '../../mqttot';
3
- import { MqttMessageOutgoing } from 'mqtts';
3
+ import * as mqtts_1 from '../../mqtt-shim';
4
4
  export declare class Commands {
5
5
  private client;
6
6
  constructor(client: MQTToTClient);
@@ -1,7 +1,7 @@
1
1
  import { MQTToTClient } from '../../mqttot';
2
2
  import { MessageSyncMessageTypes } from '../messages';
3
3
  import { ThriftPacketDescriptor } from '../../thrift';
4
- import { MqttMessageOutgoing } from 'mqtts';
4
+ import * as mqtts_1 from '../../mqtt-shim';
5
5
  interface ItemBaseType {
6
6
  threadId: string;
7
7
  clientContext?: string;
@@ -4,7 +4,7 @@ exports.MessageSyncMixin = void 0;
4
4
  const mixin_1 = require("./mixin");
5
5
  const constants_1 = require("../../constants");
6
6
  const shared_1 = require("../../shared");
7
- const mqtts_1 = require("mqtts");
7
+ const mqtts_1 = require("../../mqtt-shim");
8
8
 
9
9
  /**
10
10
  * MessageSyncMixin - patched for 2026 (robust parsing + safe username fetch + tolerant timestamp handling)
@@ -4,7 +4,7 @@ exports.RealtimeSubMixin = void 0;
4
4
  const mixin_1 = require("./mixin");
5
5
  const constants_1 = require("../../constants");
6
6
  const shared_1 = require("../../shared");
7
- const mqtts_1 = require("mqtts");
7
+ const mqtts_1 = require("../../mqtt-shim");
8
8
  class RealtimeSubMixin extends mixin_1.Mixin {
9
9
  apply(client) {
10
10
  (0, mixin_1.hook)(client, 'connect', {
@@ -5,7 +5,7 @@ const constants_1 = require("../constants");
5
5
  const commands_1 = require("./commands");
6
6
  const shared_1 = require("../shared");
7
7
  const mqttot_1 = require("../mqttot");
8
- const mqtts_1 = require("mqtts");
8
+ const mqtts_1 = require("../mqtt-shim");
9
9
  const errors_1 = require("../errors");
10
10
  const eventemitter3_1 = require("eventemitter3");
11
11
  const mixins_1 = require("./mixins");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodejs-insta-private-api-mqtt",
3
- "version": "1.3.17",
3
+ "version": "1.3.18",
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": {
@@ -52,7 +52,7 @@
52
52
  "eventemitter3": "^5.0.1",
53
53
  "form-data": "^4.0.0",
54
54
  "lodash": "^4.17.21",
55
- "mqtts": "^1.5.0",
55
+ "mqtt": "^5.10.3",
56
56
  "node-persist": "^4.0.4",
57
57
  "pako": "^2.1.0",
58
58
  "protobufjs": "^7.5.4",