nodejs-insta-private-api-mqtt 1.3.39 → 1.3.40

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.
@@ -4,769 +4,663 @@ exports.EnhancedDirectCommands = void 0;
4
4
  const shared_1 = require("../../shared");
5
5
  const uuid_1 = require("uuid");
6
6
  const constants_1 = require("../../constants");
7
+ const thrift_1 = require("../../thrift");
7
8
 
8
9
  /**
9
10
  * Enhanced Direct Commands - sends MQTT directly with proper payload formatting
11
+ * Fixed to match instagram_mqtt library format for proper functionality
10
12
  */
11
13
  class EnhancedDirectCommands {
12
14
  constructor(client) {
13
15
  this.realtimeClient = client;
14
16
  this.enhancedDebug = (0, shared_1.debugChannel)('realtime', 'enhanced-commands');
17
+
18
+ // Foreground state config for Thrift encoding (matching instagram_mqtt)
19
+ this.foregroundStateConfig = [
20
+ thrift_1.ThriftDescriptors.boolean('inForegroundApp', 1),
21
+ thrift_1.ThriftDescriptors.boolean('inForegroundDevice', 2),
22
+ thrift_1.ThriftDescriptors.int32('keepAliveTimeout', 3),
23
+ thrift_1.ThriftDescriptors.listOfBinary('subscribeTopics', 4),
24
+ thrift_1.ThriftDescriptors.listOfBinary('subscribeGenericTopics', 5),
25
+ thrift_1.ThriftDescriptors.listOfBinary('unsubscribeTopics', 6),
26
+ thrift_1.ThriftDescriptors.listOfBinary('unsubscribeGenericTopics', 7),
27
+ thrift_1.ThriftDescriptors.int64('requestId', 8),
28
+ ];
15
29
  }
16
30
 
17
31
  /**
18
- * Send text via MQTT with proper payload format
32
+ * Get MQTT client from realtime client
19
33
  */
20
- async sendTextViaRealtime(threadId, text) {
21
- this.enhancedDebug(`Sending text to ${threadId}: "${text}"`);
22
-
23
- try {
24
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
25
- if (!mqtt || typeof mqtt.publish !== 'function') {
26
- throw new Error('MQTT client not available');
34
+ getMqtt() {
35
+ // Try several known property names for mqtt client (some libs/wrappers expose differently)
36
+ const candidates = [
37
+ 'mqtt',
38
+ '_mqtt',
39
+ 'client',
40
+ '_client',
41
+ 'connection',
42
+ 'mqttClient',
43
+ ];
44
+ let mqtt = null;
45
+ for (const key of candidates) {
46
+ // eslint-disable-next-line no-prototype-builtins
47
+ if (this.realtimeClient && Object.prototype.hasOwnProperty.call(this.realtimeClient, key) && this.realtimeClient[key]) {
48
+ mqtt = this.realtimeClient[key];
49
+ break;
27
50
  }
28
-
29
- // Build proper command payload
30
- const clientContext = (0, uuid_1.v4)();
31
- const command = {
32
- action: 'send_item',
33
- thread_id: threadId,
34
- item_type: 'text',
35
- text: text,
36
- timestamp: Date.now(),
37
- client_context: clientContext,
38
- };
39
-
40
- // Compress JSON payload
41
- const json = JSON.stringify(command);
42
- const { compressDeflate } = shared_1;
43
- const payload = await compressDeflate(json);
44
-
45
- // Send to MQTT
46
- this.enhancedDebug(`Publishing to MQTT topic ${constants_1.Topics.SEND_MESSAGE.id}`);
47
- const result = await mqtt.publish({
48
- topic: constants_1.Topics.SEND_MESSAGE.id,
49
- qosLevel: 1,
50
- payload: payload,
51
- });
52
-
53
- this.enhancedDebug(`✅ Message sent via MQTT!`);
54
- return result;
55
- } catch (err) {
56
- this.enhancedDebug(`Failed: ${err.message}`);
57
- throw err;
58
51
  }
52
+ // fallback: maybe the realtimeClient itself *is* the mqtt client
53
+ if (!mqtt && this.realtimeClient && typeof this.realtimeClient.publish === 'function') {
54
+ mqtt = this.realtimeClient;
55
+ }
56
+
57
+ if (!mqtt || typeof mqtt.publish !== 'function') {
58
+ throw new Error('MQTT client not available or does not expose publish(). Found client keys: ' +
59
+ (this.realtimeClient ? Object.keys(this.realtimeClient).join(',') : 'none'));
60
+ }
61
+ return mqtt;
59
62
  }
60
63
 
61
64
  /**
62
- * Delete message via MQTT
65
+ * Robust mqtt publish wrapper - handles both:
66
+ * - mqtt.publish({ topic, payload, qosLevel }) returning a Promise or using callback
67
+ * - mqtt.publish(topic, payload, { qos }, cb)
63
68
  */
64
- async deleteMessage(threadId, itemId) {
65
- this.enhancedDebug(`Deleting message ${itemId} from thread ${threadId}`);
66
-
69
+ async publishToMqtt(mqtt, publishObj) {
70
+ // publishObj: { topic, payload, qosLevel }
71
+ const topic = publishObj.topic;
72
+ const payload = publishObj.payload;
73
+ const qosLevel = typeof publishObj.qosLevel !== 'undefined' ? publishObj.qosLevel : 1;
74
+
75
+ // Try object-style publish first (some wrappers expect object)
67
76
  try {
68
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
69
- if (!mqtt || typeof mqtt.publish !== 'function') {
70
- throw new Error('MQTT client not available');
77
+ const maybePromise = mqtt.publish({
78
+ topic,
79
+ payload,
80
+ qosLevel,
81
+ });
82
+ if (maybePromise && typeof maybePromise.then === 'function') {
83
+ return await maybePromise;
71
84
  }
72
-
73
- const clientContext = (0, uuid_1.v4)();
74
- const command = {
75
- action: 'delete_item',
76
- thread_id: threadId,
77
- item_id: itemId,
78
- timestamp: Date.now(),
79
- client_context: clientContext,
80
- };
81
-
82
- const json = JSON.stringify(command);
83
- const { compressDeflate } = shared_1;
84
- const payload = await compressDeflate(json);
85
-
86
- this.enhancedDebug(`Publishing delete command to MQTT topic ${constants_1.Topics.SEND_MESSAGE.id}`);
87
- const result = await mqtt.publish({
88
- topic: constants_1.Topics.SEND_MESSAGE.id,
89
- qosLevel: 1,
90
- payload: payload,
85
+ // if it returned synchronously, maybe it still used callback style
86
+ return await new Promise((resolve, reject) => {
87
+ try {
88
+ mqtt.publish({ topic, payload, qosLevel }, (err, res) => {
89
+ if (err)
90
+ return reject(err);
91
+ return resolve(res);
92
+ });
93
+ } catch (err) {
94
+ reject(err);
95
+ }
91
96
  });
92
-
93
- this.enhancedDebug(`✅ Message deleted via MQTT!`);
94
- return result;
95
- } catch (err) {
96
- this.enhancedDebug(`Delete failed: ${err.message}`);
97
- throw err;
97
+ } catch (e) {
98
+ // fallthrough to positional try
99
+ }
100
+
101
+ // Try positional-style publish (topic, payload, options, callback)
102
+ try {
103
+ return await new Promise((resolve, reject) => {
104
+ try {
105
+ mqtt.publish(topic, payload, { qos: qosLevel }, (err, res) => {
106
+ if (err)
107
+ return reject(err);
108
+ return resolve(res);
109
+ });
110
+ } catch (err) {
111
+ reject(err);
112
+ }
113
+ });
114
+ } catch (e) {
115
+ // final fallback: some clients return synchronously or throw - try positional without callback
116
+ try {
117
+ const res = mqtt.publish(topic, payload, { qos: qosLevel });
118
+ if (res && typeof res.then === 'function') {
119
+ return await res;
120
+ }
121
+ // last attempt: resolve with returned value
122
+ return res;
123
+ } catch (err) {
124
+ // give clear error
125
+ throw new Error(`MQTT publish failed: no known publish signature worked. Errors: ${err && err.message ? err.message : String(err)}`);
126
+ }
98
127
  }
99
128
  }
100
129
 
101
130
  /**
102
- * Edit message via MQTT
131
+ * Send foreground state via MQTT with Thrift encoding (matching instagram_mqtt)
103
132
  */
104
- async editMessage(threadId, itemId, newText) {
105
- this.enhancedDebug(`Editing message ${itemId}: "${newText}"`);
133
+ async sendForegroundState(state) {
134
+ this.enhancedDebug(`Updated foreground state: ${JSON.stringify(state)}`);
106
135
 
107
136
  try {
108
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
109
- if (!mqtt || typeof mqtt.publish !== 'function') {
110
- throw new Error('MQTT client not available');
111
- }
137
+ const mqtt = this.getMqtt();
112
138
 
113
- const clientContext = (0, uuid_1.v4)();
114
- const command = {
115
- action: 'edit_item',
116
- thread_id: threadId,
117
- item_id: itemId,
118
- text: newText,
119
- timestamp: Date.now(),
120
- client_context: clientContext,
121
- };
122
-
123
- const json = JSON.stringify(command);
124
- const { compressDeflate } = shared_1;
125
- const payload = await compressDeflate(json);
139
+ const thriftBuffer = (0, thrift_1.thriftWriteFromObject)(state, this.foregroundStateConfig);
140
+ const concat = Buffer.concat([
141
+ Buffer.alloc(1, 0),
142
+ thriftBuffer
143
+ ]);
144
+
145
+ // ensure we pass Buffer to compressDeflate
146
+ const payload = await (0, shared_1.compressDeflate)(concat);
126
147
 
127
- this.enhancedDebug(`Publishing edit command to MQTT topic ${constants_1.Topics.SEND_MESSAGE.id}`);
128
- const result = await mqtt.publish({
129
- topic: constants_1.Topics.SEND_MESSAGE.id,
130
- qosLevel: 1,
148
+ const result = await this.publishToMqtt(mqtt, {
149
+ topic: constants_1.Topics.FOREGROUND_STATE.id,
131
150
  payload: payload,
151
+ qosLevel: 1,
132
152
  });
133
153
 
134
- this.enhancedDebug(`✅ Message edited via MQTT!`);
154
+ // Update keepAlive if provided
155
+ if ((0, shared_1.notUndefined)(state.keepAliveTimeout)) {
156
+ mqtt.keepAlive = state.keepAliveTimeout;
157
+ }
158
+
159
+ this.enhancedDebug(`✅ Foreground state updated via MQTT!`);
135
160
  return result;
136
161
  } catch (err) {
137
- this.enhancedDebug(`Edit failed: ${err.message}`);
162
+ this.enhancedDebug(`Foreground state failed: ${err && err.message ? err.message : String(err)}`);
138
163
  throw err;
139
164
  }
140
165
  }
141
166
 
142
167
  /**
143
- * Reply to message via MQTT (Quote Reply)
168
+ * Base command sender (matching instagram_mqtt format)
144
169
  */
145
- async replyToMessage(threadId, messageId, replyText) {
146
- this.enhancedDebug(`Replying to ${messageId} in thread ${threadId}: "${replyText}"`);
147
-
170
+ async sendCommand({ action, data, threadId, clientContext }) {
148
171
  try {
149
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
150
- if (!mqtt || typeof mqtt.publish !== 'function') {
151
- throw new Error('MQTT client not available');
172
+ const mqtt = this.getMqtt();
173
+
174
+ if (clientContext) {
175
+ data.client_context = clientContext;
152
176
  }
153
177
 
154
- const clientContext = (0, uuid_1.v4)();
155
- const command = {
156
- action: 'send_item',
178
+ const json = JSON.stringify({
179
+ action,
157
180
  thread_id: threadId,
158
- item_type: 'text',
159
- text: replyText,
160
- replying_to_item_id: messageId,
161
- timestamp: Date.now(),
162
- client_context: clientContext,
163
- };
164
-
165
- const json = JSON.stringify(command);
166
- const { compressDeflate } = shared_1;
167
- const payload = await compressDeflate(json);
181
+ ...data,
182
+ });
183
+
184
+ // ensure Buffer (some compress implementations expect Buffer)
185
+ const payload = await (0, shared_1.compressDeflate)(Buffer.from(json));
168
186
 
169
- this.enhancedDebug(`Publishing reply command to MQTT topic ${constants_1.Topics.SEND_MESSAGE.id}`);
170
- const result = await mqtt.publish({
187
+ return this.publishToMqtt(mqtt, {
171
188
  topic: constants_1.Topics.SEND_MESSAGE.id,
172
189
  qosLevel: 1,
173
190
  payload: payload,
174
191
  });
175
-
176
- this.enhancedDebug(`✅ Reply sent via MQTT!`);
177
- return result;
178
192
  } catch (err) {
179
- this.enhancedDebug(`Reply failed: ${err.message}`);
193
+ this.enhancedDebug(`sendCommand failed: ${err && err.message ? err.message : String(err)}`);
180
194
  throw err;
181
195
  }
182
196
  }
183
197
 
184
198
  /**
185
- * Subscribe to follow notifications via MQTT
199
+ * Base item sender (matching instagram_mqtt format)
186
200
  */
187
- async subscribeToFollowNotifications() {
188
- this.enhancedDebug(`Subscribing to follow notifications via MQTT`);
201
+ async sendItem({ threadId, itemType, data, clientContext }) {
202
+ return this.sendCommand({
203
+ action: 'send_item',
204
+ threadId,
205
+ clientContext: clientContext || (0, uuid_1.v4)(),
206
+ data: {
207
+ item_type: itemType,
208
+ ...data,
209
+ },
210
+ });
211
+ }
212
+
213
+ /**
214
+ * Send text via MQTT (matching instagram_mqtt format)
215
+ */
216
+ async sendText({ text, clientContext, threadId }) {
217
+ this.enhancedDebug(`Sending text to ${threadId}: "${text}"`);
189
218
 
190
- try {
191
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
192
- if (!mqtt || typeof mqtt.publish !== 'function') {
193
- throw new Error('MQTT client not available');
194
- }
195
-
196
- const clientContext = (0, uuid_1.v4)();
197
- const command = {
198
- action: 'subscribe',
199
- subscription_type: 'follow_notifications',
200
- timestamp: Date.now(),
201
- client_context: clientContext,
202
- };
203
-
204
- const json = JSON.stringify(command);
205
- const { compressDeflate } = shared_1;
206
- const payload = await compressDeflate(json);
207
-
208
- this.enhancedDebug(`Publishing follow subscription to MQTT`);
209
- const result = await mqtt.publish({
210
- topic: constants_1.Topics.SEND_MESSAGE.id,
211
- qosLevel: 1,
212
- payload: payload,
213
- });
214
-
215
- this.enhancedDebug(`✅ Follow notifications subscribed via MQTT!`);
216
- return result;
217
- } catch (err) {
218
- this.enhancedDebug(`Follow subscription failed: ${err.message}`);
219
- throw err;
220
- }
219
+ const result = await this.sendItem({
220
+ itemType: 'text',
221
+ threadId,
222
+ clientContext,
223
+ data: {
224
+ text,
225
+ },
226
+ });
227
+
228
+ this.enhancedDebug(`✅ Text sent via MQTT!`);
229
+ return result;
221
230
  }
222
231
 
223
232
  /**
224
- * Subscribe to mention notifications via MQTT
233
+ * Alias for sendText
225
234
  */
226
- async subscribeToMentionNotifications() {
227
- this.enhancedDebug(`Subscribing to mention notifications via MQTT`);
235
+ async sendTextViaRealtime(threadId, text, clientContext) {
236
+ return this.sendText({
237
+ text,
238
+ threadId,
239
+ clientContext,
240
+ });
241
+ }
242
+
243
+ /**
244
+ * Send hashtag via MQTT (matching instagram_mqtt format)
245
+ */
246
+ async sendHashtag({ text, threadId, hashtag, clientContext }) {
247
+ this.enhancedDebug(`Sending hashtag #${hashtag} to ${threadId}`);
228
248
 
229
- try {
230
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
231
- if (!mqtt || typeof mqtt.publish !== 'function') {
232
- throw new Error('MQTT client not available');
233
- }
234
-
235
- const clientContext = (0, uuid_1.v4)();
236
- const command = {
237
- action: 'subscribe',
238
- subscription_type: 'mention_notifications',
239
- timestamp: Date.now(),
240
- client_context: clientContext,
241
- };
242
-
243
- const json = JSON.stringify(command);
244
- const { compressDeflate } = shared_1;
245
- const payload = await compressDeflate(json);
246
-
247
- this.enhancedDebug(`Publishing mention subscription to MQTT`);
248
- const result = await mqtt.publish({
249
- topic: constants_1.Topics.SEND_MESSAGE.id,
250
- qosLevel: 1,
251
- payload: payload,
252
- });
253
-
254
- this.enhancedDebug(`✅ Mention notifications subscribed via MQTT!`);
255
- return result;
256
- } catch (err) {
257
- this.enhancedDebug(`Mention subscription failed: ${err.message}`);
258
- throw err;
259
- }
249
+ const result = await this.sendItem({
250
+ itemType: 'hashtag',
251
+ threadId,
252
+ clientContext,
253
+ data: {
254
+ text: text || '',
255
+ hashtag,
256
+ item_id: hashtag,
257
+ },
258
+ });
259
+
260
+ this.enhancedDebug(`✅ Hashtag sent via MQTT!`);
261
+ return result;
260
262
  }
261
263
 
262
264
  /**
263
- * Subscribe to call notifications via MQTT
265
+ * Send like via MQTT (matching instagram_mqtt format)
264
266
  */
265
- async subscribeToCallNotifications() {
266
- this.enhancedDebug(`Subscribing to call notifications via MQTT`);
267
+ async sendLike({ threadId, clientContext }) {
268
+ this.enhancedDebug(`Sending like in thread ${threadId}`);
267
269
 
268
- try {
269
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
270
- if (!mqtt || typeof mqtt.publish !== 'function') {
271
- throw new Error('MQTT client not available');
272
- }
273
-
274
- const clientContext = (0, uuid_1.v4)();
275
- const command = {
276
- action: 'subscribe',
277
- subscription_type: 'call_notifications',
278
- timestamp: Date.now(),
279
- client_context: clientContext,
280
- };
281
-
282
- const json = JSON.stringify(command);
283
- const { compressDeflate } = shared_1;
284
- const payload = await compressDeflate(json);
285
-
286
- this.enhancedDebug(`Publishing call subscription to MQTT`);
287
- const result = await mqtt.publish({
288
- topic: constants_1.Topics.SEND_MESSAGE.id,
289
- qosLevel: 1,
290
- payload: payload,
291
- });
292
-
293
- this.enhancedDebug(`✅ Call notifications subscribed via MQTT!`);
294
- return result;
295
- } catch (err) {
296
- this.enhancedDebug(`Call subscription failed: ${err.message}`);
297
- throw err;
298
- }
270
+ const result = await this.sendItem({
271
+ itemType: 'like',
272
+ threadId,
273
+ clientContext,
274
+ data: {},
275
+ });
276
+
277
+ this.enhancedDebug(`✅ Like sent via MQTT!`);
278
+ return result;
299
279
  }
300
280
 
301
281
  /**
302
- * Add member to thread via MQTT
282
+ * Send location via MQTT (matching instagram_mqtt format)
303
283
  */
304
- async addMemberToThread(threadId, userId) {
305
- this.enhancedDebug(`Adding user ${userId} to thread ${threadId} via MQTT`);
284
+ async sendLocation({ text, locationId, threadId, clientContext }) {
285
+ this.enhancedDebug(`Sending location ${locationId} to ${threadId}`);
306
286
 
307
- try {
308
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
309
- if (!mqtt || typeof mqtt.publish !== 'function') {
310
- throw new Error('MQTT client not available');
311
- }
312
-
313
- const clientContext = (0, uuid_1.v4)();
314
- const command = {
315
- action: 'add_member',
316
- thread_id: threadId,
317
- user_id: userId,
318
- timestamp: Date.now(),
319
- client_context: clientContext,
320
- };
321
-
322
- const json = JSON.stringify(command);
323
- const { compressDeflate } = shared_1;
324
- const payload = await compressDeflate(json);
325
-
326
- this.enhancedDebug(`Publishing add member command to MQTT`);
327
- const result = await mqtt.publish({
328
- topic: constants_1.Topics.SEND_MESSAGE.id,
329
- qosLevel: 1,
330
- payload: payload,
331
- });
332
-
333
- this.enhancedDebug(`✅ Member added to thread via MQTT!`);
334
- return result;
335
- } catch (err) {
336
- this.enhancedDebug(`Add member failed: ${err.message}`);
337
- throw err;
338
- }
287
+ const result = await this.sendItem({
288
+ itemType: 'location',
289
+ threadId,
290
+ clientContext,
291
+ data: {
292
+ text: text || '',
293
+ venue_id: locationId,
294
+ item_id: locationId,
295
+ },
296
+ });
297
+
298
+ this.enhancedDebug(`✅ Location sent via MQTT!`);
299
+ return result;
339
300
  }
340
301
 
341
302
  /**
342
- * Remove member from thread via MQTT
303
+ * Send media via MQTT (matching instagram_mqtt format - media_share)
343
304
  */
344
- async removeMemberFromThread(threadId, userId) {
345
- this.enhancedDebug(`Removing user ${userId} from thread ${threadId} via MQTT`);
305
+ async sendMedia({ text, mediaId, threadId, clientContext }) {
306
+ this.enhancedDebug(`Sending media ${mediaId} to ${threadId}`);
346
307
 
347
- try {
348
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
349
- if (!mqtt || typeof mqtt.publish !== 'function') {
350
- throw new Error('MQTT client not available');
351
- }
352
-
353
- const clientContext = (0, uuid_1.v4)();
354
- const command = {
355
- action: 'remove_member',
356
- thread_id: threadId,
357
- user_id: userId,
358
- timestamp: Date.now(),
359
- client_context: clientContext,
360
- };
361
-
362
- const json = JSON.stringify(command);
363
- const { compressDeflate } = shared_1;
364
- const payload = await compressDeflate(json);
365
-
366
- this.enhancedDebug(`Publishing remove member command to MQTT`);
367
- const result = await mqtt.publish({
368
- topic: constants_1.Topics.SEND_MESSAGE.id,
369
- qosLevel: 1,
370
- payload: payload,
371
- });
372
-
373
- this.enhancedDebug(`✅ Member removed from thread via MQTT!`);
374
- return result;
375
- } catch (err) {
376
- this.enhancedDebug(`Remove member failed: ${err.message}`);
377
- throw err;
378
- }
308
+ const result = await this.sendItem({
309
+ itemType: 'media_share',
310
+ threadId,
311
+ clientContext,
312
+ data: {
313
+ text: text || '',
314
+ media_id: mediaId,
315
+ },
316
+ });
317
+
318
+ this.enhancedDebug(`✅ Media sent via MQTT!`);
319
+ return result;
379
320
  }
380
321
 
381
322
  /**
382
- * Send reaction (emoji) via MQTT
323
+ * Send profile via MQTT (matching instagram_mqtt format)
383
324
  */
384
- async sendReaction({ itemId, reactionType = 'like', clientContext, threadId, reactionStatus = 'created', emoji }) {
385
- this.enhancedDebug(`Sending ${reactionType} reaction to message ${itemId} via MQTT`);
325
+ async sendProfile({ text, userId, threadId, clientContext }) {
326
+ this.enhancedDebug(`Sending profile ${userId} to ${threadId}`);
386
327
 
387
- try {
388
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
389
- if (!mqtt || typeof mqtt.publish !== 'function') {
390
- throw new Error('MQTT client not available');
391
- }
392
-
393
- const ctx = clientContext || (0, uuid_1.v4)();
394
- const command = {
395
- action: 'send_reaction',
396
- thread_id: threadId,
328
+ const result = await this.sendItem({
329
+ itemType: 'profile',
330
+ threadId,
331
+ clientContext,
332
+ data: {
333
+ text: text || '',
334
+ profile_user_id: userId,
335
+ item_id: userId,
336
+ },
337
+ });
338
+
339
+ this.enhancedDebug(`✅ Profile sent via MQTT!`);
340
+ return result;
341
+ }
342
+
343
+ /**
344
+ * Send reaction via MQTT (matching instagram_mqtt format)
345
+ */
346
+ async sendReaction({ itemId, reactionType, clientContext, threadId, reactionStatus, targetItemType, emoji }) {
347
+ this.enhancedDebug(`Sending ${reactionType || 'like'} reaction to message ${itemId}`);
348
+
349
+ const result = await this.sendItem({
350
+ itemType: 'reaction',
351
+ threadId,
352
+ clientContext,
353
+ data: {
397
354
  item_id: itemId,
398
- reaction_type: reactionType,
399
- reaction_status: reactionStatus,
355
+ node_type: 'item',
356
+ reaction_type: reactionType || (emoji ? 'emoji' : 'like'),
357
+ reaction_status: reactionStatus || 'created',
358
+ target_item_type: targetItemType,
400
359
  emoji: emoji || '',
401
- timestamp: Date.now(),
402
- client_context: ctx,
403
- };
404
-
405
- const json = JSON.stringify(command);
406
- const { compressDeflate } = shared_1;
407
- const payload = await compressDeflate(json);
408
-
409
- this.enhancedDebug(`Publishing reaction to MQTT`);
410
- const result = await mqtt.publish({
411
- topic: constants_1.Topics.SEND_MESSAGE.id,
412
- qosLevel: 1,
413
- payload: payload,
414
- });
415
-
416
- this.enhancedDebug(`✅ Reaction sent via MQTT!`);
417
- return result;
418
- } catch (err) {
419
- this.enhancedDebug(`Reaction failed: ${err.message}`);
420
- throw err;
421
- }
360
+ },
361
+ });
362
+
363
+ this.enhancedDebug(`✅ Reaction sent via MQTT!`);
364
+ return result;
422
365
  }
423
366
 
424
367
  /**
425
- * Mark message as seen via MQTT
368
+ * Send user story via MQTT (matching instagram_mqtt format - reel_share)
369
+ */
370
+ async sendUserStory({ text, storyId, threadId, clientContext }) {
371
+ this.enhancedDebug(`Sending story ${storyId} to ${threadId}`);
372
+
373
+ const result = await this.sendItem({
374
+ itemType: 'reel_share',
375
+ threadId,
376
+ clientContext,
377
+ data: {
378
+ text: text || '',
379
+ item_id: storyId,
380
+ media_id: storyId,
381
+ },
382
+ });
383
+
384
+ this.enhancedDebug(`✅ Story sent via MQTT!`);
385
+ return result;
386
+ }
387
+
388
+ /**
389
+ * Mark as seen via MQTT (matching instagram_mqtt format - mark_seen action)
426
390
  */
427
391
  async markAsSeen({ threadId, itemId }) {
428
- this.enhancedDebug(`Marking message ${itemId} as seen in thread ${threadId} via MQTT`);
392
+ this.enhancedDebug(`Marking message ${itemId} as seen in thread ${threadId}`);
429
393
 
430
- try {
431
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
432
- if (!mqtt || typeof mqtt.publish !== 'function') {
433
- throw new Error('MQTT client not available');
434
- }
435
-
436
- const clientContext = (0, uuid_1.v4)();
437
- const command = {
438
- action: 'mark_as_seen',
439
- thread_id: threadId,
394
+ const result = await this.sendCommand({
395
+ action: 'mark_seen',
396
+ threadId,
397
+ data: {
440
398
  item_id: itemId,
441
- timestamp: Date.now(),
442
- client_context: clientContext,
443
- };
444
-
445
- const json = JSON.stringify(command);
446
- const { compressDeflate } = shared_1;
447
- const payload = await compressDeflate(json);
448
-
449
- this.enhancedDebug(`Publishing mark as seen to MQTT`);
450
- const result = await mqtt.publish({
451
- topic: constants_1.Topics.SEND_MESSAGE.id,
452
- qosLevel: 1,
453
- payload: payload,
454
- });
455
-
456
- this.enhancedDebug(`✅ Message marked as seen via MQTT!`);
457
- return result;
458
- } catch (err) {
459
- this.enhancedDebug(`Mark as seen failed: ${err.message}`);
460
- throw err;
461
- }
399
+ },
400
+ });
401
+
402
+ this.enhancedDebug(`✅ Message marked as seen via MQTT!`);
403
+ return result;
462
404
  }
463
405
 
464
406
  /**
465
- * Indicate activity (typing) via MQTT
407
+ * Indicate activity (typing) via MQTT (matching instagram_mqtt format - activity_status)
466
408
  */
467
- async indicateActivity({ threadId, isActive = true, clientContext }) {
468
- this.enhancedDebug(`Indicating ${isActive ? 'typing' : 'stopped'} in thread ${threadId} via MQTT`);
409
+ async indicateActivity({ threadId, isActive, clientContext }) {
410
+ const active = typeof isActive === 'undefined' ? true : isActive;
411
+ this.enhancedDebug(`Indicating ${active ? 'typing' : 'stopped'} in thread ${threadId}`);
469
412
 
470
- try {
471
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
472
- if (!mqtt || typeof mqtt.publish !== 'function') {
473
- throw new Error('MQTT client not available');
474
- }
475
-
476
- const ctx = clientContext || (0, uuid_1.v4)();
477
- const command = {
478
- action: 'indicate_activity',
479
- thread_id: threadId,
480
- is_active: isActive,
481
- timestamp: Date.now(),
482
- client_context: ctx,
483
- };
484
-
485
- const json = JSON.stringify(command);
486
- const { compressDeflate } = shared_1;
487
- const payload = await compressDeflate(json);
488
-
489
- this.enhancedDebug(`Publishing activity indicator to MQTT`);
490
- const result = await mqtt.publish({
491
- topic: constants_1.Topics.SEND_MESSAGE.id,
492
- qosLevel: 1,
493
- payload: payload,
494
- });
495
-
496
- this.enhancedDebug(`✅ Activity indicator sent via MQTT!`);
497
- return result;
498
- } catch (err) {
499
- this.enhancedDebug(`Activity indicator failed: ${err.message}`);
500
- throw err;
501
- }
413
+ const result = await this.sendCommand({
414
+ action: 'indicate_activity',
415
+ threadId,
416
+ clientContext: clientContext || (0, uuid_1.v4)(),
417
+ data: {
418
+ activity_status: active ? '1' : '0',
419
+ },
420
+ });
421
+
422
+ this.enhancedDebug(`✅ Activity indicator sent via MQTT!`);
423
+ return result;
502
424
  }
503
425
 
504
426
  /**
505
- * Send media (image/video) via MQTT
427
+ * Delete message via MQTT
506
428
  */
507
- async sendMedia({ text, mediaId, threadId, clientContext }) {
508
- this.enhancedDebug(`Sending media ${mediaId} to ${threadId} via MQTT`);
429
+ async deleteMessage(threadId, itemId) {
430
+ this.enhancedDebug(`Deleting message ${itemId} from thread ${threadId}`);
509
431
 
510
- try {
511
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
512
- if (!mqtt || typeof mqtt.publish !== 'function') {
513
- throw new Error('MQTT client not available');
514
- }
515
-
516
- const ctx = clientContext || (0, uuid_1.v4)();
517
- const command = {
518
- action: 'send_item',
519
- thread_id: threadId,
520
- item_type: 'media',
521
- media_id: mediaId,
522
- text: text || '',
523
- timestamp: Date.now(),
524
- client_context: ctx,
525
- };
526
-
527
- const json = JSON.stringify(command);
528
- const { compressDeflate } = shared_1;
529
- const payload = await compressDeflate(json);
530
-
531
- this.enhancedDebug(`Publishing media to MQTT`);
532
- const result = await mqtt.publish({
533
- topic: constants_1.Topics.SEND_MESSAGE.id,
534
- qosLevel: 1,
535
- payload: payload,
536
- });
537
-
538
- this.enhancedDebug(`✅ Media sent via MQTT!`);
539
- return result;
540
- } catch (err) {
541
- this.enhancedDebug(`Media send failed: ${err.message}`);
542
- throw err;
543
- }
432
+ const result = await this.sendCommand({
433
+ action: 'delete_item',
434
+ threadId,
435
+ clientContext: (0, uuid_1.v4)(),
436
+ data: {
437
+ item_id: itemId,
438
+ },
439
+ });
440
+
441
+ this.enhancedDebug(`✅ Message deleted via MQTT!`);
442
+ return result;
544
443
  }
545
444
 
546
445
  /**
547
- * Send location via MQTT
446
+ * Edit message via MQTT
548
447
  */
549
- async sendLocation({ text, locationId, threadId, clientContext }) {
550
- this.enhancedDebug(`Sending location ${locationId} to ${threadId} via MQTT`);
448
+ async editMessage(threadId, itemId, newText) {
449
+ this.enhancedDebug(`Editing message ${itemId}: "${newText}"`);
551
450
 
552
- try {
553
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
554
- if (!mqtt || typeof mqtt.publish !== 'function') {
555
- throw new Error('MQTT client not available');
556
- }
557
-
558
- const ctx = clientContext || (0, uuid_1.v4)();
559
- const command = {
560
- action: 'send_item',
561
- thread_id: threadId,
562
- item_type: 'location',
563
- location_id: locationId,
564
- text: text || '',
565
- timestamp: Date.now(),
566
- client_context: ctx,
567
- };
568
-
569
- const json = JSON.stringify(command);
570
- const { compressDeflate } = shared_1;
571
- const payload = await compressDeflate(json);
572
-
573
- this.enhancedDebug(`Publishing location to MQTT`);
574
- const result = await mqtt.publish({
575
- topic: constants_1.Topics.SEND_MESSAGE.id,
576
- qosLevel: 1,
577
- payload: payload,
578
- });
579
-
580
- this.enhancedDebug(`✅ Location sent via MQTT!`);
581
- return result;
582
- } catch (err) {
583
- this.enhancedDebug(`Location send failed: ${err.message}`);
584
- throw err;
585
- }
451
+ const result = await this.sendCommand({
452
+ action: 'edit_item',
453
+ threadId,
454
+ clientContext: (0, uuid_1.v4)(),
455
+ data: {
456
+ item_id: itemId,
457
+ text: newText,
458
+ },
459
+ });
460
+
461
+ this.enhancedDebug(`✅ Message edited via MQTT!`);
462
+ return result;
586
463
  }
587
464
 
588
465
  /**
589
- * Send profile via MQTT
466
+ * Reply to message via MQTT (Quote Reply)
590
467
  */
591
- async sendProfile({ text, userId, threadId, clientContext }) {
592
- this.enhancedDebug(`Sending profile ${userId} to ${threadId} via MQTT`);
468
+ async replyToMessage(threadId, messageId, replyText) {
469
+ this.enhancedDebug(`Replying to ${messageId} in thread ${threadId}: "${replyText}"`);
593
470
 
594
- try {
595
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
596
- if (!mqtt || typeof mqtt.publish !== 'function') {
597
- throw new Error('MQTT client not available');
598
- }
599
-
600
- const ctx = clientContext || (0, uuid_1.v4)();
601
- const command = {
602
- action: 'send_item',
603
- thread_id: threadId,
604
- item_type: 'profile',
605
- user_id: userId,
606
- text: text || '',
607
- timestamp: Date.now(),
608
- client_context: ctx,
609
- };
610
-
611
- const json = JSON.stringify(command);
612
- const { compressDeflate } = shared_1;
613
- const payload = await compressDeflate(json);
614
-
615
- this.enhancedDebug(`Publishing profile to MQTT`);
616
- const result = await mqtt.publish({
617
- topic: constants_1.Topics.SEND_MESSAGE.id,
618
- qosLevel: 1,
619
- payload: payload,
620
- });
621
-
622
- this.enhancedDebug(`✅ Profile sent via MQTT!`);
623
- return result;
624
- } catch (err) {
625
- this.enhancedDebug(`Profile send failed: ${err.message}`);
626
- throw err;
627
- }
471
+ const result = await this.sendItem({
472
+ itemType: 'text',
473
+ threadId,
474
+ clientContext: (0, uuid_1.v4)(),
475
+ data: {
476
+ text: replyText,
477
+ replied_to_item_id: messageId,
478
+ },
479
+ });
480
+
481
+ this.enhancedDebug(`✅ Reply sent via MQTT!`);
482
+ return result;
628
483
  }
629
484
 
630
485
  /**
631
- * Send hashtag via MQTT
486
+ * Add member to thread via MQTT
632
487
  */
633
- async sendHashtag({ text, hashtag, threadId, clientContext }) {
634
- this.enhancedDebug(`Sending hashtag ${hashtag} to ${threadId} via MQTT`);
488
+ async addMemberToThread(threadId, userId) {
489
+ this.enhancedDebug(`Adding user ${userId} to thread ${threadId}`);
635
490
 
636
- try {
637
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
638
- if (!mqtt || typeof mqtt.publish !== 'function') {
639
- throw new Error('MQTT client not available');
640
- }
641
-
642
- const ctx = clientContext || (0, uuid_1.v4)();
643
- const command = {
644
- action: 'send_item',
645
- thread_id: threadId,
646
- item_type: 'hashtag',
647
- hashtag: hashtag,
648
- text: text || '',
649
- timestamp: Date.now(),
650
- client_context: ctx,
651
- };
652
-
653
- const json = JSON.stringify(command);
654
- const { compressDeflate } = shared_1;
655
- const payload = await compressDeflate(json);
656
-
657
- this.enhancedDebug(`Publishing hashtag to MQTT`);
658
- const result = await mqtt.publish({
659
- topic: constants_1.Topics.SEND_MESSAGE.id,
660
- qosLevel: 1,
661
- payload: payload,
662
- });
663
-
664
- this.enhancedDebug(`✅ Hashtag sent via MQTT!`);
665
- return result;
666
- } catch (err) {
667
- this.enhancedDebug(`Hashtag send failed: ${err.message}`);
668
- throw err;
669
- }
491
+ const result = await this.sendCommand({
492
+ action: 'add_users',
493
+ threadId,
494
+ clientContext: (0, uuid_1.v4)(),
495
+ data: {
496
+ user_ids: Array.isArray(userId) ? userId : [userId],
497
+ },
498
+ });
499
+
500
+ this.enhancedDebug(`✅ Member added to thread via MQTT!`);
501
+ return result;
670
502
  }
671
503
 
672
504
  /**
673
- * Send like via MQTT
505
+ * Remove member from thread via MQTT
674
506
  */
675
- async sendLike({ threadId, clientContext }) {
676
- this.enhancedDebug(`Sending like in thread ${threadId} via MQTT`);
507
+ async removeMemberFromThread(threadId, userId) {
508
+ this.enhancedDebug(`Removing user ${userId} from thread ${threadId}`);
677
509
 
678
- try {
679
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
680
- if (!mqtt || typeof mqtt.publish !== 'function') {
681
- throw new Error('MQTT client not available');
682
- }
683
-
684
- const ctx = clientContext || (0, uuid_1.v4)();
685
- const command = {
686
- action: 'send_item',
687
- thread_id: threadId,
688
- item_type: 'like',
689
- timestamp: Date.now(),
690
- client_context: ctx,
691
- };
692
-
693
- const json = JSON.stringify(command);
694
- const { compressDeflate } = shared_1;
695
- const payload = await compressDeflate(json);
696
-
697
- this.enhancedDebug(`Publishing like to MQTT`);
698
- const result = await mqtt.publish({
699
- topic: constants_1.Topics.SEND_MESSAGE.id,
700
- qosLevel: 1,
701
- payload: payload,
702
- });
703
-
704
- this.enhancedDebug(`✅ Like sent via MQTT!`);
705
- return result;
706
- } catch (err) {
707
- this.enhancedDebug(`Like send failed: ${err.message}`);
708
- throw err;
709
- }
510
+ const result = await this.sendCommand({
511
+ action: 'remove_users',
512
+ threadId,
513
+ clientContext: (0, uuid_1.v4)(),
514
+ data: {
515
+ user_ids: Array.isArray(userId) ? userId : [userId],
516
+ },
517
+ });
518
+
519
+ this.enhancedDebug(`✅ Member removed from thread via MQTT!`);
520
+ return result;
710
521
  }
711
522
 
712
523
  /**
713
- * Send user story via MQTT
524
+ * Leave thread via MQTT
714
525
  */
715
- async sendUserStory({ text, storyId, threadId, clientContext }) {
716
- this.enhancedDebug(`Sending story ${storyId} to ${threadId} via MQTT`);
526
+ async leaveThread(threadId) {
527
+ this.enhancedDebug(`Leaving thread ${threadId}`);
717
528
 
718
- try {
719
- const mqtt = this.realtimeClient.mqtt || this.realtimeClient._mqtt;
720
- if (!mqtt || typeof mqtt.publish !== 'function') {
721
- throw new Error('MQTT client not available');
722
- }
723
-
724
- const ctx = clientContext || (0, uuid_1.v4)();
725
- const command = {
726
- action: 'send_item',
727
- thread_id: threadId,
728
- item_type: 'story',
729
- story_id: storyId,
730
- text: text || '',
731
- timestamp: Date.now(),
732
- client_context: ctx,
733
- };
734
-
735
- const json = JSON.stringify(command);
736
- const { compressDeflate } = shared_1;
737
- const payload = await compressDeflate(json);
738
-
739
- this.enhancedDebug(`Publishing story to MQTT`);
740
- const result = await mqtt.publish({
741
- topic: constants_1.Topics.SEND_MESSAGE.id,
742
- qosLevel: 1,
743
- payload: payload,
744
- });
745
-
746
- this.enhancedDebug(`✅ Story sent via MQTT!`);
747
- return result;
748
- } catch (err) {
749
- this.enhancedDebug(`Story send failed: ${err.message}`);
750
- throw err;
751
- }
529
+ const result = await this.sendCommand({
530
+ action: 'leave',
531
+ threadId,
532
+ clientContext: (0, uuid_1.v4)(),
533
+ data: {},
534
+ });
535
+
536
+ this.enhancedDebug(`✅ Left thread via MQTT!`);
537
+ return result;
538
+ }
539
+
540
+ /**
541
+ * Mute thread via MQTT
542
+ */
543
+ async muteThread(threadId, muteUntil = null) {
544
+ this.enhancedDebug(`Muting thread ${threadId}`);
545
+
546
+ const result = await this.sendCommand({
547
+ action: 'mute',
548
+ threadId,
549
+ clientContext: (0, uuid_1.v4)(),
550
+ data: {
551
+ mute_until: muteUntil,
552
+ },
553
+ });
554
+
555
+ this.enhancedDebug(`✅ Thread muted via MQTT!`);
556
+ return result;
557
+ }
558
+
559
+ /**
560
+ * Unmute thread via MQTT
561
+ */
562
+ async unmuteThread(threadId) {
563
+ this.enhancedDebug(`Unmuting thread ${threadId}`);
564
+
565
+ const result = await this.sendCommand({
566
+ action: 'unmute',
567
+ threadId,
568
+ clientContext: (0, uuid_1.v4)(),
569
+ data: {},
570
+ });
571
+
572
+ this.enhancedDebug(`✅ Thread unmuted via MQTT!`);
573
+ return result;
574
+ }
575
+
576
+ /**
577
+ * Update thread title via MQTT
578
+ */
579
+ async updateThreadTitle(threadId, title) {
580
+ this.enhancedDebug(`Updating thread ${threadId} title to: "${title}"`);
581
+
582
+ const result = await this.sendCommand({
583
+ action: 'update_title',
584
+ threadId,
585
+ clientContext: (0, uuid_1.v4)(),
586
+ data: {
587
+ title: title,
588
+ },
589
+ });
590
+
591
+ this.enhancedDebug(`✅ Thread title updated via MQTT!`);
592
+ return result;
593
+ }
594
+
595
+ /**
596
+ * Send link via MQTT
597
+ */
598
+ async sendLink({ link, text, threadId, clientContext }) {
599
+ this.enhancedDebug(`Sending link ${link} to ${threadId}`);
600
+
601
+ const result = await this.sendItem({
602
+ itemType: 'link',
603
+ threadId,
604
+ clientContext,
605
+ data: {
606
+ link_text: text || '',
607
+ // use array (not JSON string) to match instagram_mqtt expectations
608
+ link_urls: [link],
609
+ },
610
+ });
611
+
612
+ this.enhancedDebug(`✅ Link sent via MQTT!`);
613
+ return result;
614
+ }
615
+
616
+ /**
617
+ * Send animated media (GIF/sticker) via MQTT
618
+ */
619
+ async sendAnimatedMedia({ id, isSticker, threadId, clientContext }) {
620
+ this.enhancedDebug(`Sending animated media ${id} to ${threadId}`);
621
+
622
+ const result = await this.sendItem({
623
+ itemType: 'animated_media',
624
+ threadId,
625
+ clientContext,
626
+ data: {
627
+ id: id,
628
+ is_sticker: isSticker || false,
629
+ },
630
+ });
631
+
632
+ this.enhancedDebug(`✅ Animated media sent via MQTT!`);
633
+ return result;
634
+ }
635
+
636
+ /**
637
+ * Send voice message via MQTT (after upload)
638
+ */
639
+ async sendVoice({ uploadId, waveform, waveformSamplingFrequencyHz, threadId, clientContext }) {
640
+ this.enhancedDebug(`Sending voice ${uploadId} to ${threadId}`);
641
+
642
+ const result = await this.sendItem({
643
+ itemType: 'voice_media',
644
+ threadId,
645
+ clientContext,
646
+ data: {
647
+ upload_id: uploadId,
648
+ waveform: waveform,
649
+ waveform_sampling_frequency_hz: waveformSamplingFrequencyHz || 10,
650
+ },
651
+ });
652
+
653
+ this.enhancedDebug(`✅ Voice sent via MQTT!`);
654
+ return result;
752
655
  }
753
656
 
754
657
  /**
755
658
  * Send photo via Realtime (Upload + Broadcast)
756
- * This method uploads the photo first, then broadcasts it to the thread
757
- *
758
- * @param {Object} options - Photo sending options
759
- * @param {Buffer} options.photoBuffer - Image buffer (JPEG/PNG)
760
- * @param {string} options.threadId - Thread ID to send to
761
- * @param {string} [options.caption] - Optional caption
762
- * @param {string} [options.mimeType='image/jpeg'] - MIME type
763
- * @param {string} [options.clientContext] - Optional client context
764
659
  */
765
660
  async sendPhotoViaRealtime({ photoBuffer, threadId, caption = '', mimeType = 'image/jpeg', clientContext }) {
766
661
  this.enhancedDebug(`Sending photo to thread ${threadId} via Realtime`);
767
662
 
768
663
  try {
769
- // Validate inputs
770
664
  if (!photoBuffer || !Buffer.isBuffer(photoBuffer) || photoBuffer.length === 0) {
771
665
  throw new Error('photoBuffer must be a non-empty Buffer');
772
666
  }
@@ -774,13 +668,11 @@ class EnhancedDirectCommands {
774
668
  throw new Error('threadId is required');
775
669
  }
776
670
 
777
- // Get the ig client from realtime client
778
671
  const ig = this.realtimeClient.ig;
779
672
  if (!ig || !ig.request) {
780
673
  throw new Error('Instagram client not available. Make sure you are logged in.');
781
674
  }
782
675
 
783
- // Step 1: Upload photo using rupload endpoint
784
676
  this.enhancedDebug(`Step 1: Uploading photo (${photoBuffer.length} bytes)...`);
785
677
 
786
678
  const uploadId = Date.now().toString();
@@ -824,11 +716,10 @@ class EnhancedDirectCommands {
824
716
  }
825
717
  this.enhancedDebug(`✅ Photo uploaded! upload_id: ${serverUploadId}`);
826
718
  } catch (uploadErr) {
827
- this.enhancedDebug(`Upload error: ${uploadErr.message}`);
828
- throw new Error(`Photo upload failed: ${uploadErr.message}`);
719
+ this.enhancedDebug(`Upload error: ${uploadErr && uploadErr.message ? uploadErr.message : String(uploadErr)}`);
720
+ throw new Error(`Photo upload failed: ${uploadErr && uploadErr.message ? uploadErr.message : String(uploadErr)}`);
829
721
  }
830
722
 
831
- // Step 2: Broadcast the uploaded photo to the thread
832
723
  this.enhancedDebug(`Step 2: Broadcasting photo to thread ${threadId}...`);
833
724
 
834
725
  const broadcastForm = {
@@ -851,18 +742,18 @@ class EnhancedDirectCommands {
851
742
  this.enhancedDebug(`✅ Photo sent successfully to thread ${threadId}!`);
852
743
  return broadcastResponse;
853
744
  } catch (broadcastErr) {
854
- this.enhancedDebug(`Broadcast error: ${broadcastErr.message}`);
855
- throw new Error(`Photo broadcast failed: ${broadcastErr.message}`);
745
+ this.enhancedDebug(`Broadcast error: ${broadcastErr && broadcastErr.message ? broadcastErr.message : String(broadcastErr)}`);
746
+ throw new Error(`Photo broadcast failed: ${broadcastErr && broadcastErr.message ? broadcastErr.message : String(broadcastErr)}`);
856
747
  }
857
748
 
858
749
  } catch (err) {
859
- this.enhancedDebug(`sendPhotoViaRealtime failed: ${err.message}`);
750
+ this.enhancedDebug(`sendPhotoViaRealtime failed: ${err && err.message ? err.message : String(err)}`);
860
751
  throw err;
861
752
  }
862
753
  }
863
754
 
864
755
  /**
865
- * Alias for sendPhotoViaRealtime (for compatibility)
756
+ * Alias for sendPhotoViaRealtime
866
757
  */
867
758
  async sendPhoto(options) {
868
759
  return this.sendPhotoViaRealtime(options);
@@ -870,21 +761,11 @@ class EnhancedDirectCommands {
870
761
 
871
762
  /**
872
763
  * Send video via Realtime (Upload + Broadcast)
873
- *
874
- * @param {Object} options - Video sending options
875
- * @param {Buffer} options.videoBuffer - Video buffer (MP4)
876
- * @param {string} options.threadId - Thread ID to send to
877
- * @param {string} [options.caption] - Optional caption
878
- * @param {number} [options.duration] - Video duration in seconds
879
- * @param {number} [options.width] - Video width
880
- * @param {number} [options.height] - Video height
881
- * @param {string} [options.clientContext] - Optional client context
882
764
  */
883
765
  async sendVideoViaRealtime({ videoBuffer, threadId, caption = '', duration = 0, width = 720, height = 1280, clientContext }) {
884
766
  this.enhancedDebug(`Sending video to thread ${threadId} via Realtime`);
885
767
 
886
768
  try {
887
- // Validate inputs
888
769
  if (!videoBuffer || !Buffer.isBuffer(videoBuffer) || videoBuffer.length === 0) {
889
770
  throw new Error('videoBuffer must be a non-empty Buffer');
890
771
  }
@@ -892,13 +773,11 @@ class EnhancedDirectCommands {
892
773
  throw new Error('threadId is required');
893
774
  }
894
775
 
895
- // Get the ig client from realtime client
896
776
  const ig = this.realtimeClient.ig;
897
777
  if (!ig || !ig.request) {
898
778
  throw new Error('Instagram client not available. Make sure you are logged in.');
899
779
  }
900
780
 
901
- // Step 1: Upload video using rupload endpoint
902
781
  this.enhancedDebug(`Step 1: Uploading video (${videoBuffer.length} bytes)...`);
903
782
 
904
783
  const uploadId = Date.now().toString();
@@ -906,7 +785,7 @@ class EnhancedDirectCommands {
906
785
 
907
786
  const ruploadParams = {
908
787
  upload_id: uploadId,
909
- media_type: 2, // 2 = video
788
+ media_type: 2,
910
789
  xsharing_user_ids: JSON.stringify([]),
911
790
  upload_media_duration_ms: Math.round(duration * 1000),
912
791
  upload_media_width: width,
@@ -939,11 +818,10 @@ class EnhancedDirectCommands {
939
818
  }
940
819
  this.enhancedDebug(`✅ Video uploaded! upload_id: ${serverUploadId}`);
941
820
  } catch (uploadErr) {
942
- this.enhancedDebug(`Video upload error: ${uploadErr.message}`);
943
- throw new Error(`Video upload failed: ${uploadErr.message}`);
821
+ this.enhancedDebug(`Video upload error: ${uploadErr && uploadErr.message ? uploadErr.message : String(uploadErr)}`);
822
+ throw new Error(`Video upload failed: ${uploadErr && uploadErr.message ? uploadErr.message : String(uploadErr)}`);
944
823
  }
945
824
 
946
- // Step 2: Broadcast the uploaded video to the thread
947
825
  this.enhancedDebug(`Step 2: Broadcasting video to thread ${threadId}...`);
948
826
 
949
827
  const broadcastForm = {
@@ -967,21 +845,215 @@ class EnhancedDirectCommands {
967
845
  this.enhancedDebug(`✅ Video sent successfully to thread ${threadId}!`);
968
846
  return broadcastResponse;
969
847
  } catch (broadcastErr) {
970
- this.enhancedDebug(`Video broadcast error: ${broadcastErr.message}`);
971
- throw new Error(`Video broadcast failed: ${broadcastErr.message}`);
848
+ this.enhancedDebug(`Video broadcast error: ${broadcastErr && broadcastErr.message ? broadcastErr.message : String(broadcastErr)}`);
849
+ throw new Error(`Video broadcast failed: ${broadcastErr && broadcastErr.message ? broadcastErr.message : String(broadcastErr)}`);
972
850
  }
973
851
 
974
852
  } catch (err) {
975
- this.enhancedDebug(`sendVideoViaRealtime failed: ${err.message}`);
853
+ this.enhancedDebug(`sendVideoViaRealtime failed: ${err && err.message ? err.message : String(err)}`);
976
854
  throw err;
977
855
  }
978
856
  }
979
857
 
980
858
  /**
981
- * Alias for sendVideoViaRealtime (for compatibility)
859
+ * Alias for sendVideoViaRealtime
982
860
  */
983
861
  async sendVideo(options) {
984
862
  return this.sendVideoViaRealtime(options);
985
863
  }
864
+
865
+ /**
866
+ * Approve pending thread via MQTT
867
+ */
868
+ async approveThread(threadId) {
869
+ this.enhancedDebug(`Approving thread ${threadId}`);
870
+
871
+ const result = await this.sendCommand({
872
+ action: 'approve',
873
+ threadId,
874
+ clientContext: (0, uuid_1.v4)(),
875
+ data: {},
876
+ });
877
+
878
+ this.enhancedDebug(`✅ Thread approved via MQTT!`);
879
+ return result;
880
+ }
881
+
882
+ /**
883
+ * Decline pending thread via MQTT
884
+ */
885
+ async declineThread(threadId) {
886
+ this.enhancedDebug(`Declining thread ${threadId}`);
887
+
888
+ const result = await this.sendCommand({
889
+ action: 'decline',
890
+ threadId,
891
+ clientContext: (0, uuid_1.v4)(),
892
+ data: {},
893
+ });
894
+
895
+ this.enhancedDebug(`✅ Thread declined via MQTT!`);
896
+ return result;
897
+ }
898
+
899
+ /**
900
+ * Block user in thread via MQTT
901
+ */
902
+ async blockUserInThread(threadId, userId) {
903
+ this.enhancedDebug(`Blocking user ${userId} in thread ${threadId}`);
904
+
905
+ const result = await this.sendCommand({
906
+ action: 'block',
907
+ threadId,
908
+ clientContext: (0, uuid_1.v4)(),
909
+ data: {
910
+ user_id: userId,
911
+ },
912
+ });
913
+
914
+ this.enhancedDebug(`✅ User blocked in thread via MQTT!`);
915
+ return result;
916
+ }
917
+
918
+ /**
919
+ * Report thread via MQTT
920
+ */
921
+ async reportThread(threadId, reason) {
922
+ this.enhancedDebug(`Reporting thread ${threadId}`);
923
+
924
+ const result = await this.sendCommand({
925
+ action: 'report',
926
+ threadId,
927
+ clientContext: (0, uuid_1.v4)(),
928
+ data: {
929
+ reason: reason || 'spam',
930
+ },
931
+ });
932
+
933
+ this.enhancedDebug(`✅ Thread reported via MQTT!`);
934
+ return result;
935
+ }
936
+
937
+ /**
938
+ * Remove reaction via MQTT
939
+ */
940
+ async removeReaction({ itemId, threadId, clientContext }) {
941
+ this.enhancedDebug(`Removing reaction from message ${itemId}`);
942
+
943
+ const result = await this.sendItem({
944
+ itemType: 'reaction',
945
+ threadId,
946
+ clientContext,
947
+ data: {
948
+ item_id: itemId,
949
+ node_type: 'item',
950
+ reaction_type: 'like',
951
+ reaction_status: 'deleted',
952
+ },
953
+ });
954
+
955
+ this.enhancedDebug(`✅ Reaction removed via MQTT!`);
956
+ return result;
957
+ }
958
+
959
+ /**
960
+ * Send disappearing photo via MQTT
961
+ */
962
+ async sendDisappearingPhoto({ uploadId, threadId, viewMode = 'once', clientContext }) {
963
+ this.enhancedDebug(`Sending disappearing photo to ${threadId}`);
964
+
965
+ const result = await this.sendItem({
966
+ itemType: 'expiring_media_message',
967
+ threadId,
968
+ clientContext,
969
+ data: {
970
+ upload_id: uploadId,
971
+ view_mode: viewMode,
972
+ allow_replay: viewMode === 'replayable',
973
+ },
974
+ });
975
+
976
+ this.enhancedDebug(`✅ Disappearing photo sent via MQTT!`);
977
+ return result;
978
+ }
979
+
980
+ /**
981
+ * Send disappearing video via MQTT
982
+ */
983
+ async sendDisappearingVideo({ uploadId, threadId, viewMode = 'once', clientContext }) {
984
+ this.enhancedDebug(`Sending disappearing video to ${threadId}`);
985
+
986
+ const result = await this.sendItem({
987
+ itemType: 'expiring_media_message',
988
+ threadId,
989
+ clientContext,
990
+ data: {
991
+ upload_id: uploadId,
992
+ view_mode: viewMode,
993
+ allow_replay: viewMode === 'replayable',
994
+ media_type: 2,
995
+ },
996
+ });
997
+
998
+ this.enhancedDebug(`✅ Disappearing video sent via MQTT!`);
999
+ return result;
1000
+ }
1001
+
1002
+ /**
1003
+ * Mark visual message as seen via MQTT
1004
+ */
1005
+ async markVisualMessageSeen({ threadId, itemId, clientContext }) {
1006
+ this.enhancedDebug(`Marking visual message ${itemId} as seen`);
1007
+
1008
+ const result = await this.sendCommand({
1009
+ action: 'mark_visual_item_seen',
1010
+ threadId,
1011
+ clientContext: clientContext || (0, uuid_1.v4)(),
1012
+ data: {
1013
+ item_id: itemId,
1014
+ },
1015
+ });
1016
+
1017
+ this.enhancedDebug(`✅ Visual message marked as seen via MQTT!`);
1018
+ return result;
1019
+ }
1020
+
1021
+ /**
1022
+ * Screenshot notification via MQTT
1023
+ */
1024
+ async sendScreenshotNotification({ threadId, itemId, clientContext }) {
1025
+ this.enhancedDebug(`Sending screenshot notification for ${itemId}`);
1026
+
1027
+ const result = await this.sendCommand({
1028
+ action: 'screenshot_notification',
1029
+ threadId,
1030
+ clientContext: clientContext || (0, uuid_1.v4)(),
1031
+ data: {
1032
+ item_id: itemId,
1033
+ },
1034
+ });
1035
+
1036
+ this.enhancedDebug(`✅ Screenshot notification sent via MQTT!`);
1037
+ return result;
1038
+ }
1039
+
1040
+ /**
1041
+ * Replay notification via MQTT
1042
+ */
1043
+ async sendReplayNotification({ threadId, itemId, clientContext }) {
1044
+ this.enhancedDebug(`Sending replay notification for ${itemId}`);
1045
+
1046
+ const result = await this.sendCommand({
1047
+ action: 'replay_notification',
1048
+ threadId,
1049
+ clientContext: clientContext || (0, uuid_1.v4)(),
1050
+ data: {
1051
+ item_id: itemId,
1052
+ },
1053
+ });
1054
+
1055
+ this.enhancedDebug(`✅ Replay notification sent via MQTT!`);
1056
+ return result;
1057
+ }
986
1058
  }
987
- exports.EnhancedDirectCommands = EnhancedDirectCommands;
1059
+ exports.EnhancedDirectCommands = EnhancedDirectCommands;