nodejs-insta-private-api-mqtt 1.3.40 → 1.3.41
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.
- package/README.md +161 -0
- package/dist/realtime/commands/enhanced.direct.commands.js +256 -112
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -870,3 +870,164 @@ MIT
|
|
|
870
870
|
For issues, bugs, or feature requests: https://github.com/Kunboruto20/nodejs-insta-private-api/issues
|
|
871
871
|
|
|
872
872
|
Documentation: https://github.com/Kunboruto20/nodejs-insta-private-api
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
---
|
|
876
|
+
## Enhanced Location Usage — Practical Examples (English)
|
|
877
|
+
|
|
878
|
+
The `EnhancedDirectCommands` class (see `enhanced.direct.commands.js`) implements robust location sending for Instagram Direct by trying **story-with-location-sticker → share story to thread → fallback to link**. Below are ready-to-copy examples showing how to use the location-related methods and payloads exposed by the class.
|
|
879
|
+
|
|
880
|
+
> These examples assume:
|
|
881
|
+
> - `realtime` is an instance of `RealtimeClient`.
|
|
882
|
+
> - `realtime.directCommands` is an instance of `EnhancedDirectCommands`.
|
|
883
|
+
> - You have a valid `threadId` (target DM thread).
|
|
884
|
+
> - `realtime.ig` exists when examples require publishing a story via the private IG client.
|
|
885
|
+
|
|
886
|
+
### 1) Send a location when you already have a `venue` object (recommended)
|
|
887
|
+
|
|
888
|
+
```javascript
|
|
889
|
+
// venue shape expected by sendLocation:
|
|
890
|
+
// { id, name, address, lat, lng, facebook_places_id, external_source }
|
|
891
|
+
const venue = {
|
|
892
|
+
id: "213385402",
|
|
893
|
+
name: "McDonald's Unirii",
|
|
894
|
+
address: "Piața Unirii, Bucharest",
|
|
895
|
+
lat: 44.4268,
|
|
896
|
+
lng: 26.1025,
|
|
897
|
+
facebook_places_id: "213385402",
|
|
898
|
+
external_source: "facebook_places"
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
await realtime.directCommands.sendLocation({
|
|
902
|
+
threadId: "340282366841710300949128114477782749726",
|
|
903
|
+
venue,
|
|
904
|
+
text: "Meet me here at 18:00"
|
|
905
|
+
});
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
**What happens:**
|
|
909
|
+
1. The method attempts to publish a Story with a location sticker using `realtime.ig.publish.story`.
|
|
910
|
+
2. If the Story publish succeeds and a `storyId` is returned, `sendUserStory` (reel_share) is used to share the story to the thread.
|
|
911
|
+
3. If either step fails, the method falls back to sending a link to `https://www.instagram.com/explore/locations/{placeId}/` via `itemType: 'link'`.
|
|
912
|
+
|
|
913
|
+
---
|
|
914
|
+
|
|
915
|
+
### 2) Search for a place (instagram private search) and send it
|
|
916
|
+
|
|
917
|
+
Use `searchAndSendLocation()` when you only have a search query or coordinates:
|
|
918
|
+
|
|
919
|
+
```javascript
|
|
920
|
+
await realtime.directCommands.searchAndSendLocation({
|
|
921
|
+
threadId: "340282366841710300949128114477782749726",
|
|
922
|
+
query: "Starbucks Piata Unirii",
|
|
923
|
+
lat: 44.4268,
|
|
924
|
+
lng: 26.1025
|
|
925
|
+
});
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
This helper calls Instagram's `/fbsearch/places/` private endpoint (via `realtime.ig.request`) and then normalizes the first result into the `venue` shape before calling `sendLocation()`.
|
|
929
|
+
|
|
930
|
+
---
|
|
931
|
+
|
|
932
|
+
### 3) Build a location sticker manually & publish story (advanced)
|
|
933
|
+
|
|
934
|
+
If you want direct control over the sticker object or to publish your own image, you can use `createLocationStickerFromVenue()` and `realtime.ig.publish.story()` directly:
|
|
935
|
+
|
|
936
|
+
```javascript
|
|
937
|
+
const venue = {
|
|
938
|
+
id: "213385402",
|
|
939
|
+
name: "McDonald's Unirii",
|
|
940
|
+
address: "Piața Unirii, Bucharest",
|
|
941
|
+
lat: 44.4268,
|
|
942
|
+
lng: 26.1025,
|
|
943
|
+
facebook_places_id: "213385402"
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
// create sticker compatible with publish.story helpers
|
|
947
|
+
const sticker = realtime.directCommands.createLocationStickerFromVenue(venue);
|
|
948
|
+
|
|
949
|
+
// create a tiny placeholder image (1x1 PNG) or your real photo buffer
|
|
950
|
+
const SINGLE_PIXEL_PNG_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=";
|
|
951
|
+
const photoBuffer = Buffer.from(SINGLE_PIXEL_PNG_BASE64, 'base64');
|
|
952
|
+
|
|
953
|
+
// publish story with the sticker (if realtime.ig.publish.story exists)
|
|
954
|
+
const publishResult = await realtime.ig.publish.story({
|
|
955
|
+
file: photoBuffer,
|
|
956
|
+
stickers: [sticker]
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
// try to resolve returned story id and then share it
|
|
960
|
+
const storyId = publishResult?.media?.pk || publishResult?.item_id || publishResult?.upload_id;
|
|
961
|
+
if (storyId) {
|
|
962
|
+
await realtime.directCommands.sendUserStory({
|
|
963
|
+
threadId: "340282366841710300949128114477782749726",
|
|
964
|
+
storyId,
|
|
965
|
+
text: "Location for tonight"
|
|
966
|
+
});
|
|
967
|
+
} else {
|
|
968
|
+
// fallback: send explore link manually
|
|
969
|
+
await realtime.directCommands.sendLink({
|
|
970
|
+
threadId: "340282366841710300949128114477782749726",
|
|
971
|
+
link: `https://www.instagram.com/explore/locations/${venue.facebook_places_id || venue.id}/`,
|
|
972
|
+
text: venue.name
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
---
|
|
978
|
+
|
|
979
|
+
### 4) Force sending the explore-location link (explicit fallback)
|
|
980
|
+
|
|
981
|
+
If you don't want to publish a story and only need the location link in DM:
|
|
982
|
+
|
|
983
|
+
```javascript
|
|
984
|
+
const placeId = "213385402";
|
|
985
|
+
await realtime.directCommands.sendLink({
|
|
986
|
+
threadId: "340282366841710300949128114477782749726",
|
|
987
|
+
link: `https://www.instagram.com/explore/locations/${placeId}/`,
|
|
988
|
+
text: "Meet here"
|
|
989
|
+
});
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
---
|
|
993
|
+
|
|
994
|
+
### 5) Error handling & debug tips
|
|
995
|
+
|
|
996
|
+
```javascript
|
|
997
|
+
try {
|
|
998
|
+
await realtime.directCommands.sendLocation({ threadId, venue, text: "See you" });
|
|
999
|
+
console.log("Location sent!");
|
|
1000
|
+
} catch (err) {
|
|
1001
|
+
console.error("Failed to send location:", err);
|
|
1002
|
+
// fallback to explicit link if needed
|
|
1003
|
+
await realtime.directCommands.sendLink({
|
|
1004
|
+
threadId,
|
|
1005
|
+
link: `https://www.instagram.com/explore/locations/${venue.facebook_places_id || venue.id}/`,
|
|
1006
|
+
text: venue.name || "Location"
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
If you need verbose logs, enable debug for the realtime/enhanced module:
|
|
1012
|
+
|
|
1013
|
+
```bash
|
|
1014
|
+
# in your environment (example)
|
|
1015
|
+
DEBUG="realtime:enhanced-commands" node your_bot.js
|
|
1016
|
+
# or to see broader realtime logs
|
|
1017
|
+
DEBUG="realtime:*" node your_bot.js
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
---
|
|
1021
|
+
|
|
1022
|
+
### 6) Quick checklist (what the library needs to make story-with-sticker work)
|
|
1023
|
+
|
|
1024
|
+
- `realtime.ig` must exist and expose `publish.story(...)` (a private client publish helper).
|
|
1025
|
+
- The `venue` must include either `facebook_places_id` or `id`.
|
|
1026
|
+
- If `realtime.ig.publish.story` is unavailable or Instagram rejects the sticker, the library **automatically falls back** to sending a DM link to the Explore locations page.
|
|
1027
|
+
|
|
1028
|
+
---
|
|
1029
|
+
|
|
1030
|
+
## End of Location Examples
|
|
1031
|
+
|
|
1032
|
+
These examples are appended to the original README in order to keep the whole original file intact while adding clear, English examples for location flows.
|
|
1033
|
+
|
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EnhancedDirectCommands = void 0;
|
|
4
|
+
|
|
4
5
|
const shared_1 = require("../../shared");
|
|
5
6
|
const uuid_1 = require("uuid");
|
|
6
7
|
const constants_1 = require("../../constants");
|
|
7
8
|
const thrift_1 = require("../../thrift");
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
11
|
+
* EnhancedDirectCommands
|
|
12
|
+
*
|
|
13
|
+
* - Full, self-contained class that publishes correctly-formatted payloads to Instagram's
|
|
14
|
+
* Direct MQTT (Thrift + compressed payloads).
|
|
15
|
+
* - Includes a robust sendLocation implementation that sends a nested `location` object,
|
|
16
|
+
* and a fallback to sending a link (which reliably appears in chat).
|
|
17
|
+
*
|
|
18
|
+
* IMPORTANT:
|
|
19
|
+
* - Instagram's internal protocol is not public. This implementation matches patterns
|
|
20
|
+
* observed in reverse-engineered clients. Even so, Instagram may silently reject
|
|
21
|
+
* location messages if server-side validation's schema differs. If a message is
|
|
22
|
+
* rejected, fallback sends a link to the location which is visible to users.
|
|
12
23
|
*/
|
|
13
24
|
class EnhancedDirectCommands {
|
|
14
25
|
constructor(client) {
|
|
15
26
|
this.realtimeClient = client;
|
|
16
27
|
this.enhancedDebug = (0, shared_1.debugChannel)('realtime', 'enhanced-commands');
|
|
17
|
-
|
|
28
|
+
|
|
18
29
|
// Foreground state config for Thrift encoding (matching instagram_mqtt)
|
|
19
30
|
this.foregroundStateConfig = [
|
|
20
31
|
thrift_1.ThriftDescriptors.boolean('inForegroundApp', 1),
|
|
@@ -29,10 +40,10 @@ class EnhancedDirectCommands {
|
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
/**
|
|
32
|
-
*
|
|
43
|
+
* Attempt to locate the MQTT client object on the realtime client.
|
|
44
|
+
* Many wrappers expose mqtt under different property names.
|
|
33
45
|
*/
|
|
34
46
|
getMqtt() {
|
|
35
|
-
// Try several known property names for mqtt client (some libs/wrappers expose differently)
|
|
36
47
|
const candidates = [
|
|
37
48
|
'mqtt',
|
|
38
49
|
'_mqtt',
|
|
@@ -43,7 +54,6 @@ class EnhancedDirectCommands {
|
|
|
43
54
|
];
|
|
44
55
|
let mqtt = null;
|
|
45
56
|
for (const key of candidates) {
|
|
46
|
-
// eslint-disable-next-line no-prototype-builtins
|
|
47
57
|
if (this.realtimeClient && Object.prototype.hasOwnProperty.call(this.realtimeClient, key) && this.realtimeClient[key]) {
|
|
48
58
|
mqtt = this.realtimeClient[key];
|
|
49
59
|
break;
|
|
@@ -67,7 +77,6 @@ class EnhancedDirectCommands {
|
|
|
67
77
|
* - mqtt.publish(topic, payload, { qos }, cb)
|
|
68
78
|
*/
|
|
69
79
|
async publishToMqtt(mqtt, publishObj) {
|
|
70
|
-
// publishObj: { topic, payload, qosLevel }
|
|
71
80
|
const topic = publishObj.topic;
|
|
72
81
|
const payload = publishObj.payload;
|
|
73
82
|
const qosLevel = typeof publishObj.qosLevel !== 'undefined' ? publishObj.qosLevel : 1;
|
|
@@ -132,10 +141,10 @@ class EnhancedDirectCommands {
|
|
|
132
141
|
*/
|
|
133
142
|
async sendForegroundState(state) {
|
|
134
143
|
this.enhancedDebug(`Updated foreground state: ${JSON.stringify(state)}`);
|
|
135
|
-
|
|
144
|
+
|
|
136
145
|
try {
|
|
137
146
|
const mqtt = this.getMqtt();
|
|
138
|
-
|
|
147
|
+
|
|
139
148
|
const thriftBuffer = (0, thrift_1.thriftWriteFromObject)(state, this.foregroundStateConfig);
|
|
140
149
|
const concat = Buffer.concat([
|
|
141
150
|
Buffer.alloc(1, 0),
|
|
@@ -144,18 +153,18 @@ class EnhancedDirectCommands {
|
|
|
144
153
|
|
|
145
154
|
// ensure we pass Buffer to compressDeflate
|
|
146
155
|
const payload = await (0, shared_1.compressDeflate)(concat);
|
|
147
|
-
|
|
156
|
+
|
|
148
157
|
const result = await this.publishToMqtt(mqtt, {
|
|
149
158
|
topic: constants_1.Topics.FOREGROUND_STATE.id,
|
|
150
159
|
payload: payload,
|
|
151
160
|
qosLevel: 1,
|
|
152
161
|
});
|
|
153
|
-
|
|
162
|
+
|
|
154
163
|
// Update keepAlive if provided
|
|
155
164
|
if ((0, shared_1.notUndefined)(state.keepAliveTimeout)) {
|
|
156
165
|
mqtt.keepAlive = state.keepAliveTimeout;
|
|
157
166
|
}
|
|
158
|
-
|
|
167
|
+
|
|
159
168
|
this.enhancedDebug(`✅ Foreground state updated via MQTT!`);
|
|
160
169
|
return result;
|
|
161
170
|
} catch (err) {
|
|
@@ -166,15 +175,16 @@ class EnhancedDirectCommands {
|
|
|
166
175
|
|
|
167
176
|
/**
|
|
168
177
|
* Base command sender (matching instagram_mqtt format)
|
|
178
|
+
* It encodes the command as JSON, compresses, and publishes to SEND_MESSAGE topic.
|
|
169
179
|
*/
|
|
170
180
|
async sendCommand({ action, data, threadId, clientContext }) {
|
|
171
181
|
try {
|
|
172
182
|
const mqtt = this.getMqtt();
|
|
173
|
-
|
|
183
|
+
|
|
174
184
|
if (clientContext) {
|
|
175
185
|
data.client_context = clientContext;
|
|
176
186
|
}
|
|
177
|
-
|
|
187
|
+
|
|
178
188
|
const json = JSON.stringify({
|
|
179
189
|
action,
|
|
180
190
|
thread_id: threadId,
|
|
@@ -183,7 +193,7 @@ class EnhancedDirectCommands {
|
|
|
183
193
|
|
|
184
194
|
// ensure Buffer (some compress implementations expect Buffer)
|
|
185
195
|
const payload = await (0, shared_1.compressDeflate)(Buffer.from(json));
|
|
186
|
-
|
|
196
|
+
|
|
187
197
|
return this.publishToMqtt(mqtt, {
|
|
188
198
|
topic: constants_1.Topics.SEND_MESSAGE.id,
|
|
189
199
|
qosLevel: 1,
|
|
@@ -211,11 +221,11 @@ class EnhancedDirectCommands {
|
|
|
211
221
|
}
|
|
212
222
|
|
|
213
223
|
/**
|
|
214
|
-
* Send text via MQTT
|
|
224
|
+
* Send text via MQTT
|
|
215
225
|
*/
|
|
216
226
|
async sendText({ text, clientContext, threadId }) {
|
|
217
227
|
this.enhancedDebug(`Sending text to ${threadId}: "${text}"`);
|
|
218
|
-
|
|
228
|
+
|
|
219
229
|
const result = await this.sendItem({
|
|
220
230
|
itemType: 'text',
|
|
221
231
|
threadId,
|
|
@@ -224,7 +234,7 @@ class EnhancedDirectCommands {
|
|
|
224
234
|
text,
|
|
225
235
|
},
|
|
226
236
|
});
|
|
227
|
-
|
|
237
|
+
|
|
228
238
|
this.enhancedDebug(`✅ Text sent via MQTT!`);
|
|
229
239
|
return result;
|
|
230
240
|
}
|
|
@@ -241,11 +251,11 @@ class EnhancedDirectCommands {
|
|
|
241
251
|
}
|
|
242
252
|
|
|
243
253
|
/**
|
|
244
|
-
* Send hashtag via MQTT
|
|
254
|
+
* Send hashtag via MQTT
|
|
245
255
|
*/
|
|
246
256
|
async sendHashtag({ text, threadId, hashtag, clientContext }) {
|
|
247
257
|
this.enhancedDebug(`Sending hashtag #${hashtag} to ${threadId}`);
|
|
248
|
-
|
|
258
|
+
|
|
249
259
|
const result = await this.sendItem({
|
|
250
260
|
itemType: 'hashtag',
|
|
251
261
|
threadId,
|
|
@@ -256,55 +266,186 @@ class EnhancedDirectCommands {
|
|
|
256
266
|
item_id: hashtag,
|
|
257
267
|
},
|
|
258
268
|
});
|
|
259
|
-
|
|
269
|
+
|
|
260
270
|
this.enhancedDebug(`✅ Hashtag sent via MQTT!`);
|
|
261
271
|
return result;
|
|
262
272
|
}
|
|
263
273
|
|
|
264
274
|
/**
|
|
265
|
-
* Send like via MQTT
|
|
275
|
+
* Send like via MQTT
|
|
266
276
|
*/
|
|
267
277
|
async sendLike({ threadId, clientContext }) {
|
|
268
278
|
this.enhancedDebug(`Sending like in thread ${threadId}`);
|
|
269
|
-
|
|
279
|
+
|
|
270
280
|
const result = await this.sendItem({
|
|
271
281
|
itemType: 'like',
|
|
272
282
|
threadId,
|
|
273
283
|
clientContext,
|
|
274
284
|
data: {},
|
|
275
285
|
});
|
|
276
|
-
|
|
286
|
+
|
|
277
287
|
this.enhancedDebug(`✅ Like sent via MQTT!`);
|
|
278
288
|
return result;
|
|
279
289
|
}
|
|
280
290
|
|
|
281
291
|
/**
|
|
282
|
-
* Send location via MQTT (
|
|
292
|
+
* Send location via MQTT (enhanced)
|
|
293
|
+
*
|
|
294
|
+
* Accepts:
|
|
295
|
+
* - threadId (string)
|
|
296
|
+
* - clientContext (optional)
|
|
297
|
+
* - venue (object) - should include at minimum:
|
|
298
|
+
* { id, name, address, lat, lng, facebook_places_id, external_source }
|
|
299
|
+
*
|
|
300
|
+
* The function tries to send a nested `location` object inside the item payload:
|
|
301
|
+
* {
|
|
302
|
+
* item_type: 'location',
|
|
303
|
+
* location: { lat, lng, name, address, external_source, facebook_places_id },
|
|
304
|
+
* text: '' // optional text
|
|
305
|
+
* }
|
|
306
|
+
*
|
|
307
|
+
* If the venue is missing required fields, it falls back to sending a link that points
|
|
308
|
+
* to the explore/locations/<id> page (which reliably appears in the chat).
|
|
309
|
+
*
|
|
310
|
+
* NOTE: Instagram expects the payload to be Thrift-encoded + compressed for MQTT.
|
|
283
311
|
*/
|
|
284
|
-
async sendLocation({
|
|
285
|
-
this.enhancedDebug(`
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
312
|
+
async sendLocation({ threadId, clientContext, venue, text = '' }) {
|
|
313
|
+
this.enhancedDebug(`Attempting to send location to ${threadId}. Venue: ${venue ? JSON.stringify(venue) : 'none'}`);
|
|
314
|
+
|
|
315
|
+
// Basic validation - if we don't have lat/lng and id, fallback to link or error
|
|
316
|
+
const hasCoords = venue && typeof venue.lat === 'number' && typeof venue.lng === 'number';
|
|
317
|
+
const hasId = venue && (venue.facebook_places_id || venue.id);
|
|
318
|
+
|
|
319
|
+
// Build the "location" nested object expected semantically
|
|
320
|
+
const locationObj = hasCoords ? {
|
|
321
|
+
lat: Number(venue.lat),
|
|
322
|
+
lng: Number(venue.lng),
|
|
323
|
+
name: venue.name || '',
|
|
324
|
+
address: venue.address || '',
|
|
325
|
+
external_source: venue.external_source || 'facebook_places',
|
|
326
|
+
facebook_places_id: venue.facebook_places_id || String(venue.id || ''),
|
|
327
|
+
} : null;
|
|
328
|
+
|
|
329
|
+
// If we have a good location object, attempt to send it
|
|
330
|
+
if (locationObj && hasId) {
|
|
331
|
+
try {
|
|
332
|
+
const result = await this.sendItem({
|
|
333
|
+
itemType: 'location',
|
|
334
|
+
threadId,
|
|
335
|
+
clientContext: clientContext || (0, uuid_1.v4)(),
|
|
336
|
+
data: {
|
|
337
|
+
text: text || '',
|
|
338
|
+
// Put the nested `location` object in the payload as many reverse engineered
|
|
339
|
+
// clients do. We also add the older-style ids for compatibility.
|
|
340
|
+
location: locationObj,
|
|
341
|
+
venue_id: locationObj.facebook_places_id,
|
|
342
|
+
item_id: locationObj.facebook_places_id,
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
this.enhancedDebug(`✅ Location payload published via MQTT (may still be rejected server-side).`);
|
|
347
|
+
return result;
|
|
348
|
+
} catch (err) {
|
|
349
|
+
this.enhancedDebug(`Location publish failed: ${err && err.message ? err.message : String(err)} - falling back to link`);
|
|
350
|
+
// fallthrough to fallback below
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Fallback: send as a link to the location explore page (guaranteed to render in DM)
|
|
355
|
+
if (hasId) {
|
|
356
|
+
// prefer facebook_places_id if provided
|
|
357
|
+
const placeId = venue.facebook_places_id || venue.id;
|
|
358
|
+
const link = `https://www.instagram.com/explore/locations/${placeId}/`;
|
|
359
|
+
this.enhancedDebug(`Sending location fallback link: ${link}`);
|
|
360
|
+
|
|
361
|
+
try {
|
|
362
|
+
const fallback = await this.sendItem({
|
|
363
|
+
itemType: 'link',
|
|
364
|
+
threadId,
|
|
365
|
+
clientContext: clientContext || (0, uuid_1.v4)(),
|
|
366
|
+
data: {
|
|
367
|
+
link_text: text || (venue && venue.name) || 'Location',
|
|
368
|
+
link_urls: [link],
|
|
369
|
+
},
|
|
370
|
+
});
|
|
371
|
+
this.enhancedDebug(`✅ Location fallback link sent via MQTT!`);
|
|
372
|
+
return fallback;
|
|
373
|
+
} catch (err) {
|
|
374
|
+
this.enhancedDebug(`Fallback link send failed: ${err && err.message ? err.message : String(err)}`);
|
|
375
|
+
throw err;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// If we don't have any usable info, throw an error
|
|
380
|
+
throw new Error('sendLocation requires a venue object with at least id (or facebook_places_id) and lat/lng to send a native location. Without that, nothing can be sent.');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Helper: search places via the Instagram client (optional).
|
|
385
|
+
* If your realtimeClient has an .ig.request helper, this will call the appropriate
|
|
386
|
+
* endpoint to fetch place metadata, and then call sendLocation with the full venue.
|
|
387
|
+
*
|
|
388
|
+
* This is optional — you can call sendLocation yourself with the venue object you already have.
|
|
389
|
+
*/
|
|
390
|
+
async searchAndSendLocation({ threadId, query, lat, lng, clientContext }) {
|
|
391
|
+
const ig = this.realtimeClient && this.realtimeClient.ig;
|
|
392
|
+
if (!ig || !ig.request) {
|
|
393
|
+
throw new Error('Instagram client (ig.request) not available on realtimeClient. Provide `venue` directly to sendLocation instead.');
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
this.enhancedDebug(`Searching location: ${query} at ${lat},${lng}`);
|
|
397
|
+
|
|
398
|
+
// Example endpoint - private API endpoints vary. If your client has a helper method,
|
|
399
|
+
// prefer that. This tries a common private endpoint pattern.
|
|
400
|
+
const url = '/fbsearch/places/';
|
|
401
|
+
const params = {
|
|
402
|
+
search_media_creation: false,
|
|
403
|
+
rank_token: (0, uuid_1.v4)(),
|
|
404
|
+
query: query,
|
|
405
|
+
latitude: lat,
|
|
406
|
+
longitude: lng,
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
try {
|
|
410
|
+
const res = await ig.request.send({
|
|
411
|
+
url: url,
|
|
412
|
+
method: 'GET',
|
|
413
|
+
qs: params,
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// Parse response - different private API clients return different shapes.
|
|
417
|
+
// We try to find the first usable place with id/lat/lng/name.
|
|
418
|
+
const places = (res && (res.places || res.items || res.results)) || [];
|
|
419
|
+
const place = places.find(p => p && (p.pk || p.place || p.location || p.facebook_places_id)) || places[0];
|
|
420
|
+
|
|
421
|
+
if (!place) {
|
|
422
|
+
throw new Error('No places found from search.');
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Normalize to `venue` shape our sendLocation expects
|
|
426
|
+
const venue = {
|
|
427
|
+
id: String(place.pk || (place.place && place.place.id) || place.id || place.facebook_places_id || ''),
|
|
428
|
+
name: place.name || (place.place && place.place.name) || '',
|
|
429
|
+
address: place.address || (place.place && place.place.address) || '',
|
|
430
|
+
lat: (place.location && (place.location.lat || place.location.latitude)) || place.lat || null,
|
|
431
|
+
lng: (place.location && (place.location.lng || place.location.longitude)) || place.lng || null,
|
|
432
|
+
facebook_places_id: place.facebook_places_id || (place.place && place.place.id) || String(place.pk || ''),
|
|
433
|
+
external_source: place.external_source || 'facebook_places',
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
return await this.sendLocation({ threadId, clientContext, venue });
|
|
437
|
+
} catch (err) {
|
|
438
|
+
this.enhancedDebug(`place search/send failed: ${err && err.message ? err.message : String(err)}`);
|
|
439
|
+
throw err;
|
|
440
|
+
}
|
|
300
441
|
}
|
|
301
442
|
|
|
302
443
|
/**
|
|
303
|
-
* Send media via MQTT (
|
|
444
|
+
* Send media via MQTT (media_share)
|
|
304
445
|
*/
|
|
305
446
|
async sendMedia({ text, mediaId, threadId, clientContext }) {
|
|
306
447
|
this.enhancedDebug(`Sending media ${mediaId} to ${threadId}`);
|
|
307
|
-
|
|
448
|
+
|
|
308
449
|
const result = await this.sendItem({
|
|
309
450
|
itemType: 'media_share',
|
|
310
451
|
threadId,
|
|
@@ -314,17 +455,17 @@ class EnhancedDirectCommands {
|
|
|
314
455
|
media_id: mediaId,
|
|
315
456
|
},
|
|
316
457
|
});
|
|
317
|
-
|
|
458
|
+
|
|
318
459
|
this.enhancedDebug(`✅ Media sent via MQTT!`);
|
|
319
460
|
return result;
|
|
320
461
|
}
|
|
321
462
|
|
|
322
463
|
/**
|
|
323
|
-
* Send profile via MQTT
|
|
464
|
+
* Send profile via MQTT
|
|
324
465
|
*/
|
|
325
466
|
async sendProfile({ text, userId, threadId, clientContext }) {
|
|
326
467
|
this.enhancedDebug(`Sending profile ${userId} to ${threadId}`);
|
|
327
|
-
|
|
468
|
+
|
|
328
469
|
const result = await this.sendItem({
|
|
329
470
|
itemType: 'profile',
|
|
330
471
|
threadId,
|
|
@@ -335,17 +476,17 @@ class EnhancedDirectCommands {
|
|
|
335
476
|
item_id: userId,
|
|
336
477
|
},
|
|
337
478
|
});
|
|
338
|
-
|
|
479
|
+
|
|
339
480
|
this.enhancedDebug(`✅ Profile sent via MQTT!`);
|
|
340
481
|
return result;
|
|
341
482
|
}
|
|
342
483
|
|
|
343
484
|
/**
|
|
344
|
-
* Send reaction via MQTT
|
|
485
|
+
* Send reaction via MQTT
|
|
345
486
|
*/
|
|
346
487
|
async sendReaction({ itemId, reactionType, clientContext, threadId, reactionStatus, targetItemType, emoji }) {
|
|
347
488
|
this.enhancedDebug(`Sending ${reactionType || 'like'} reaction to message ${itemId}`);
|
|
348
|
-
|
|
489
|
+
|
|
349
490
|
const result = await this.sendItem({
|
|
350
491
|
itemType: 'reaction',
|
|
351
492
|
threadId,
|
|
@@ -359,17 +500,17 @@ class EnhancedDirectCommands {
|
|
|
359
500
|
emoji: emoji || '',
|
|
360
501
|
},
|
|
361
502
|
});
|
|
362
|
-
|
|
503
|
+
|
|
363
504
|
this.enhancedDebug(`✅ Reaction sent via MQTT!`);
|
|
364
505
|
return result;
|
|
365
506
|
}
|
|
366
507
|
|
|
367
508
|
/**
|
|
368
|
-
* Send user story via MQTT (
|
|
509
|
+
* Send user story via MQTT (reel_share)
|
|
369
510
|
*/
|
|
370
511
|
async sendUserStory({ text, storyId, threadId, clientContext }) {
|
|
371
512
|
this.enhancedDebug(`Sending story ${storyId} to ${threadId}`);
|
|
372
|
-
|
|
513
|
+
|
|
373
514
|
const result = await this.sendItem({
|
|
374
515
|
itemType: 'reel_share',
|
|
375
516
|
threadId,
|
|
@@ -380,17 +521,17 @@ class EnhancedDirectCommands {
|
|
|
380
521
|
media_id: storyId,
|
|
381
522
|
},
|
|
382
523
|
});
|
|
383
|
-
|
|
524
|
+
|
|
384
525
|
this.enhancedDebug(`✅ Story sent via MQTT!`);
|
|
385
526
|
return result;
|
|
386
527
|
}
|
|
387
528
|
|
|
388
529
|
/**
|
|
389
|
-
* Mark as seen via MQTT (
|
|
530
|
+
* Mark as seen via MQTT (mark_seen action)
|
|
390
531
|
*/
|
|
391
532
|
async markAsSeen({ threadId, itemId }) {
|
|
392
533
|
this.enhancedDebug(`Marking message ${itemId} as seen in thread ${threadId}`);
|
|
393
|
-
|
|
534
|
+
|
|
394
535
|
const result = await this.sendCommand({
|
|
395
536
|
action: 'mark_seen',
|
|
396
537
|
threadId,
|
|
@@ -398,18 +539,18 @@ class EnhancedDirectCommands {
|
|
|
398
539
|
item_id: itemId,
|
|
399
540
|
},
|
|
400
541
|
});
|
|
401
|
-
|
|
542
|
+
|
|
402
543
|
this.enhancedDebug(`✅ Message marked as seen via MQTT!`);
|
|
403
544
|
return result;
|
|
404
545
|
}
|
|
405
546
|
|
|
406
547
|
/**
|
|
407
|
-
* Indicate activity (typing) via MQTT (
|
|
548
|
+
* Indicate activity (typing) via MQTT (activity_status)
|
|
408
549
|
*/
|
|
409
550
|
async indicateActivity({ threadId, isActive, clientContext }) {
|
|
410
551
|
const active = typeof isActive === 'undefined' ? true : isActive;
|
|
411
552
|
this.enhancedDebug(`Indicating ${active ? 'typing' : 'stopped'} in thread ${threadId}`);
|
|
412
|
-
|
|
553
|
+
|
|
413
554
|
const result = await this.sendCommand({
|
|
414
555
|
action: 'indicate_activity',
|
|
415
556
|
threadId,
|
|
@@ -418,7 +559,7 @@ class EnhancedDirectCommands {
|
|
|
418
559
|
activity_status: active ? '1' : '0',
|
|
419
560
|
},
|
|
420
561
|
});
|
|
421
|
-
|
|
562
|
+
|
|
422
563
|
this.enhancedDebug(`✅ Activity indicator sent via MQTT!`);
|
|
423
564
|
return result;
|
|
424
565
|
}
|
|
@@ -428,7 +569,7 @@ class EnhancedDirectCommands {
|
|
|
428
569
|
*/
|
|
429
570
|
async deleteMessage(threadId, itemId) {
|
|
430
571
|
this.enhancedDebug(`Deleting message ${itemId} from thread ${threadId}`);
|
|
431
|
-
|
|
572
|
+
|
|
432
573
|
const result = await this.sendCommand({
|
|
433
574
|
action: 'delete_item',
|
|
434
575
|
threadId,
|
|
@@ -437,7 +578,7 @@ class EnhancedDirectCommands {
|
|
|
437
578
|
item_id: itemId,
|
|
438
579
|
},
|
|
439
580
|
});
|
|
440
|
-
|
|
581
|
+
|
|
441
582
|
this.enhancedDebug(`✅ Message deleted via MQTT!`);
|
|
442
583
|
return result;
|
|
443
584
|
}
|
|
@@ -447,7 +588,7 @@ class EnhancedDirectCommands {
|
|
|
447
588
|
*/
|
|
448
589
|
async editMessage(threadId, itemId, newText) {
|
|
449
590
|
this.enhancedDebug(`Editing message ${itemId}: "${newText}"`);
|
|
450
|
-
|
|
591
|
+
|
|
451
592
|
const result = await this.sendCommand({
|
|
452
593
|
action: 'edit_item',
|
|
453
594
|
threadId,
|
|
@@ -457,7 +598,7 @@ class EnhancedDirectCommands {
|
|
|
457
598
|
text: newText,
|
|
458
599
|
},
|
|
459
600
|
});
|
|
460
|
-
|
|
601
|
+
|
|
461
602
|
this.enhancedDebug(`✅ Message edited via MQTT!`);
|
|
462
603
|
return result;
|
|
463
604
|
}
|
|
@@ -467,7 +608,7 @@ class EnhancedDirectCommands {
|
|
|
467
608
|
*/
|
|
468
609
|
async replyToMessage(threadId, messageId, replyText) {
|
|
469
610
|
this.enhancedDebug(`Replying to ${messageId} in thread ${threadId}: "${replyText}"`);
|
|
470
|
-
|
|
611
|
+
|
|
471
612
|
const result = await this.sendItem({
|
|
472
613
|
itemType: 'text',
|
|
473
614
|
threadId,
|
|
@@ -477,7 +618,7 @@ class EnhancedDirectCommands {
|
|
|
477
618
|
replied_to_item_id: messageId,
|
|
478
619
|
},
|
|
479
620
|
});
|
|
480
|
-
|
|
621
|
+
|
|
481
622
|
this.enhancedDebug(`✅ Reply sent via MQTT!`);
|
|
482
623
|
return result;
|
|
483
624
|
}
|
|
@@ -487,7 +628,7 @@ class EnhancedDirectCommands {
|
|
|
487
628
|
*/
|
|
488
629
|
async addMemberToThread(threadId, userId) {
|
|
489
630
|
this.enhancedDebug(`Adding user ${userId} to thread ${threadId}`);
|
|
490
|
-
|
|
631
|
+
|
|
491
632
|
const result = await this.sendCommand({
|
|
492
633
|
action: 'add_users',
|
|
493
634
|
threadId,
|
|
@@ -496,7 +637,7 @@ class EnhancedDirectCommands {
|
|
|
496
637
|
user_ids: Array.isArray(userId) ? userId : [userId],
|
|
497
638
|
},
|
|
498
639
|
});
|
|
499
|
-
|
|
640
|
+
|
|
500
641
|
this.enhancedDebug(`✅ Member added to thread via MQTT!`);
|
|
501
642
|
return result;
|
|
502
643
|
}
|
|
@@ -506,7 +647,7 @@ class EnhancedDirectCommands {
|
|
|
506
647
|
*/
|
|
507
648
|
async removeMemberFromThread(threadId, userId) {
|
|
508
649
|
this.enhancedDebug(`Removing user ${userId} from thread ${threadId}`);
|
|
509
|
-
|
|
650
|
+
|
|
510
651
|
const result = await this.sendCommand({
|
|
511
652
|
action: 'remove_users',
|
|
512
653
|
threadId,
|
|
@@ -515,7 +656,7 @@ class EnhancedDirectCommands {
|
|
|
515
656
|
user_ids: Array.isArray(userId) ? userId : [userId],
|
|
516
657
|
},
|
|
517
658
|
});
|
|
518
|
-
|
|
659
|
+
|
|
519
660
|
this.enhancedDebug(`✅ Member removed from thread via MQTT!`);
|
|
520
661
|
return result;
|
|
521
662
|
}
|
|
@@ -525,14 +666,14 @@ class EnhancedDirectCommands {
|
|
|
525
666
|
*/
|
|
526
667
|
async leaveThread(threadId) {
|
|
527
668
|
this.enhancedDebug(`Leaving thread ${threadId}`);
|
|
528
|
-
|
|
669
|
+
|
|
529
670
|
const result = await this.sendCommand({
|
|
530
671
|
action: 'leave',
|
|
531
672
|
threadId,
|
|
532
673
|
clientContext: (0, uuid_1.v4)(),
|
|
533
674
|
data: {},
|
|
534
675
|
});
|
|
535
|
-
|
|
676
|
+
|
|
536
677
|
this.enhancedDebug(`✅ Left thread via MQTT!`);
|
|
537
678
|
return result;
|
|
538
679
|
}
|
|
@@ -542,7 +683,7 @@ class EnhancedDirectCommands {
|
|
|
542
683
|
*/
|
|
543
684
|
async muteThread(threadId, muteUntil = null) {
|
|
544
685
|
this.enhancedDebug(`Muting thread ${threadId}`);
|
|
545
|
-
|
|
686
|
+
|
|
546
687
|
const result = await this.sendCommand({
|
|
547
688
|
action: 'mute',
|
|
548
689
|
threadId,
|
|
@@ -551,7 +692,7 @@ class EnhancedDirectCommands {
|
|
|
551
692
|
mute_until: muteUntil,
|
|
552
693
|
},
|
|
553
694
|
});
|
|
554
|
-
|
|
695
|
+
|
|
555
696
|
this.enhancedDebug(`✅ Thread muted via MQTT!`);
|
|
556
697
|
return result;
|
|
557
698
|
}
|
|
@@ -561,14 +702,14 @@ class EnhancedDirectCommands {
|
|
|
561
702
|
*/
|
|
562
703
|
async unmuteThread(threadId) {
|
|
563
704
|
this.enhancedDebug(`Unmuting thread ${threadId}`);
|
|
564
|
-
|
|
705
|
+
|
|
565
706
|
const result = await this.sendCommand({
|
|
566
707
|
action: 'unmute',
|
|
567
708
|
threadId,
|
|
568
709
|
clientContext: (0, uuid_1.v4)(),
|
|
569
710
|
data: {},
|
|
570
711
|
});
|
|
571
|
-
|
|
712
|
+
|
|
572
713
|
this.enhancedDebug(`✅ Thread unmuted via MQTT!`);
|
|
573
714
|
return result;
|
|
574
715
|
}
|
|
@@ -578,7 +719,7 @@ class EnhancedDirectCommands {
|
|
|
578
719
|
*/
|
|
579
720
|
async updateThreadTitle(threadId, title) {
|
|
580
721
|
this.enhancedDebug(`Updating thread ${threadId} title to: "${title}"`);
|
|
581
|
-
|
|
722
|
+
|
|
582
723
|
const result = await this.sendCommand({
|
|
583
724
|
action: 'update_title',
|
|
584
725
|
threadId,
|
|
@@ -587,7 +728,7 @@ class EnhancedDirectCommands {
|
|
|
587
728
|
title: title,
|
|
588
729
|
},
|
|
589
730
|
});
|
|
590
|
-
|
|
731
|
+
|
|
591
732
|
this.enhancedDebug(`✅ Thread title updated via MQTT!`);
|
|
592
733
|
return result;
|
|
593
734
|
}
|
|
@@ -597,7 +738,7 @@ class EnhancedDirectCommands {
|
|
|
597
738
|
*/
|
|
598
739
|
async sendLink({ link, text, threadId, clientContext }) {
|
|
599
740
|
this.enhancedDebug(`Sending link ${link} to ${threadId}`);
|
|
600
|
-
|
|
741
|
+
|
|
601
742
|
const result = await this.sendItem({
|
|
602
743
|
itemType: 'link',
|
|
603
744
|
threadId,
|
|
@@ -608,7 +749,7 @@ class EnhancedDirectCommands {
|
|
|
608
749
|
link_urls: [link],
|
|
609
750
|
},
|
|
610
751
|
});
|
|
611
|
-
|
|
752
|
+
|
|
612
753
|
this.enhancedDebug(`✅ Link sent via MQTT!`);
|
|
613
754
|
return result;
|
|
614
755
|
}
|
|
@@ -618,7 +759,7 @@ class EnhancedDirectCommands {
|
|
|
618
759
|
*/
|
|
619
760
|
async sendAnimatedMedia({ id, isSticker, threadId, clientContext }) {
|
|
620
761
|
this.enhancedDebug(`Sending animated media ${id} to ${threadId}`);
|
|
621
|
-
|
|
762
|
+
|
|
622
763
|
const result = await this.sendItem({
|
|
623
764
|
itemType: 'animated_media',
|
|
624
765
|
threadId,
|
|
@@ -628,7 +769,7 @@ class EnhancedDirectCommands {
|
|
|
628
769
|
is_sticker: isSticker || false,
|
|
629
770
|
},
|
|
630
771
|
});
|
|
631
|
-
|
|
772
|
+
|
|
632
773
|
this.enhancedDebug(`✅ Animated media sent via MQTT!`);
|
|
633
774
|
return result;
|
|
634
775
|
}
|
|
@@ -638,7 +779,7 @@ class EnhancedDirectCommands {
|
|
|
638
779
|
*/
|
|
639
780
|
async sendVoice({ uploadId, waveform, waveformSamplingFrequencyHz, threadId, clientContext }) {
|
|
640
781
|
this.enhancedDebug(`Sending voice ${uploadId} to ${threadId}`);
|
|
641
|
-
|
|
782
|
+
|
|
642
783
|
const result = await this.sendItem({
|
|
643
784
|
itemType: 'voice_media',
|
|
644
785
|
threadId,
|
|
@@ -649,17 +790,18 @@ class EnhancedDirectCommands {
|
|
|
649
790
|
waveform_sampling_frequency_hz: waveformSamplingFrequencyHz || 10,
|
|
650
791
|
},
|
|
651
792
|
});
|
|
652
|
-
|
|
793
|
+
|
|
653
794
|
this.enhancedDebug(`✅ Voice sent via MQTT!`);
|
|
654
795
|
return result;
|
|
655
796
|
}
|
|
656
797
|
|
|
657
798
|
/**
|
|
658
799
|
* Send photo via Realtime (Upload + Broadcast)
|
|
800
|
+
* Note: depends on realtimeClient.ig.request for uploading
|
|
659
801
|
*/
|
|
660
802
|
async sendPhotoViaRealtime({ photoBuffer, threadId, caption = '', mimeType = 'image/jpeg', clientContext }) {
|
|
661
803
|
this.enhancedDebug(`Sending photo to thread ${threadId} via Realtime`);
|
|
662
|
-
|
|
804
|
+
|
|
663
805
|
try {
|
|
664
806
|
if (!photoBuffer || !Buffer.isBuffer(photoBuffer) || photoBuffer.length === 0) {
|
|
665
807
|
throw new Error('photoBuffer must be a non-empty Buffer');
|
|
@@ -674,10 +816,10 @@ class EnhancedDirectCommands {
|
|
|
674
816
|
}
|
|
675
817
|
|
|
676
818
|
this.enhancedDebug(`Step 1: Uploading photo (${photoBuffer.length} bytes)...`);
|
|
677
|
-
|
|
819
|
+
|
|
678
820
|
const uploadId = Date.now().toString();
|
|
679
821
|
const objectName = `${(0, uuid_1.v4)()}.${mimeType === 'image/png' ? 'png' : 'jpg'}`;
|
|
680
|
-
|
|
822
|
+
|
|
681
823
|
const isJpeg = mimeType === 'image/jpeg' || mimeType === 'image/jpg';
|
|
682
824
|
const compression = isJpeg
|
|
683
825
|
? '{"lib_name":"moz","lib_version":"3.1.m","quality":"80"}'
|
|
@@ -721,7 +863,7 @@ class EnhancedDirectCommands {
|
|
|
721
863
|
}
|
|
722
864
|
|
|
723
865
|
this.enhancedDebug(`Step 2: Broadcasting photo to thread ${threadId}...`);
|
|
724
|
-
|
|
866
|
+
|
|
725
867
|
const broadcastForm = {
|
|
726
868
|
upload_id: serverUploadId,
|
|
727
869
|
action: 'send_item',
|
|
@@ -761,10 +903,11 @@ class EnhancedDirectCommands {
|
|
|
761
903
|
|
|
762
904
|
/**
|
|
763
905
|
* Send video via Realtime (Upload + Broadcast)
|
|
906
|
+
* Note: depends on realtimeClient.ig.request for uploading
|
|
764
907
|
*/
|
|
765
908
|
async sendVideoViaRealtime({ videoBuffer, threadId, caption = '', duration = 0, width = 720, height = 1280, clientContext }) {
|
|
766
909
|
this.enhancedDebug(`Sending video to thread ${threadId} via Realtime`);
|
|
767
|
-
|
|
910
|
+
|
|
768
911
|
try {
|
|
769
912
|
if (!videoBuffer || !Buffer.isBuffer(videoBuffer) || videoBuffer.length === 0) {
|
|
770
913
|
throw new Error('videoBuffer must be a non-empty Buffer');
|
|
@@ -779,10 +922,10 @@ class EnhancedDirectCommands {
|
|
|
779
922
|
}
|
|
780
923
|
|
|
781
924
|
this.enhancedDebug(`Step 1: Uploading video (${videoBuffer.length} bytes)...`);
|
|
782
|
-
|
|
925
|
+
|
|
783
926
|
const uploadId = Date.now().toString();
|
|
784
927
|
const objectName = `${(0, uuid_1.v4)()}.mp4`;
|
|
785
|
-
|
|
928
|
+
|
|
786
929
|
const ruploadParams = {
|
|
787
930
|
upload_id: uploadId,
|
|
788
931
|
media_type: 2,
|
|
@@ -823,7 +966,7 @@ class EnhancedDirectCommands {
|
|
|
823
966
|
}
|
|
824
967
|
|
|
825
968
|
this.enhancedDebug(`Step 2: Broadcasting video to thread ${threadId}...`);
|
|
826
|
-
|
|
969
|
+
|
|
827
970
|
const broadcastForm = {
|
|
828
971
|
upload_id: serverUploadId,
|
|
829
972
|
action: 'send_item',
|
|
@@ -867,14 +1010,14 @@ class EnhancedDirectCommands {
|
|
|
867
1010
|
*/
|
|
868
1011
|
async approveThread(threadId) {
|
|
869
1012
|
this.enhancedDebug(`Approving thread ${threadId}`);
|
|
870
|
-
|
|
1013
|
+
|
|
871
1014
|
const result = await this.sendCommand({
|
|
872
1015
|
action: 'approve',
|
|
873
1016
|
threadId,
|
|
874
1017
|
clientContext: (0, uuid_1.v4)(),
|
|
875
1018
|
data: {},
|
|
876
1019
|
});
|
|
877
|
-
|
|
1020
|
+
|
|
878
1021
|
this.enhancedDebug(`✅ Thread approved via MQTT!`);
|
|
879
1022
|
return result;
|
|
880
1023
|
}
|
|
@@ -884,14 +1027,14 @@ class EnhancedDirectCommands {
|
|
|
884
1027
|
*/
|
|
885
1028
|
async declineThread(threadId) {
|
|
886
1029
|
this.enhancedDebug(`Declining thread ${threadId}`);
|
|
887
|
-
|
|
1030
|
+
|
|
888
1031
|
const result = await this.sendCommand({
|
|
889
1032
|
action: 'decline',
|
|
890
1033
|
threadId,
|
|
891
1034
|
clientContext: (0, uuid_1.v4)(),
|
|
892
1035
|
data: {},
|
|
893
1036
|
});
|
|
894
|
-
|
|
1037
|
+
|
|
895
1038
|
this.enhancedDebug(`✅ Thread declined via MQTT!`);
|
|
896
1039
|
return result;
|
|
897
1040
|
}
|
|
@@ -901,7 +1044,7 @@ class EnhancedDirectCommands {
|
|
|
901
1044
|
*/
|
|
902
1045
|
async blockUserInThread(threadId, userId) {
|
|
903
1046
|
this.enhancedDebug(`Blocking user ${userId} in thread ${threadId}`);
|
|
904
|
-
|
|
1047
|
+
|
|
905
1048
|
const result = await this.sendCommand({
|
|
906
1049
|
action: 'block',
|
|
907
1050
|
threadId,
|
|
@@ -910,7 +1053,7 @@ class EnhancedDirectCommands {
|
|
|
910
1053
|
user_id: userId,
|
|
911
1054
|
},
|
|
912
1055
|
});
|
|
913
|
-
|
|
1056
|
+
|
|
914
1057
|
this.enhancedDebug(`✅ User blocked in thread via MQTT!`);
|
|
915
1058
|
return result;
|
|
916
1059
|
}
|
|
@@ -920,7 +1063,7 @@ class EnhancedDirectCommands {
|
|
|
920
1063
|
*/
|
|
921
1064
|
async reportThread(threadId, reason) {
|
|
922
1065
|
this.enhancedDebug(`Reporting thread ${threadId}`);
|
|
923
|
-
|
|
1066
|
+
|
|
924
1067
|
const result = await this.sendCommand({
|
|
925
1068
|
action: 'report',
|
|
926
1069
|
threadId,
|
|
@@ -929,7 +1072,7 @@ class EnhancedDirectCommands {
|
|
|
929
1072
|
reason: reason || 'spam',
|
|
930
1073
|
},
|
|
931
1074
|
});
|
|
932
|
-
|
|
1075
|
+
|
|
933
1076
|
this.enhancedDebug(`✅ Thread reported via MQTT!`);
|
|
934
1077
|
return result;
|
|
935
1078
|
}
|
|
@@ -939,7 +1082,7 @@ class EnhancedDirectCommands {
|
|
|
939
1082
|
*/
|
|
940
1083
|
async removeReaction({ itemId, threadId, clientContext }) {
|
|
941
1084
|
this.enhancedDebug(`Removing reaction from message ${itemId}`);
|
|
942
|
-
|
|
1085
|
+
|
|
943
1086
|
const result = await this.sendItem({
|
|
944
1087
|
itemType: 'reaction',
|
|
945
1088
|
threadId,
|
|
@@ -951,7 +1094,7 @@ class EnhancedDirectCommands {
|
|
|
951
1094
|
reaction_status: 'deleted',
|
|
952
1095
|
},
|
|
953
1096
|
});
|
|
954
|
-
|
|
1097
|
+
|
|
955
1098
|
this.enhancedDebug(`✅ Reaction removed via MQTT!`);
|
|
956
1099
|
return result;
|
|
957
1100
|
}
|
|
@@ -961,7 +1104,7 @@ class EnhancedDirectCommands {
|
|
|
961
1104
|
*/
|
|
962
1105
|
async sendDisappearingPhoto({ uploadId, threadId, viewMode = 'once', clientContext }) {
|
|
963
1106
|
this.enhancedDebug(`Sending disappearing photo to ${threadId}`);
|
|
964
|
-
|
|
1107
|
+
|
|
965
1108
|
const result = await this.sendItem({
|
|
966
1109
|
itemType: 'expiring_media_message',
|
|
967
1110
|
threadId,
|
|
@@ -972,7 +1115,7 @@ class EnhancedDirectCommands {
|
|
|
972
1115
|
allow_replay: viewMode === 'replayable',
|
|
973
1116
|
},
|
|
974
1117
|
});
|
|
975
|
-
|
|
1118
|
+
|
|
976
1119
|
this.enhancedDebug(`✅ Disappearing photo sent via MQTT!`);
|
|
977
1120
|
return result;
|
|
978
1121
|
}
|
|
@@ -982,7 +1125,7 @@ class EnhancedDirectCommands {
|
|
|
982
1125
|
*/
|
|
983
1126
|
async sendDisappearingVideo({ uploadId, threadId, viewMode = 'once', clientContext }) {
|
|
984
1127
|
this.enhancedDebug(`Sending disappearing video to ${threadId}`);
|
|
985
|
-
|
|
1128
|
+
|
|
986
1129
|
const result = await this.sendItem({
|
|
987
1130
|
itemType: 'expiring_media_message',
|
|
988
1131
|
threadId,
|
|
@@ -994,7 +1137,7 @@ class EnhancedDirectCommands {
|
|
|
994
1137
|
media_type: 2,
|
|
995
1138
|
},
|
|
996
1139
|
});
|
|
997
|
-
|
|
1140
|
+
|
|
998
1141
|
this.enhancedDebug(`✅ Disappearing video sent via MQTT!`);
|
|
999
1142
|
return result;
|
|
1000
1143
|
}
|
|
@@ -1004,7 +1147,7 @@ class EnhancedDirectCommands {
|
|
|
1004
1147
|
*/
|
|
1005
1148
|
async markVisualMessageSeen({ threadId, itemId, clientContext }) {
|
|
1006
1149
|
this.enhancedDebug(`Marking visual message ${itemId} as seen`);
|
|
1007
|
-
|
|
1150
|
+
|
|
1008
1151
|
const result = await this.sendCommand({
|
|
1009
1152
|
action: 'mark_visual_item_seen',
|
|
1010
1153
|
threadId,
|
|
@@ -1013,7 +1156,7 @@ class EnhancedDirectCommands {
|
|
|
1013
1156
|
item_id: itemId,
|
|
1014
1157
|
},
|
|
1015
1158
|
});
|
|
1016
|
-
|
|
1159
|
+
|
|
1017
1160
|
this.enhancedDebug(`✅ Visual message marked as seen via MQTT!`);
|
|
1018
1161
|
return result;
|
|
1019
1162
|
}
|
|
@@ -1023,7 +1166,7 @@ class EnhancedDirectCommands {
|
|
|
1023
1166
|
*/
|
|
1024
1167
|
async sendScreenshotNotification({ threadId, itemId, clientContext }) {
|
|
1025
1168
|
this.enhancedDebug(`Sending screenshot notification for ${itemId}`);
|
|
1026
|
-
|
|
1169
|
+
|
|
1027
1170
|
const result = await this.sendCommand({
|
|
1028
1171
|
action: 'screenshot_notification',
|
|
1029
1172
|
threadId,
|
|
@@ -1032,7 +1175,7 @@ class EnhancedDirectCommands {
|
|
|
1032
1175
|
item_id: itemId,
|
|
1033
1176
|
},
|
|
1034
1177
|
});
|
|
1035
|
-
|
|
1178
|
+
|
|
1036
1179
|
this.enhancedDebug(`✅ Screenshot notification sent via MQTT!`);
|
|
1037
1180
|
return result;
|
|
1038
1181
|
}
|
|
@@ -1042,7 +1185,7 @@ class EnhancedDirectCommands {
|
|
|
1042
1185
|
*/
|
|
1043
1186
|
async sendReplayNotification({ threadId, itemId, clientContext }) {
|
|
1044
1187
|
this.enhancedDebug(`Sending replay notification for ${itemId}`);
|
|
1045
|
-
|
|
1188
|
+
|
|
1046
1189
|
const result = await this.sendCommand({
|
|
1047
1190
|
action: 'replay_notification',
|
|
1048
1191
|
threadId,
|
|
@@ -1051,9 +1194,10 @@ class EnhancedDirectCommands {
|
|
|
1051
1194
|
item_id: itemId,
|
|
1052
1195
|
},
|
|
1053
1196
|
});
|
|
1054
|
-
|
|
1197
|
+
|
|
1055
1198
|
this.enhancedDebug(`✅ Replay notification sent via MQTT!`);
|
|
1056
1199
|
return result;
|
|
1057
1200
|
}
|
|
1058
1201
|
}
|
|
1059
|
-
|
|
1202
|
+
|
|
1203
|
+
exports.EnhancedDirectCommands = EnhancedDirectCommands;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodejs-insta-private-api-mqtt",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.41",
|
|
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": {
|